add support for Windows

This commit is contained in:
Ramen2X 2024-12-26 18:44:45 -05:00
parent eb3be12f7c
commit c0242c7125
4 changed files with 90 additions and 14 deletions

View file

@ -19,6 +19,10 @@ target_include_directories(actionheadergen PRIVATE
target_link_libraries(actionheadergen PRIVATE libweaver)
if (WIN32)
target_link_libraries(actionheadergen PRIVATE shlwapi)
endif()
set_target_properties(actionheadergen PROPERTIES
CXX_STANDARD 98
CXX_STANDARD_REQUIRED ON

View file

@ -28,7 +28,7 @@ Some creative liberties possibly not present in the original codebase have been
This project uses the CMake build system. As this project makes use of [libweaver](https://github.com/isledecomp/SIEdit), you will need to pull the source recursively.
The code in this repository should be cross-platform, aside from the use of dirent. Dirent has third party implementations on Windows that this project should build fine with, but a native recursive file search function using the WinAPI is still needed to eliminate this edge-case.
The code in this repository is cross-platform and should build for Windows, macOS, and Linux. Additionally, it is C++98 compliant.
## Usage

View file

@ -1,4 +1,5 @@
#include <ctype.h>
#include <string.h>
#include "headergenerator.h"
@ -20,7 +21,7 @@ bool HeaderGenerator::CreateForwardDeclHeader(char *p_outputDir)
{
// attempt to create special forward decl header
if (!CreateHeader("", p_outputDir)) {
printf("Failed to create forward declaration header, check file permissions?\n");
printf("Failed to create forward declaration header, check file permissions or ensure output directory exists\n");
return false;
}
return true;
@ -30,7 +31,7 @@ bool HeaderGenerator::GenerateHeader(char *p_interleafName, std::map<size_t, std
{
// attempt to create header file
if (!CreateHeader(p_interleafName, p_outputDir)) {
printf("Failed to create Interleaf header, check file permissions?\n");
printf("Failed to create Interleaf header, check file permissions or ensure output directory exists\n");
return false;
}

View file

@ -1,16 +1,83 @@
#include <dirent.h>
#include <stdio.h>
#include <string>
#include "headergenerator.h"
#include "interleafhandler.h"
bool RecursivelyFindInterleaf(const char *p_path, std::vector<std::string> &p_interleafFiles)
#ifdef _WIN32
#include <shlwapi.h>
#include <windows.h>
#define strcasecmp _stricmp
#undef ERROR_SUCCESS
#else
#include <dirent.h>
#endif
#include <stdio.h>
#include <string>
bool RecursivelyFindInterleaf(const char* p_path, std::vector<std::string>& p_interleafFiles)
{
// TODO: *by default* this is a UNIX-specific solution
// Windows is capable of using dirent through third party implementations,
// but it would be nice to have something that works out of the box on Win32
// this is one of the pains of C++98, there is no good directory support in the standard
#ifdef _WIN32
// C++98 compliant Windows implementation
HANDLE hFind;
WIN32_FIND_DATAA findData;
std::string searchPattern = std::string(p_path) + "\\*";
hFind = FindFirstFile(searchPattern.c_str(), &findData);
if (hFind == INVALID_HANDLE_VALUE)
{
printf("Could not open directory %s, exiting\n", p_path);
return false;
}
while (true)
{
// filter out backwards paths
if (strcmp(findData.cFileName, ".") == 0 || strcmp(findData.cFileName, "..") == 0)
{
if (!FindNextFileA(hFind, &findData))
{
// no more files left, exit
break;
}
continue;
}
// this is a subdirectory, so recurse
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
char nextPathBuffer[1024];
snprintf(nextPathBuffer, sizeof(nextPathBuffer), "%s\\%s", p_path, findData.cFileName);
if (!RecursivelyFindInterleaf(nextPathBuffer, p_interleafFiles))
// couldn't access this subdirectory, abort
return false;
}
else
{
// found an Interleaf file
if (StrStrI(findData.cFileName, ".si") != NULL)
{
// construct the full path to the file first
char fullPathBuffer[1024];
snprintf(fullPathBuffer, sizeof(fullPathBuffer), "%s\\%s", p_path, findData.cFileName);
// push it to the vector
p_interleafFiles.push_back(fullPathBuffer);
}
}
if (!FindNextFile(hFind, &findData))
{
// no more files left, exit
break;
}
}
// success
FindClose(hFind);
return true;
#else
// POSIX implementation using dirent
DIR *directory = opendir(p_path);
if (!directory) {
printf("Could not open directory %s, exiting\n", p_path);
@ -33,7 +100,7 @@ bool RecursivelyFindInterleaf(const char *p_path, std::vector<std::string> &p_in
return false;
}
}
}
}
else {
if (strcasestr(dentry->d_name, ".si") != NULL) {
// found an Interleaf file
@ -51,6 +118,7 @@ bool RecursivelyFindInterleaf(const char *p_path, std::vector<std::string> &p_in
// success
closedir(directory);
return true;
#endif
}
int main(int argc, char *argv[])
@ -114,7 +182,10 @@ int main(int argc, char *argv[])
// set filename to filePath without directory appended
// libweaver unfortunately doesn't provide a way to get
// the Interleaf name so we have to construct it ourselves
char *filename = strrchr(currentFilePath, '/');
char *lastIndexSlash = strrchr(currentFilePath, '/');
char *lastIndexBackslash = strrchr(currentFilePath, '\\');
char *filename = (lastIndexSlash > lastIndexBackslash) ? lastIndexSlash : lastIndexBackslash;
if (filename) {
// we don't need ".SI" for our purposes
// so just remove the last 3 characters