mirror of
https://github.com/Karaka-Management/cOMS.git
synced 2026-01-10 19:08:39 +00:00
142 lines
3.4 KiB
C
Executable File
142 lines
3.4 KiB
C
Executable File
#ifndef COMS_UI_LANGUAGE_H
|
|
#define COMS_UI_LANGUAGE_H
|
|
|
|
#include "../stdlib/Types.h"
|
|
#include "../memory/RingMemory.h"
|
|
#include "../system/FileUtils.cpp"
|
|
|
|
#define LANGUAGE_VERSION 1
|
|
|
|
// Size is limited to 4GB
|
|
struct Language {
|
|
// WARNING: the actual start of data is data -= sizeof(Language); see file loading below
|
|
// The reason for this is we store the Language struct in the beginning of the data/file
|
|
byte* data;
|
|
|
|
int32 count;
|
|
int32 size;
|
|
char** lang;
|
|
};
|
|
|
|
void language_from_file_txt(
|
|
Language* language,
|
|
const char* path,
|
|
RingMemory* ring
|
|
) {
|
|
FileBody file = {};
|
|
file_read(path, &file, ring);
|
|
ASSERT_SIMPLE(file.size);
|
|
|
|
// count elements
|
|
language->count = 1;
|
|
int32 len = 0;
|
|
|
|
byte* data = file.content;
|
|
|
|
while (data[len] != '\0') {
|
|
if (data[len] == '\n' && data[len + 1] == '\n') {
|
|
++language->count;
|
|
data[len] = '\0';
|
|
++len;
|
|
}
|
|
|
|
++len;
|
|
}
|
|
|
|
language->size = len;
|
|
language->lang = (char **) language->data;
|
|
memcpy(language->data + language->count * sizeof(char *), data, len);
|
|
|
|
// First element = 0
|
|
char** pos = language->lang;
|
|
*pos++ = (char *) data;
|
|
|
|
for (int32 i = 1; i < len - 1; ++i) {
|
|
if (data[i] == '\0') {
|
|
// We have to move by 2 since every text element is separated by 2 \n
|
|
// 1 \n is a valid char for a single text element
|
|
// @performance This also means that we have one additional byte for
|
|
// every text element even in the binary version.
|
|
*pos++ = (char *) &data[i + 2];
|
|
}
|
|
}
|
|
}
|
|
|
|
int32 language_data_size(const Language* language)
|
|
{
|
|
return (int32) (language->size
|
|
+ sizeof(language->count)
|
|
+ sizeof(language->size)
|
|
+ language->count * sizeof(uint32)
|
|
);
|
|
}
|
|
|
|
// File layout - binary
|
|
// offsets for start of strings
|
|
// actual string data
|
|
int32 language_from_data(
|
|
const byte* data,
|
|
Language* language
|
|
) {
|
|
const byte* pos = data;
|
|
|
|
// Count
|
|
language->count = SWAP_ENDIAN_LITTLE(*((int32 *) pos));
|
|
pos += sizeof(language->count);
|
|
|
|
language->size = SWAP_ENDIAN_LITTLE(*((int32 *) pos));
|
|
pos += sizeof(language->size);
|
|
|
|
language->lang = (char **) language->data;
|
|
char** pos_lang = language->lang;
|
|
|
|
byte* start = language->data;
|
|
|
|
// Load pointers/offsets
|
|
for (int32 i = 0; i < language->count; ++i) {
|
|
*pos_lang++ = (char *) (start + SWAP_ENDIAN_LITTLE(*((uint32 *) pos)));
|
|
pos += sizeof(uint32);
|
|
}
|
|
|
|
memcpy(
|
|
language->data + language->count * sizeof(uint32),
|
|
pos,
|
|
language->size
|
|
);
|
|
|
|
return language_data_size(language);
|
|
}
|
|
|
|
int32 language_to_data(
|
|
const Language* language,
|
|
byte* data
|
|
) {
|
|
byte* pos = data;
|
|
|
|
// Count
|
|
*((int32 *) pos) = SWAP_ENDIAN_LITTLE(language->count);
|
|
pos += sizeof(language->count);
|
|
|
|
// Count
|
|
*((int32 *) pos) = SWAP_ENDIAN_LITTLE((int32) language->size);
|
|
pos += sizeof(language->size);
|
|
|
|
byte* start = pos;
|
|
|
|
// Save pointers
|
|
for (int32 i = 0; i < language->count; ++i) {
|
|
*((uint32 *) pos) = SWAP_ENDIAN_LITTLE((uint32) ((uintptr_t) pos - (uintptr_t) start));
|
|
pos += sizeof(uint32);
|
|
}
|
|
|
|
// Save actual strings
|
|
memcpy(
|
|
pos,
|
|
language->data + language->count * sizeof(uint32),
|
|
language->size
|
|
);
|
|
|
|
return language_data_size(language);
|
|
}
|
|
|
|
#endif |