Skip to content

Commit

Permalink
Merge branch 'master' of github.com:gk646/cxstructs
Browse files Browse the repository at this point in the history
  • Loading branch information
gk646 committed Jun 7, 2024
2 parents f88c90a + 87daa6a commit 76c86c2
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 70 deletions.
26 changes: 10 additions & 16 deletions include/cxutil/cxassert.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

# include <cstdio>

inline void CX_ASSERT_failed(const char* expr, const char* file, int line, const char* message) {
namespace {
void CX_ASSERT_failed(const char* expr, const char* file, int line, const char* message) {
fprintf(stderr, "Assert failed: %s\nAt: %s:%d\nMessage: %s", expr, file, line, message);
# if defined(_MSC_VER)
__debugbreak();
Expand All @@ -34,27 +35,20 @@ inline void CX_ASSERT_failed(const char* expr, const char* file, int line, const
# endif
}

inline void WARNING_failed(const char* expr, const char* file, int line, const char* message) {
void WARNING_failed(const char* expr, const char* file, int line, const char* message) {
fprintf(stderr, "Warning: %s\nAt: %s:%d\nMessage: %s", expr, file, line, message);
}
} // namespace

# define CX_ASSERT(expr, message) \
((expr) ? (void)0 : CX_ASSERT_failed(#expr, __FILE__, __LINE__, message))
# define CX_ASSERT(expr, message) ((expr) ? (void)0 : CX_ASSERT_failed(#expr, __FILE__, __LINE__, message))

# define CX_WARNING(expr, message) \
((expr) ? (void)0 : WARNING_failed(#expr, __FILE__, __LINE__, message))
# define CX_WARNING(expr, message) ((expr) ? (void)0 : WARNING_failed(#expr, __FILE__, __LINE__, message))

# if defined(_MSC_VER) && !defined(_DEBUG)
# if !defined(_DEBUG) || defined(NDEBUG)
# undef CX_ASSERT
# undef CX_WARNING
# define CX_ASSERT(expr, message) ((void)0)
# elif defined(NDEBUG)
# undef CX_ASSERT
# undef CX_ASSERT_1
# undef CX_ASSERT_2
# define CX_ASSERT_1(expr) ((void)0)
# define CX_ASSERT_2(expr, message) ((void)0)
# define GET_MACRO(_1, _2, NAME, ...) NAME
# define CX_ASSERT(...) GET_MACRO(__VA_ARGS__, CX_ASSERT_2, CX_ASSERT_1)(__VA_ARGS__)
# define CX_WARNING(expr, message) ((void)0)
# endif

#endif //CXSTRUCTS_SRC_CXASSERT_H_
#endif //CXSTRUCTS_SRC_CXASSERT_H_
117 changes: 75 additions & 42 deletions include/cxutil/cxio.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@
# include <cstring>

// Simple, readable and fast *symmetric* serialization structure with loading
// and saving. Each line is a concatenated list of values and delimiter '|'
// (might be changeable in the future) 13|3.145|This is a string|56|
// and saving. Each line is a concatenated list of values and a separator
// 13|3.145|This is a string|56|

// I didnt find a way around hard coding the separator...

// Using the CXX23 std::print() is about 10% slower

namespace cxstructs {
// inline static constexpr char DELIMITER = '|'; //Not used yet
static constexpr int MAX_SECTION_SIZE = 16;
# define NEW_LINE_SUB '\036'

//-----------SHARED-----------//
namespace {
Expand Down Expand Up @@ -65,7 +68,6 @@ inline auto io_check_eof(FILE* file) -> bool {
fseek(file, currentPos, SEEK_SET);
return false; // Not EOF
}

//-----------SAVING-----------//
// Writes a section header - used like: while(io_load_inside_section()){}
inline void io_save_section(FILE* file, const char* value) {
Expand All @@ -75,26 +77,44 @@ inline void io_save_section(FILE* file, const char* value) {
inline void io_save_newline(FILE* file) {
fputc('\n', file);
}
// Writes a string value to file

// Writes a string value to file, replacing newlines with the SEPARATOR
inline void io_save(FILE* file, const char* value) {
fprintf(file, "%s|", value);
while (*value != '\0') {
if (*value == '\n') {
fputc(NEW_LINE_SUB, file); // Replace newline with SEPARATOR
} else {
fputc(*value, file); // Write the character as is
}
++value;
}
fputc('\037', file); // Add SEPARATOR at the end
}

// Writes an integer or enum property to the file
inline void io_save(FILE* file, const int value) {
fprintf(file, "%d|", value);
fprintf(file, "%d\037", value);
}
// Writes an boolean to the file

// Writes a boolean to the file
inline void io_save(FILE* file, const bool value) {
fprintf(file, "%d|", value ? 1 : 0);
fprintf(file, "%d\037", value ? 1 : 0);
}

// Writes a float to the file
inline void io_save(FILE* file, const float value) {
fprintf(file, "%.3f|", value);
fprintf(file, "%.3f\037", value);
}
// Writes a three floats to the file

// Writes three floats to the file - separated by ";"
inline void io_save(FILE* file, const float value, const float value2, const float value3) {
fprintf(file, "%.3f|%.3f|%.3F|", value, value2, value3);
fprintf(file, "%.6f;%.6f;%.6f\037", value, value2, value3);
}
// Writes three floats to the file - separated by ";"
inline void io_save(FILE* file, const float value, const float value2) {
fprintf(file, "%.6f;%.6f\037", value, value2);
}

// Buffers the given SaveFunc to memory so the file is only written if it
// executes successfully. Returns false on error
template <typename SaveFunc> // SaveFunc(FILE* file)
Expand All @@ -103,14 +123,12 @@ bool io_save_buffered_write(const char* fileName, const int memoryBufferBytes, S

# ifdef _WIN32
FILE* file;
fopen_s(&file,"NUL", "wb");
fopen_s(&file, "NUL", "wb");
# else
FILE* file = fopen("/dev/null", "wb");
# endif
// Write to in memory buffer
if (file == nullptr) {
return false;
}
if (file == nullptr) { return false; }

auto* buffer = new char[memoryBufferBytes];
std::memset(buffer, 0, memoryBufferBytes);
Expand All @@ -132,9 +150,9 @@ bool io_save_buffered_write(const char* fileName, const int memoryBufferBytes, S
// When successful, open the actual save file and save the data
const int dataSize = (int)strlen(buffer);
# ifdef _WIN32
fopen_s(&file,fileName, "wb");
fopen_s(&file, fileName, "wb");
# else
file = fopen(fileName, "wb");
file = fopen(fileName, "wb");
# endif
if (file == nullptr) {
delete[] buffer;
Expand All @@ -151,21 +169,25 @@ bool io_save_buffered_write(const char* fileName, const int memoryBufferBytes, S

delete[] buffer;

if (fclose(file) != 0) {
return false;
}
if (fclose(file) != 0) { return false; }

return true;
}
//-----------LOADING-----------//
// Searches for the next new line but stops at the delimiter if not forced
// Searches for the next new line but stops at the separator if not forced
inline void io_load_newline(FILE* file, bool force = false) {
char ch;
while (fread(&ch, 1, 1, file) == 1) {
if (!force && ch == '|') return;
if (!force && ch == '\037') return;
if (ch == '\n') return;
}
}
inline void io_load_skip_separator(FILE* file) {
char ch;
while (fread(&ch, 1, 1, file) == 1) {
if (ch == '\037') return;
}
}
inline bool io_load_inside_section(FILE* file, const char* section) {
long currentPos = ftell(file);
if (currentPos == -1) return false; // Error - we return false
Expand All @@ -192,54 +214,65 @@ inline bool io_load_inside_section(FILE* file, const char* section) {
if (manual_strncmp(buffer, section, sectionLength) == 0) {
io_load_newline(file, false);
return true; // Found same section
} else {
io_load_newline(file, false);
return false; // Found new section
}

io_load_newline(file, false);
return false; // Found new section
}

fseek(file, currentPos, SEEK_SET);
return true; // Still inside same section
}
// include <string> to use
# if defined( _STRING_) || defined(_GLIBCXX_STRING)
inline void io_load(FILE* file, std::string& s, int reserve_amount = 15) {
s.reserve(reserve_amount);
# if defined(_STRING_) || defined(_GLIBCXX_STRING)
inline void io_load(FILE* file, std::string& s) {
//s.reserve(reserve_amount); // Dont need to reserve - string shouldnt allocate below 15 characters
char ch;
while (fread(&ch, 1, 1, file) == 1 && ch != '|') {
while (fread(&ch, 1, 1, file) == 1 && ch != '\037') {
if (ch == NEW_LINE_SUB) [[unlikely]] { ch = '\n'; }
s.push_back(ch);
}
while (ch != '\37' && fread(&ch, 1, 1, file) == 1) {}
}
# endif
// Load a string property into a user-supplied buffer
inline void io_load(FILE* file, char* buffer, size_t buffer_size) {
size_t count = 0;
// Load a string property into a user-supplied buffer - return bytes written - reads until linesep is found
inline int io_load(FILE* file, char* buffer, size_t buffer_size) {
int count = 0;
char ch;
while (count < buffer_size - 1 && fread(&ch, 1, 1, file) == 1 && ch != '|') {
while (count < buffer_size - 1 && fread(&ch, 1, 1, file) == 1 && ch != '\037') {
if (ch == NEW_LINE_SUB) [[unlikely]] { ch = '\n'; }
buffer[count++] = ch;
}
buffer[count] = '\0';
while (ch != '\037' && fread(&ch, 1, 1, file) == 1) {}
return count;
}
// Directly load an integer property from the file
inline void io_load(FILE* file, int& i) {
fscanf(file, "%d|", &i);
fscanf(file, "%d\037", &i);
}
// Directly load a boolean to the file

// Directly load a boolean from the file
inline void io_load(FILE* file, bool& value) {
int num = 0;
fscanf(file, "%d|", &num);
fscanf(file, "%d\037", &num);
value = num == 1;
}

// Directly load a float from the file
inline void io_load(FILE* file, float& f) {
fscanf(file, "%f|", &f);
fscanf(file, "%f\037", &f);
}
// Directly load a three floats from the file

// Directly load three floats from the file
inline void io_load(FILE* file, float& f, float& f2, float& f3) {
fscanf(file, "%f|%f|%f|", &f, &f2, &f3);
fscanf(file, "%f;%f;%f\037", &f, &f2, &f3);
}
// Directly load three floats from the file
inline void io_load(FILE* file, float& f, float& f2) {
fscanf(file, "%f;%f\037", &f, &f2);
}
}

} // namespace cxstructs

# ifdef CX_INCLUDE_TESTS
# include <chrono>
Expand Down
Loading

0 comments on commit 76c86c2

Please sign in to comment.