mirror of
https://github.com/elasota/Aerofoil.git
synced 2025-09-23 14:53:52 +00:00
Provides drop-in replacements for some functions from WindowsUnicodeToolShim and the Windows API which are used by some of the tools that come with Aerofoil, so that these tools can be built on Unix-like systems with minimal modifications to their code.
101 lines
3.0 KiB
C++
101 lines
3.0 KiB
C++
#pragma once
|
|
|
|
// This header provides POSIX-compatible versions of some functions from
|
|
// WindowsUnicodeToolShim and the Windows API.
|
|
|
|
#include <cstdio>
|
|
#include <cstdarg>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
// Linux and macOS (and probably other non-Windows systems in general) do not
|
|
// have separate file system or command line APIs for different text encodings.
|
|
// On these systems UTF-8 is commonly the system encoding and, if so, argv will
|
|
// typically be UTF-8 encoded, though it is the calling process's responsibility
|
|
// to ensure this, as argv is passed verbatim as a sequence of byte strings.
|
|
//
|
|
// Filesystems on Unix-like systems are typically encoding-unaware, in which
|
|
// case the actual encoding used should match the system encoding, or else
|
|
// manual intervention is required.
|
|
//
|
|
// On macOS, HFS+ and APFS filenames are encoded as UTF-16 and UTF-8
|
|
// respectively, and the C filesystem API accepts UTF-8 strings. There are some
|
|
// gotchas relating to Unicode normalization, where HFS+ enforces a specific
|
|
// form of normalization at the filesystem layer but APFS does not, and using
|
|
// the C API to access the filesystem may avoid automatic normalization that
|
|
// higher-level macOS API functions may perform.
|
|
//
|
|
// In summary, text encoding is still a hairy problem on every computer system,
|
|
// though on the major non-Windows systems, assuming UTF-8 encoding is
|
|
// reasonable. For now, this header simply maps the WindowsUnicodeToolShim
|
|
// functions to their regular C API counterparts.
|
|
#define toolMain main
|
|
#define fopen_utf8 fopen
|
|
#define fputs_utf8 fputs
|
|
|
|
typedef int errno_t;
|
|
|
|
inline int mkdir_utf8(const char *path)
|
|
{
|
|
return mkdir(path, 0777);
|
|
}
|
|
|
|
// These use long as the offset type, which is 64 bits on 64-bit Linux and macOS
|
|
// systems, so explicitly 64-bit variants aren't necessary. 32-bit systems are
|
|
// likely to have a 32-bit long type, but we aren't likely to deal with
|
|
// multi-gigabyte files, are we?
|
|
#define _fseeki64 fseek
|
|
#define _ftelli64 ftell
|
|
|
|
// On Windows this is supposed to call an error handler if the buffer is too
|
|
// small. I don't think this is likely to happen in Aerofoil's case, but if it
|
|
// does, this function will crash the program as a precaution.
|
|
template <size_t size> int sprintf_s
|
|
(
|
|
char (&buffer)[size],
|
|
const char *format,
|
|
...
|
|
) {
|
|
va_list ap;
|
|
|
|
va_start(ap, format);
|
|
int count = vsnprintf(buffer, size, format, ap);
|
|
va_end(ap);
|
|
|
|
if (count >= size)
|
|
exit(1);
|
|
|
|
return count;
|
|
}
|
|
|
|
inline errno_t fopen_s(FILE **pFile, const char *name, const char *mode)
|
|
{
|
|
FILE *f = fopen(name, mode);
|
|
if (!f)
|
|
{
|
|
// Error codes might not match those from Windows, but all are
|
|
// non-zero, so *detecting* an error will work fine.
|
|
return errno;
|
|
}
|
|
*pFile = f;
|
|
return 0;
|
|
}
|
|
|
|
inline void TerminateDirectoryPath(std::string &path)
|
|
{
|
|
const size_t length = path.length();
|
|
|
|
if (length == 0 || path[length - 1] != '/')
|
|
path.push_back('/');
|
|
}
|
|
|
|
void ScanDirectoryForExtension
|
|
(
|
|
std::vector<std::string> &outPaths,
|
|
const char *path,
|
|
const char *ending,
|
|
bool recursive
|
|
);
|