finished basic ini skeleton

This commit is contained in:
Hane 2024-12-06 19:59:09 +01:00
commit adca5111f6
4 changed files with 83 additions and 11 deletions

View file

@ -31,7 +31,6 @@ std::string getPath(SettingsTargetDirectory target, bool create) {
currentChar = roamingPath[pathLen];
}
settingsPath = (wchar_t*)calloc(pathLen +
maxPathBypassLen +
folderPathLen +

View file

@ -941,6 +941,8 @@ HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) {
}
connect(channels, &QCheckBox::stateChanged, [this, parent](){
set->setValue("show_channels", channels->isChecked(), sizeof("show_channels"));
if(!OverseerHandler::settingsPath.empty())
set->save(OverseerHandler::settingsPath.c_str());
if(parent)
QCoreApplication::instance()->postEvent
(parent, new QEvent((QEvent::Type)CustomQEvent::RecomposeMainWindow));

View file

@ -3,14 +3,17 @@
namespace ini {
wchar_t* utf8toUtf16(const char* str) {
wchar_t* utf8toUtf16(const char* str, uint64_t* size = nullptr) {
if(!str || str[0] == '\0') return nullptr;
int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
if(size) *size = sizeNeeded;
wchar_t* utf16 = (wchar_t*)calloc(sizeNeeded, 1);
MultiByteToWideChar(CP_UTF8, 0, str, -1, utf16, sizeNeeded);
return utf16;
}
UserSettings::UserSettings(char* textContents) {
//Parsing values
bool isCRLF = false;
@ -47,7 +50,6 @@ namespace ini {
free(textContents);
}
//todo: buffer overflow. poc
char* const UserSettings::getValue(char* key, uint64_t len) {
if (auto search = values.find(key); search != values.end())
return (char* const) search->second;
@ -92,6 +94,80 @@ namespace ini {
return;
}
bool UserSettings::save(const char* path) {
wchar_t maxPathBypass[] = L"\\\\?\\";
uint32_t maxPathBypassLen = (sizeof(maxPathBypass)/ sizeof(wchar_t)) - 1;
if(!path) return false;
uint64_t convertedPathSize = 0;
wchar_t* convertedPath = utf8toUtf16(path, &convertedPathSize);
if(!convertedPath) return false;
wchar_t* utf16Path = (wchar_t*)calloc(maxPathBypassLen + convertedPathSize, sizeof(wchar_t));
memcpy(utf16Path, maxPathBypass, sizeof(wchar_t) * maxPathBypassLen);
memcpy(utf16Path + maxPathBypassLen, convertedPath, sizeof(wchar_t) * convertedPathSize);
free(convertedPath);
#define releaseBeforeReturn() do { \
CloseHandle(settingsHandle); \
settingsHandle = nullptr; \
free(utf16Path); \
free(text); \
} while(0)
//We initially reserve 1024B for flushing. If storage is exceeded, more same-size chunks are allocated
const uint64_t chunkSize = 1024;
char* text = (char*)calloc(chunkSize, sizeof(char));
uint64_t mapSize = values.size();
uint64_t chunks = 1;
uint64_t keySize = 0, valueSize = 0, totalSize = 0, previousStepSize = 0;
//for(std::pair<char*, char*> entry : values) {
std::unordered_map<char*, char*, Djb12Hasher, StrcmpEqual>::iterator it;
for (it = values.begin(); it != values.end(); it++) {
keySize = strlen(it->first);
valueSize = strlen(it->second);
totalSize += valueSize + keySize + (it == values.begin() ? 1 : 2); //newline and separator
if(totalSize > (chunkSize * chunks)) {
text = (char*)realloc(text, (++chunks * chunkSize));
}
if(it != values.begin())
memcpy(text + previousStepSize++, "\n", sizeof(char));
memcpy(text + previousStepSize, it->first, sizeof(char) * keySize);
memcpy(text + previousStepSize + keySize, "=", sizeof(char));
memcpy(text + previousStepSize + 1 + keySize, it->second, sizeof(char) * valueSize);
previousStepSize = totalSize;
}
HANDLE settingsHandle = nullptr;
settingsHandle = CreateFile2(
utf16Path,
GENERIC_READ | GENERIC_WRITE,
0,
CREATE_ALWAYS,
NULL);
if(settingsHandle == INVALID_HANDLE_VALUE) {
releaseBeforeReturn();
return false;
}
DWORD bytesWritten;
BOOL writeSuccess = WriteFile(
settingsHandle,
text,
totalSize,
&bytesWritten,
nullptr
);
releaseBeforeReturn();
if (writeSuccess == TRUE) return true;
else return false;
return false;
}
UserSettings::~UserSettings() {
//if(textContents) free(textContents);
for(std::pair<char*, char*> entry : values) {

View file

@ -57,18 +57,13 @@ class UserSettings {
char* const getValue(char* key, uint64_t len = 0);
void setValue(char* key, char* value, uint64_t valueSize, uint64_t keySize); //'\0' included
void setValue(char* key, bool value, uint64_t keySize); //'\0' included
//void setValue(char* key, uint64_t value, uint64_t valueSize, uint64_t keySize); //'\0' included
bool save(const char* path);
protected:
private:
//void* returnValue();
UserSettings(char* text = nullptr);
//std::map<const char*, int> values{ {"show_channels", false}, {"test", 7} };
std::unordered_map<char*, char*, Djb12Hasher, StrcmpEqual> values;
//char* textContents = nullptr;
//uint64_t textContentsSize = 0;
char* pos = "true";
char* neg = "false";
};