Skip to content

Commit

Permalink
c++17: replacing custom code with std::filesystem[::path] where feasible
Browse files Browse the repository at this point in the history
SAVENEX include files are now also treated as regular includes (WRT
include paths search)

Obsolete functions mostly pruned

The conversion to std::fs is now mostly complete, maybe a bit more of
code restructuring, adding a bit more test coverage and this should be
ready to ship.
  • Loading branch information
ped7g committed Jan 22, 2025
1 parent 6b7af42 commit f3df4db
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 155 deletions.
32 changes: 15 additions & 17 deletions sjasm/io_nex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ class SBmpFile {

~SBmpFile();
void close();
bool open(const std::filesystem::path & bmpname);
bool open(fullpath_ref_t bmpIn);
word getColor(uint32_t index);
void loadPixelData(byte* buffer);
};
Expand All @@ -297,9 +297,9 @@ void SBmpFile::close() {
palBuffer = nullptr;
}

bool SBmpFile::open(const std::filesystem::path & bmpname) {
if (!FOPEN_ISOK(bmp, bmpname, "rb")) {
Error("[SAVENEX] Error opening file", bmpname.string().c_str(), SUPPRESS);
bool SBmpFile::open(fullpath_ref_t bmpIn) {
if (!FOPEN_ISOK(bmp, bmpIn.full, "rb")) {
Error("[SAVENEX] Error opening file", bmpIn.fullStr.c_str(), SUPPRESS);
return false;
}
palBuffer = new byte[4*PALETTE_SIZE];
Expand All @@ -324,7 +324,7 @@ bool SBmpFile::open(const std::filesystem::path & bmpname) {
40 != header2Size || 1 != colorPlanes || 8 != bpp || 0 != compressionType)
{
Error("[SAVENEX] BMP file is not in expected format (uncompressed, 8bpp, 40B BITMAPINFOHEADER header)",
bmpname.string().c_str(), SUPPRESS);
bmpIn.fullStr.c_str(), SUPPRESS);
close();
return false;
}
Expand Down Expand Up @@ -624,15 +624,14 @@ static void dirNexPaletteMem() {

static void dirNexPaletteBmp() {
// ;; SAVENEX PALETTE BMP <filename>
const std::filesystem::path bmpname = GetFileName(lp);
if (bmpname.empty() || comma(lp)) {
fullpath_ref_t bmpIn = GetInputFile(lp);
if (bmpIn.full.empty() || comma(lp)) {
Error("[SAVENEX] expected syntax is BMP <filename>", bp, SUPPRESS);
return;
}
// try to open the actual BMP file
SBmpFile bmp;
bool bmpOpened = bmp.open(bmpname);
if (!bmpOpened) return;
if (!bmp.open(bmpIn)) return;
// check the palette if it was requested from this bmp and process it
dirNexPaletteBmp(bmp);
}
Expand Down Expand Up @@ -732,7 +731,7 @@ static void dirNexScreenLayer2andLowRes(EBmpType type) {

static void dirNexScreenBmp() {
// ;; SAVENEX SCREEN BMP <filename>[,<savePalette 0/1>[,<paletteOffset 0..15>]]
const std::filesystem::path bmpname = GetFileName(lp);
fullpath_ref_t bmpIn = GetInputFile(lp);
aint bmpArgs[2] = { 1, -1 };
if (comma(lp)) { // empty filename will fall here too, causing syntax error
const bool optionals[] = {false, true}; // savePalette is mandatory after comma
Expand All @@ -751,9 +750,9 @@ static void dirNexScreenBmp() {
}
// try to open the actual BMP file
SBmpFile bmp;
bool bmpOpened = bmp.open(bmpname);
bool bmpOpened = bmp.open(bmpIn);
if (bmpOpened && other == bmp.type) {
Error("[SAVENEX] BMP file is not 256x192, 128x96, 320x256 or 640x256", bmpname.string().c_str(), SUPPRESS);
Error("[SAVENEX] BMP file is not 256x192, 128x96, 320x256 or 640x256", bmpIn.fullStr.c_str(), SUPPRESS);
bmpOpened = false;
}
if (!bmpOpened) return;
Expand Down Expand Up @@ -1038,12 +1037,11 @@ static void dirNexClose() {
// update V1.3 banksOffset in case there was no bank stored at all (before appending binary data!)
nex.updateIfAheadFirstBankSave();
// read CLOSE command argument and try to append the proposed file (if some was provided)
std::filesystem::path appendName {""};
if (!SkipBlanks(lp)) appendName = GetFileName(lp);
if (appendName.has_filename()) { // some append file requested, try to copy its content at tail of NEX
fullpath_ref_t appendIn = GetInputFile(lp);
if (appendIn.full.has_filename()) { // some append file requested, try to copy its content at tail of NEX
FILE* appendF = nullptr;
if (!FOPEN_ISOK(appendF, appendName, "rb")) {
Error("[SAVENEX] Error opening append file", appendName.string().c_str(), SUPPRESS);
if (!FOPEN_ISOK(appendF, appendIn.full, "rb")) {
Error("[SAVENEX] Error opening append file", appendIn.fullStr.c_str(), SUPPRESS);
} else {
static constexpr int copyBufSize = 0x4000;
byte* copyBuffer = new byte[copyBufSize];
Expand Down
72 changes: 14 additions & 58 deletions sjasm/sjio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include <fcntl.h>

static const std::filesystem::path EMPTY_PATH{""};
static constexpr char pathBadSlash = '\\';
static constexpr char pathGoodSlash = '/';

int ListAddress;
std::vector<const char*> archivedFileNames; // archive of filename strings (Lua scripts only?)
Expand All @@ -58,37 +60,24 @@ static aint WBLength = 0;

static void CloseBreakpointsFile();

//FIXME prune these functions after everything will be refactored to GetInput/OutputFileName
static EDelimiterType delimiterOfLastFileName = DT_NONE;

// do: remember delimiter for GetDelimiterOfLastFileName, convert backslashes, prepend prefix
std::filesystem::path GetFileName(delim_string_t & str_name, const std::filesystem::path & pathPrefix) {
SJ_FixSlashes(str_name);
delimiterOfLastFileName = str_name.second; // remember delimiter for GetDelimiterOfLastFileName
// return prefixed path (or just path if prefix is empty, "/" is not applied then)
return pathPrefix / str_name.first;
}

std::filesystem::path GetFileName(char*& p, const std::filesystem::path & pathPrefix) {
auto str_name = GetDelimitedStringEx(p);
return GetFileName(str_name, pathPrefix);
}

std::filesystem::path GetOutputFileName(char*& p) {
return GetFileName(p, Options::OutPrefix);
auto str_name = GetDelimitedStringEx(p); // read delimited filename string
SJ_FixSlashes(str_name); // convert backslashes *with* warning
// prefix with output path and force slashes again (without warning)
return SJ_force_slash(Options::OutPrefix / str_name.first);
}

EDelimiterType GetDelimiterOfLastFileName() {
// DT_NONE if no GetFileName was called
return delimiterOfLastFileName;
}

//FIXME duplicate from support - get rid of SJ_SearchPath, GetPath, ... (whole chain)
static bool isAnySlash(const char c) {
return pathGoodSlash == c || pathBadSlash == c;
}

//FIXME duplicate from support - get rid of SJ_SearchPath, GetPath, ... (whole chain)
/**
* @brief Check if the path does start with MS windows drive-letter and colon, but accepts
* only absolute form with slash after colon, otherwise warns about relative way not supported.
*
* @param filePath p_filePath: filename to check
* @return bool true if the filename contains drive-letter with ABSOLUTE path
*/
static bool isWindowsDrivePathStart(const char* filePath) {
if (!filePath || !filePath[0] || ':' != filePath[1]) return false;
const char driveLetter = toupper(filePath[0]);
Expand All @@ -113,7 +102,7 @@ fullpath_ref_t GetInputFile(delim_string_t && in) {
// not archived yet, look for the file somewhere...
const std::filesystem::path name_in{ in.first };
// completely empty -> special value to signal stdin
if (name_in.empty()) { // use special SInputFile constructor to have fake name "<stdin>"
if (name_in.empty() && DT_COUNT == in.second) { // use special SInputFile constructor to have fake name "<stdin>"
return archivedInputFiles.emplace_hint(lb, std::move(in), 1)->second;
}
// no filename - return it as is (it's not valid for open)
Expand Down Expand Up @@ -483,39 +472,6 @@ void EmitBlock(aint byte, aint len, bool preserveDeviceMemory, int emitMaxToList
}
}

char* GetPath(const char* fname, char** filenamebegin, bool systemPathsBeforeCurrent)
{
char fullFilePath[MAX_PATH] = { 0 };
CStringsList* dir = Options::IncludeDirsList; // include-paths to search
// search current directory first (unless "systemPathsBeforeCurrent")
if (!systemPathsBeforeCurrent) {
// if found, just skip the `while (dir)` loop
if (SJ_SearchPath(CurrentDirectory.string().c_str(), fname, nullptr, MAX_PATH, fullFilePath, filenamebegin)) dir = nullptr;
else fullFilePath[0] = 0; // clear fullFilePath every time when not found
}
while (dir) {
if (SJ_SearchPath(dir->string, fname, nullptr, MAX_PATH, fullFilePath, filenamebegin)) break;
fullFilePath[0] = 0; // clear fullFilePath every time when not found
dir = dir->next;
}
// if the file was not found in the list, and current directory was not searched yet
if (!fullFilePath[0] && systemPathsBeforeCurrent) {
//and the current directory was not searched yet, do it now, set empty string if nothing
if (!SJ_SearchPath(CurrentDirectory.string().c_str(), fname, NULL, MAX_PATH, fullFilePath, filenamebegin)) {
fullFilePath[0] = 0; // clear fullFilePath every time when not found
}
}
if (!fullFilePath[0] && filenamebegin) { // if still not found, reset also *filenamebegin
*filenamebegin = fullFilePath;
}
// copy the result into new memory
char* kip = STRDUP(fullFilePath);
if (kip == NULL) ErrorOOM();
// convert filenamebegin pointer into the copied string (from temporary buffer pointer)
if (filenamebegin) *filenamebegin += (kip - fullFilePath);
return kip;
}

// if offset is negative, it functions as "how many bytes from end of file"
// if length is negative, it functions as "how many bytes from end of file to not load"
void BinIncFile(fullpath_ref_t file, aint offset, aint length) {
Expand Down
7 changes: 1 addition & 6 deletions sjasm/sjio.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,7 @@ using files_in_map_t = std::map<const delim_string_t, const SInputFile>;
// (archives the input in case this is first time, otherwise returns archived path)
fullpath_ref_t GetInputFile(delim_string_t && in);
fullpath_ref_t GetInputFile(char*& p);

std::filesystem::path GetFileName(delim_string_t & str_name, const std::filesystem::path & pathPrefix = "");
std::filesystem::path GetFileName(char*& p, const std::filesystem::path & pathPrefix = ""); // get string in delimiters, remember delimiter, convert slashes, prepend pathPrefix
std::filesystem::path GetOutputFileName(char*& p); // GetFileName with pathPrefix = OutPrefix
EDelimiterType GetDelimiterOfLastFileName(); // DT_NONE if no GetFileName was called
std::filesystem::path GetOutputFileName(char*& p);

//FIXME this is still used by Lua to archive its temporary filenames retrieved trough debug interface, maybe abuse GetInputFile here too? (DT_COUNT delim string)
const char* ArchiveFilename(const char* fullpathname); // returns permanent c_str pointer to input c_str (used for Lua script file names)
Expand Down Expand Up @@ -109,7 +105,6 @@ void OpenTapFile(const std::filesystem::path & tapename, int flagbyte);
void PrintHex(char* & dest, aint value, int nibbles);
void PrintHex32(char* & dest, aint value);
void PrintHexAlt(char* & dest, aint value);
char* GetPath(const char* fname, char** filenamebegin = NULL, bool systemPathsBeforeCurrent = false); //FIXME path??

/**
* @brief Includes bytes of particular file into output (and virtual device memory).
Expand Down
66 changes: 0 additions & 66 deletions sjasm/support.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,79 +49,13 @@ FILE* SJ_fopen(const std::filesystem::path & fname, const char* mode) {
return fopen(fname.string().c_str(), mode);
}

FILE* SJ_fopen(const char* fname, const char* mode) {
if (nullptr == fname) return nullptr;
return SJ_fopen(std::filesystem::path(fname), mode);
}

/*
FILE* dbg_fopen(const char* fname, const char* modes) {
FILE* f = fopen(fname, modes);
printf("fopen = %p modes [%s]\tname (%lu) [%s]\n", (void*)f, modes, strlen(fname), fname);
return f;
}
*/

void SJ_GetCurrentDirectory(int whatever, char* pad) {
pad[0] = 0;
//TODO implement this one? And decide what to do with it?
// Will affect "--fullpath" paths if implemented correctly (as GetCurrentDirectory on windows)
//FIXME double-check with new std::filesystem usage, I think there may be API for this
}

static bool isAnySlash(const char c) {
return pathGoodSlash == c || pathBadSlash == c;
}

/**
* @brief Check if the path does start with MS windows drive-letter and colon, but accepts
* only absolute form with slash after colon, otherwise warns about relative way not supported.
*
* @param filePath p_filePath: filename to check
* @return bool true if the filename contains drive-letter with ABSOLUTE path
*/
static bool isWindowsDrivePathStart(const char* filePath) {
if (!filePath || !filePath[0] || ':' != filePath[1]) return false;
const char driveLetter = toupper(filePath[0]);
if (driveLetter < 'A' || 'Z' < driveLetter) return false;
if (!isAnySlash(filePath[2])) {
Warning("Relative file path with drive letter detected (not supported)", filePath, W_EARLY);
return false;
}
return true;
}

int SJ_SearchPath(const char* oudzp, const char* filename, const char*, int maxlen, char* nieuwzp, char** ach) {
assert(nieuwzp);
*nieuwzp = 0;
if (nullptr == filename) return 0;
if (isAnySlash(filename[0]) || isWindowsDrivePathStart(filename)) {
STRCPY(nieuwzp, maxlen, filename);
} else {
STRCPY(nieuwzp, maxlen, oudzp);
if (*nieuwzp) {
char *lastChar = nieuwzp + strlen(nieuwzp) - 1;
if (!isAnySlash(*lastChar)) {
lastChar[1] = pathGoodSlash;
lastChar[2] = 0;
}
}
STRCAT(nieuwzp, maxlen, filename);
}
if (ach) {
char* p = *ach = nieuwzp;
while (*p) {
if (isAnySlash(*p++)) *ach = p;
}
}
FILE* fp;
if (FOPEN_ISOK(fp, nieuwzp, "r")) {
fclose(fp);
return 1;
}
return 0;
}

#ifndef WIN32

long GetTickCount() {
Expand Down
8 changes: 0 additions & 8 deletions sjasm/support.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@

// support.h

constexpr char pathBadSlash = '\\';
constexpr char pathGoodSlash = '/';

constexpr uint16_t sj_bswap16(const uint16_t v) {
return ((v>>8)&0xFF) | ((v<<8)&0xFF00);
}
Expand Down Expand Up @@ -61,9 +58,6 @@ static_assert(0x78563412 == sj_bswap32(0x12345678), "internal error in bswap32 i

#endif

#ifndef TCHAR
#define TCHAR char
#endif
#ifndef WIN32
long GetTickCount();
#endif
Expand All @@ -78,9 +72,7 @@ long GetTickCount();

void SJ_FixSlashes(delim_string_t & str, bool do_warning = true); // convert backslashes, can produce warning
FILE* SJ_fopen(const std::filesystem::path & fname, const char* mode);
FILE* SJ_fopen(const char* fname, const char* mode);
void SJ_GetCurrentDirectory(int, char*);
int SJ_SearchPath(const char* oudzp, const char* filename, const char* /*extension*/, int maxlen, char* nieuwzp, char** ach);

// FILE* dbg_fopen(const char* fname, const char* modes);

Expand Down

0 comments on commit f3df4db

Please sign in to comment.