-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Hi , if you want manage language.ini instead of language .dll here code:
languageIni.cpp
#include "languageIni.h"
// source from https://github.com/SiegeEngineers/aoc-language-ini/blob/default/aoc_language_ini.c
// source from https://github.com/SiegeEngineers/aoc-language-ini/blob/unicode/api.c
static char* read_file(char* filename) {
FILE* file = fopen(filename, "rb");
if (file == NULL) return NULL;
fseek(file, 0, SEEK_END);
int size = ftell(file);
fseek(file, 0, SEEK_SET);
char* content = (char* )calloc(1, size + 1);
content[size] = '\0';
int read = fread(content, 1, size, file);
fclose(file);
if (size != read) {
free(content);
return NULL;
}
return content;
}
static void expand_string_table(string_table_t* string_table) {
string_table->capacity += 8192;
string_table->entries = (string_entry_t*)realloc(string_table->entries,
string_table->capacity * sizeof(string_entry_t));
}
static char* from_utf8(char* utf8) {
int utf16len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
wchar_t* utf16 = (wchar_t*)calloc(utf16len, sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, utf16len);
int local_len = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL, 0, NULL, NULL);
char* local = (char*)calloc(local_len, sizeof(char));
WideCharToMultiByte(CP_ACP, 0, utf16, -1, local, local_len, NULL, NULL);
free(utf16);
return local;
}
static char* unescape(char* input) {
int l = strlen(input);
int j = 0;
char* buf = (char*)calloc(1, l + 1);
for (int i = 0; i < l; i++) {
if (input[i] == '\' && i + 1 < l) {
switch (input[i + 1]) {
case 'n':
i++;
buf[j++] = '\n';
break;
case 'r':
i++;
buf[j++] = '\r';
break;
default:
buf[j++] = input[i];
break;
}
}
else {
buf[j++] = input[i];
}
}
buf[j] = '\0';
return buf;
}
HANDLE aoc_ini_load_strings(char* filename) {
//string_table_t string_table = {
// .id = string_table_id,
// .filename = strdup(filename),
// .size = 0,
// .capacity = 8192
//};
string_table_t string_table;
string_table.id = string_table_id;
string_table.filename = strdup(filename);
string_table.size = 0;
string_table.capacity = 8192;
string_table_id++;
int id;
char cur_string[4096];
char* content = read_file(filename);
if (!content) return INVALID_HANDLE_VALUE;
string_table.entries = (string_entry_t*)calloc(string_table.capacity, sizeof(string_entry_t));
char is_unicode = FALSE;
char* read_ptr = strtok(content, "\n");
while (read_ptr != NULL) {
if (read_ptr[0] == '[') {
if (strncmp(read_ptr, "[unicode]", strlen("[unicode]")) == 0) {
is_unicode = TRUE;
}
}
if (read_ptr[0] != ';') {
if (sscanf(read_ptr, "%d=%4096[^\n\r]", &id, cur_string) == 2) {
string_table.entries[string_table.size].id = id;
char* local_string = cur_string;
//if (is_unicode) {
local_string = from_utf8(cur_string);
//}
char* unescaped = unescape(local_string);
if (is_unicode) {
free(local_string);
}
string_table.entries[string_table.size].value = unescaped;
string_table.entries[string_table.size].size = strlen(unescaped);
string_table.size++;
if (string_table.size >= string_table.capacity) {
expand_string_table(&string_table);
}
}
}
read_ptr = strtok(NULL, "\n");
}
if (string_table.size < string_table.capacity) {
// just to be safe, zero out the rest
memset(&string_table.entries[string_table.size], 0,
(string_table.capacity - string_table.size) * sizeof(string_entry_t));
}
if (string_tables == NULL) {
string_tables = (string_table_t*) calloc(1, sizeof(string_table_t));
num_string_tables = 1;
}
else {
num_string_tables += 1;
string_tables = (string_table_t*)realloc(string_tables, num_string_tables * sizeof(string_table_t));
}
memcpy(&string_tables[num_string_tables - 1], &string_table, sizeof(string_table));
return (HANDLE)string_table.id;
}
static void free_string_table_entries(string_table_t* table) {
for (int i = 0; i < table->size; i++) {
free(table->entries[i].value);
}
free(table->entries);
table->entries = NULL;
table->size = 0;
table->capacity = 0;
}
static void aoc_ini_free_all() {
for (int i = 0; i < num_string_tables; i++) {
free_string_table_entries(&string_tables[i]);
free(string_tables[i].filename);
}
free(string_tables);
num_string_tables = 0;
return;
}
void aoc_ini_free_strings(HANDLE table_handle) {
int table_id = (size_t)table_handle;
for (int i = 0; i < num_string_tables; i++) {
if (string_tables[i].id == table_id) {
free_string_table_entries(&string_tables[i]);
size_t num_remaining = num_string_tables - (i + 1);
if (num_remaining == 0) {
num_string_tables -= 1;
string_tables = (string_table_t*)realloc(string_tables, num_string_tables * sizeof(string_table_t));
}
else {
string_table_t* rest = (string_table_t*)calloc(num_remaining, sizeof(string_table_t));
memcpy(rest, &string_tables[i + 1], num_remaining * sizeof(string_table_t));
num_string_tables -= 1;
string_tables = (string_table_t*)realloc(string_tables, num_string_tables * sizeof(string_table_t));
memcpy(&string_tables[i], rest, num_remaining * sizeof(string_table_t));
free(rest);
}
break;
}
}
}
static string_entry_t* find_string_in_table(string_table_t* table, int id) {
for (int i = 0; i < table->size; i++) {
if (table->entries[i].id == id) {
return &table->entries[i];
}
}
return NULL;
}
string_entry_t* find_string(int id) {//static
string_entry_t* entry = NULL;
for (int i = num_string_tables - 1; i >= 0; i--) {
entry = find_string_in_table(&string_tables[i], id);
if (entry) return entry;
}
return NULL;
}
languageIni.h
#pragma once
#include
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <wchar.h>
typedef struct string_table_id {
size_t id;
} string_table_id;
typedef struct string_entry {
int id;
int size;
char* value;
} string_entry_t;
typedef struct string_table {
size_t id;
char* filename;
size_t size;
size_t capacity;
string_entry_t* entries;
} string_table_t;
HANDLE aoc_ini_load_strings(char* filename);
//typedef void* HINSTANCE;
typedef char* (__stdcall* fn_load_string)(HINSTANCE, unsigned int, char*, int);
static string_table_t* string_tables;
static size_t num_string_tables;
static size_t string_table_id;// next_string_table_id;
//static __stdcall char* load_string_hook(HINSTANCE dll, unsigned int string_id, char* buf_out, int buf_size);//static __stdcall
//static __stdcallchar* load_string_hookAoc10(HINSTANCE dll, unsigned int string_id, char* buf_out, int buf_size);
//
string_entry_t* find_string(int id);