finished basic ini skeleton
This commit is contained in:
parent
1ae324b68a
commit
adca5111f6
4 changed files with 83 additions and 11 deletions
|
|
@ -31,7 +31,6 @@ std::string getPath(SettingsTargetDirectory target, bool create) {
|
|||
currentChar = roamingPath[pathLen];
|
||||
}
|
||||
|
||||
|
||||
settingsPath = (wchar_t*)calloc(pathLen +
|
||||
maxPathBypassLen +
|
||||
folderPathLen +
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue