Files

523 lines
14 KiB
C++
Raw Permalink Normal View History

2025-05-17 21:29:46 -04:00
#include "IniUtility.h"
2025-05-20 17:32:37 -04:00
#include <stdio.h>
#include <string.h>
2025-05-17 21:29:46 -04:00
#include "pointerVector.h"
namespace {
2025-05-20 17:32:37 -04:00
char* trim(char* str)
{
if (str == NULL) return NULL;
// Trim leading spaces
char* start = str;
2025-05-24 09:10:13 -04:00
while (*start == ' ' || *start == '\t' || *start == '\r' || *start == '\n') start++;
2025-05-20 17:32:37 -04:00
// Trim trailing spaces
char* end = start + strlen(start) - 1;
2025-05-24 09:10:13 -04:00
while (end > start && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')) end--;
2025-05-20 17:32:37 -04:00
*(end + 1) = '\0';
return start;
2025-05-17 21:29:46 -04:00
}
2025-05-20 17:32:37 -04:00
bool isSection(char* line, char* sectionName)
{
if (line && line[0] == '[')
{
char* end = strchr(line, ']');
if (end)
{
strncpy(sectionName, line + 1, end - line - 1);
sectionName[end - line - 1] = '\0';
return true;
}
2025-05-17 21:29:46 -04:00
}
return false;
}
2025-05-20 17:32:37 -04:00
bool isKeyValuePair(char* line, char* key, char* value, bool& hasSpaces)
{
char* equalPos = strchr(line, '=');
if (equalPos)
{
strncpy(key, line, equalPos - line);
key[equalPos - line] = '\0';
strcpy(value, equalPos + 1);
// Check if spaces are around '='
hasSpaces = (strstr(line, " = ") != NULL);
trim(key);
trim(value);
2025-05-17 21:29:46 -04:00
return true;
}
return false;
}
}
char* IniUtility::GetValue(const char* filename, const char* section, const char* key)
{
2025-05-20 17:32:37 -04:00
FILE* file = fopen(filename, "r");
if (!file) return strdup("");
2025-05-17 21:29:46 -04:00
2025-05-20 17:32:37 -04:00
char line[MAX_LINE_SIZE], currentSection[256];
char keyStr[256];
strcpy(keyStr, key);
2025-05-23 22:36:35 -04:00
bool inGlobalSection = isNullOrEmpty(section);
2025-05-17 21:29:46 -04:00
2025-05-20 17:32:37 -04:00
while (fgets(line, sizeof(line), file))
{
char* trimmedLine = trim(line);
if (*trimmedLine == '\0' || *trimmedLine == ';') continue;
2025-05-17 21:29:46 -04:00
2025-05-20 17:32:37 -04:00
if (isSection(trimmedLine, currentSection))
{
2025-05-17 21:29:46 -04:00
inGlobalSection = false;
2025-05-20 17:32:37 -04:00
if (strcmp(currentSection, section) == 0)
{
2025-05-17 21:29:46 -04:00
inGlobalSection = true;
}
continue;
}
2025-05-20 17:32:37 -04:00
char foundKey[256], foundValue[MAX_VALUE_SIZE];
2025-05-17 21:29:46 -04:00
bool hasSpaces;
2025-05-20 17:32:37 -04:00
if (isKeyValuePair(trimmedLine, foundKey, foundValue, hasSpaces))
{
if ((inGlobalSection || strcmp(currentSection, section) == 0) && strcmp(foundKey, key) == 0)
{
char* result = strdup(foundValue);
fclose(file);
2025-05-17 21:29:46 -04:00
return result;
}
}
}
2025-05-20 17:32:37 -04:00
fclose(file);
2025-05-17 21:29:46 -04:00
return strdup("");
}
bool IniUtility::SetValue(const char* filename, const char* section, const char* key, const char* value)
{
2025-05-23 22:36:35 -04:00
FILE* file = fopen(filename, "rb");
2025-05-31 22:12:31 -04:00
bool fileExists = (file != NULL);
char* fileContent = NULL;
long fileSize = 0;
2025-05-20 17:32:37 -04:00
2025-05-31 22:12:31 -04:00
if (fileExists)
2025-05-20 17:32:37 -04:00
{
2025-05-31 22:12:31 -04:00
// Get file size
fseek(file, 0, SEEK_END);
fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
2025-05-17 21:29:46 -04:00
2025-05-31 22:12:31 -04:00
fileContent = new char[fileSize + 1]; // +1 for null terminator
if (!fileContent)
{
fclose(file);
return false;
}
fread(fileContent, 1, fileSize, file);
fileContent[fileSize] = '\0';
fclose(file);
}
2025-05-23 22:36:35 -04:00
// Prepare buffer for the new content
char* newContent = new char[fileSize + 1280]; // Allocate some extra space for new content
if (!newContent)
{
2025-05-31 22:12:31 -04:00
if (fileContent) delete[] fileContent;
2025-05-23 22:36:35 -04:00
return false;
}
newContent[0] = '\0'; // Start with an empty string
2025-05-20 17:32:37 -04:00
char line[MAX_LINE_SIZE], currentSection[256], previousSection[256] = "";
char keyStr[256], valueStr[MAX_VALUE_SIZE];
strcpy(keyStr, key);
strcpy(valueStr, value);
2025-05-17 21:29:46 -04:00
bool keyUpdated = false;
bool inGlobalSection = true;
2025-05-20 17:32:37 -04:00
bool firstFormatDetected = false;
2025-05-17 21:29:46 -04:00
bool useSpaces = false; // Determines if spaces should be used around '='
2025-05-31 22:12:31 -04:00
if (fileExists && fileContent)
2025-05-20 17:32:37 -04:00
{
2025-05-31 22:12:31 -04:00
char* currentLine = strtok(fileContent, "\r\n");
while (currentLine)
2025-05-20 17:32:37 -04:00
{
2025-05-31 22:12:31 -04:00
strncpy(line, currentLine, sizeof(line) - 1);
line[sizeof(line) - 1] = '\0'; // Ensure null-termination
char* trimmedLine = trim(line);
2025-05-17 21:29:46 -04:00
2025-05-31 22:12:31 -04:00
if (*trimmedLine == '\0' || *trimmedLine == ';')
2025-05-23 22:36:35 -04:00
{
2025-05-31 22:12:31 -04:00
strcat(newContent, line);
2025-05-24 09:10:13 -04:00
strcat(newContent, "\r\n");
currentLine = strtok(NULL, "\r\n");
2025-05-17 21:29:46 -04:00
continue;
}
2025-05-31 22:12:31 -04:00
char foundKey[256], foundValue[MAX_VALUE_SIZE];
bool lineHasSpaces;
if (isSection(trimmedLine, currentSection))
{
if (!keyUpdated && strcmp(previousSection, section) == 0)
{
strcat(newContent, keyStr);
strcat(newContent, useSpaces ? " = " : "=");
strcat(newContent, valueStr);
strcat(newContent, "\r\n");
keyUpdated = true;
}
strcpy(previousSection, currentSection);
strcat(newContent, line);
strcat(newContent, "\r\n");
inGlobalSection = false;
currentLine = strtok(NULL, "\r\n");
continue;
}
if (isKeyValuePair(trimmedLine, foundKey, foundValue, lineHasSpaces))
{
if (!firstFormatDetected)
{
useSpaces = lineHasSpaces;
firstFormatDetected = true;
}
if ((inGlobalSection || strcmp(currentSection, section) == 0) && strcmp(foundKey, keyStr) == 0)
{
strcat(newContent, keyStr);
strcat(newContent, useSpaces ? " = " : "=");
strcat(newContent, valueStr);
strcat(newContent, "\r\n");
keyUpdated = true;
currentLine = strtok(NULL, "\r\n");
continue;
}
}
strcat(newContent, line);
strcat(newContent, "\r\n");
currentLine = strtok(NULL, "\r\n");
}
2025-05-17 21:29:46 -04:00
}
if (!keyUpdated)
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
// Add the new section and key-value if it wasn't found and updated
if ((!inGlobalSection && strcmp(currentSection, section) != 0)
|| (inGlobalSection && !isNullOrEmpty(section)))
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
strcat(newContent, "[");
strcat(newContent, section);
2025-05-24 09:10:13 -04:00
strcat(newContent, "]\r\n");
2025-05-17 21:29:46 -04:00
}
2025-05-23 22:36:35 -04:00
strcat(newContent, keyStr);
strcat(newContent, useSpaces ? " = " : "=");
strcat(newContent, valueStr);
2025-05-24 09:10:13 -04:00
strcat(newContent, "\r\n");
2025-05-17 21:29:46 -04:00
}
2025-05-23 22:36:35 -04:00
// Open the file again for writing
file = fopen(filename, "wb");
2025-05-20 17:32:37 -04:00
if (!file)
{
2025-05-31 22:12:31 -04:00
if (fileContent) delete[] fileContent;
2025-05-23 22:36:35 -04:00
delete[] newContent;
2025-05-17 21:29:46 -04:00
return false;
}
2025-05-20 17:32:37 -04:00
2025-05-23 22:36:35 -04:00
// Write the updated content to the file
fwrite(newContent, sizeof(char), strlen(newContent), file);
2025-05-20 17:32:37 -04:00
2025-05-23 22:36:35 -04:00
// Clean up
2025-05-20 17:32:37 -04:00
fclose(file);
2025-05-31 22:12:31 -04:00
if (fileContent) delete[] fileContent;
2025-05-23 22:36:35 -04:00
delete[] newContent;
2025-05-17 21:29:46 -04:00
return true;
}
pointerVector<char*>* IniUtility::GetSectionNames(const char* filename)
{
2025-05-20 17:32:37 -04:00
FILE* file = fopen(filename, "r");
2025-05-17 21:29:46 -04:00
if (!file)
2025-05-20 17:32:37 -04:00
{
2025-05-17 21:29:46 -04:00
return new pointerVector<char*>(false);
}
2025-05-20 17:32:37 -04:00
char line[MAX_LINE_SIZE];
2025-05-17 21:29:46 -04:00
pointerVector<char*>* sections = new pointerVector<char*>(false);
2025-05-20 17:32:37 -04:00
while (fgets(line, sizeof(line), file))
{
char sectionName[256];
2025-05-17 21:29:46 -04:00
if (isSection(trim(line), sectionName))
2025-05-20 17:32:37 -04:00
{
char* section = strdup(sectionName);
2025-05-17 21:29:46 -04:00
sections->add(section);
}
}
2025-05-20 17:32:37 -04:00
fclose(file);
2025-05-17 21:29:46 -04:00
return sections;
}
pointerVector<char*>* IniUtility::GetSectionKeys(const char* filename, const char* section)
{
2025-05-20 17:32:37 -04:00
FILE* file = fopen(filename, "r");
2025-05-17 21:29:46 -04:00
if (!file)
2025-05-20 17:32:37 -04:00
{
2025-05-17 21:29:46 -04:00
return new pointerVector<char*>(false);
}
2025-05-20 17:32:37 -04:00
char line[MAX_LINE_SIZE], currentSection[256];
2025-05-17 21:29:46 -04:00
pointerVector<char*>* keys = new pointerVector<char*>(false);
2025-05-23 22:36:35 -04:00
bool inGlobalSection = isNullOrEmpty(section);
2025-05-17 21:29:46 -04:00
2025-05-20 17:32:37 -04:00
while (fgets(line, sizeof(line), file))
{
char* trimmedLine = trim(line);
if (*trimmedLine == '\0' || *trimmedLine == ';') continue;
2025-05-17 21:29:46 -04:00
if (isSection(trimmedLine, currentSection))
2025-05-20 17:32:37 -04:00
{
2025-05-17 21:29:46 -04:00
inGlobalSection = false;
2025-05-20 17:32:37 -04:00
if (strcmp(currentSection, section) == 0)
{
2025-05-17 21:29:46 -04:00
inGlobalSection = true;
}
continue;
}
2025-05-20 17:32:37 -04:00
if (inGlobalSection || strcmp(currentSection, section) == 0)
{
char key[256], value[MAX_VALUE_SIZE];
2025-05-17 21:29:46 -04:00
bool hasSpaces;
if (isKeyValuePair(trimmedLine, key, value, hasSpaces))
2025-05-20 17:32:37 -04:00
{
char* keyCStr = strdup(key);
2025-05-17 21:29:46 -04:00
keys->add(keyCStr);
}
}
}
2025-05-20 17:32:37 -04:00
fclose(file);
2025-05-17 21:29:46 -04:00
return keys;
}
bool IniUtility::DeleteKey(const char* filename, const char* section, const char* key)
{
2025-05-23 22:36:35 -04:00
FILE* file = fopen(filename, "rb");
2025-05-20 17:32:37 -04:00
if (!file)
{
2025-05-17 21:29:46 -04:00
return false;
}
2025-05-23 22:36:35 -04:00
// Get file size
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
// Allocate memory to read the entire file
char* fileContent = new char[fileSize + 1];
if (!fileContent)
2025-05-20 17:32:37 -04:00
{
fclose(file);
return false;
}
2025-05-23 22:36:35 -04:00
// Read the entire file into memory
fread(fileContent, 1, fileSize, file);
fileContent[fileSize] = '\0'; // Null terminate the string
fclose(file);
// Prepare buffer for the new content
char* newContent = new char[fileSize + 1];
if (!newContent)
{
delete[] fileContent;
return false;
}
newContent[0] = '\0'; // Start with an empty string
2025-05-20 17:32:37 -04:00
char line[MAX_LINE_SIZE], currentSection[256];
2025-05-17 21:29:46 -04:00
bool keyDeleted = false;
2025-05-23 22:36:35 -04:00
bool inGlobalSection = isNullOrEmpty(section);
2025-05-17 21:29:46 -04:00
2025-05-24 09:10:13 -04:00
char* currentLine = strtok(fileContent, "\r\n");
2025-05-23 22:36:35 -04:00
while (currentLine)
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
strncpy(line, currentLine, sizeof(line) - 1);
line[sizeof(line) - 1] = '\0'; // Ensure null-termination
2025-05-20 17:32:37 -04:00
char* trimmedLine = trim(line);
2025-05-23 22:36:35 -04:00
2025-05-20 17:32:37 -04:00
if (*trimmedLine == '\0' || *trimmedLine == ';')
{
2025-05-23 22:36:35 -04:00
strcat(newContent, line);
2025-05-24 09:10:13 -04:00
strcat(newContent, "\r\n");
currentLine = strtok(NULL, "\r\n");
2025-05-17 21:29:46 -04:00
continue;
}
2025-05-20 17:32:37 -04:00
char foundKey[256], foundValue[MAX_VALUE_SIZE];
2025-05-17 21:29:46 -04:00
bool hasSpaces;
if (isSection(trimmedLine, currentSection))
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
strcat(newContent, line);
2025-05-24 09:10:13 -04:00
strcat(newContent, "\r\n");
2025-05-17 21:29:46 -04:00
inGlobalSection = false;
2025-05-24 09:10:13 -04:00
currentLine = strtok(NULL, "\r\n");
2025-05-17 21:29:46 -04:00
continue;
}
2025-05-20 17:32:37 -04:00
if ((inGlobalSection || strcmp(currentSection, section) == 0) && isKeyValuePair(trimmedLine, foundKey, foundValue, hasSpaces))
{
if (strcmp(foundKey, key) == 0)
{
2025-05-17 21:29:46 -04:00
keyDeleted = true;
2025-05-24 09:10:13 -04:00
currentLine = strtok(NULL, "\r\n");
2025-05-20 17:32:37 -04:00
continue; // Skip writing this line to delete the key
2025-05-17 21:29:46 -04:00
}
}
2025-05-23 22:36:35 -04:00
strcat(newContent, line);
2025-05-24 09:10:13 -04:00
strcat(newContent, "\r\n");
currentLine = strtok(NULL, "\r\n");
2025-05-17 21:29:46 -04:00
}
if (!keyDeleted)
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
delete[] fileContent;
delete[] newContent;
2025-05-17 21:29:46 -04:00
return false;
}
2025-05-23 22:36:35 -04:00
// Open the file again for writing
file = fopen(filename, "wb");
2025-05-20 17:32:37 -04:00
if (!file)
{
2025-05-23 22:36:35 -04:00
delete[] fileContent;
delete[] newContent;
2025-05-17 21:29:46 -04:00
return false;
}
2025-05-20 17:32:37 -04:00
2025-05-23 22:36:35 -04:00
// Write the updated content to the file
fwrite(newContent, sizeof(char), strlen(newContent), file);
2025-05-20 17:32:37 -04:00
2025-05-23 22:36:35 -04:00
// Clean up
2025-05-20 17:32:37 -04:00
fclose(file);
2025-05-23 22:36:35 -04:00
delete[] fileContent;
delete[] newContent;
2025-05-17 21:29:46 -04:00
return true;
}
bool IniUtility::DeleteSection(const char* filename, const char* section)
{
2025-05-23 22:36:35 -04:00
FILE* file = fopen(filename, "rb");
2025-05-20 17:32:37 -04:00
if (!file)
{
2025-05-17 21:29:46 -04:00
return false;
}
2025-05-23 22:36:35 -04:00
// Get file size
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
// Allocate memory to read the entire file
char* fileContent = new char[fileSize + 1];
if (!fileContent)
2025-05-20 17:32:37 -04:00
{
fclose(file);
return false;
}
2025-05-23 22:36:35 -04:00
// Read the entire file into memory
fread(fileContent, 1, fileSize, file);
fileContent[fileSize] = '\0'; // Null terminate the string
fclose(file);
// Prepare buffer for the new content
char* newContent = new char[fileSize + 1];
if (!newContent)
{
delete[] fileContent;
return false;
}
newContent[0] = '\0'; // Start with an empty string
2025-05-31 22:12:31 -04:00
char line[MAX_LINE_SIZE];
2025-05-17 21:29:46 -04:00
bool sectionDeleted = false;
bool inTargetSection = false;
2025-05-23 22:36:35 -04:00
bool deleteGlobal = isNullOrEmpty(section);
2025-05-17 21:29:46 -04:00
2025-05-24 09:10:13 -04:00
char* currentLine = strtok(fileContent, "\r\n");
2025-05-23 22:36:35 -04:00
while (currentLine)
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
strncpy(line, currentLine, sizeof(line) - 1);
line[sizeof(line) - 1] = '\0'; // Ensure null-termination
2025-05-20 17:32:37 -04:00
char* trimmedLine = trim(line);
2025-05-17 21:29:46 -04:00
2025-05-20 17:32:37 -04:00
if (*trimmedLine == '\0' || *trimmedLine == ';')
{
2025-05-17 21:29:46 -04:00
if (!inTargetSection)
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
strcat(newContent, line);
2025-05-24 09:10:13 -04:00
strcat(newContent, "\r\n");
2025-05-17 21:29:46 -04:00
}
2025-05-24 09:10:13 -04:00
currentLine = strtok(NULL, "\r\n");
2025-05-17 21:29:46 -04:00
continue;
}
2025-05-20 17:32:37 -04:00
char sectionName[256];
2025-05-17 21:29:46 -04:00
if (isSection(trimmedLine, sectionName))
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
if (inTargetSection)
2025-05-20 17:32:37 -04:00
{
2025-05-17 21:29:46 -04:00
inTargetSection = false;
2025-05-23 22:36:35 -04:00
sectionDeleted = true; // Mark section deletion complete
2025-05-17 21:29:46 -04:00
}
2025-05-20 17:32:37 -04:00
if (!deleteGlobal && strcmp(sectionName, section) == 0)
{
2025-05-17 21:29:46 -04:00
inTargetSection = true;
sectionDeleted = true;
2025-05-24 09:10:13 -04:00
currentLine = strtok(NULL, "\r\n");
2025-05-20 17:32:37 -04:00
continue; // Skip writing this section
2025-05-17 21:29:46 -04:00
}
}
2025-05-23 22:36:35 -04:00
if (!inTargetSection)
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
strcat(newContent, line);
2025-05-24 09:10:13 -04:00
strcat(newContent, "\r\n");
2025-05-17 21:29:46 -04:00
}
2025-05-24 09:10:13 -04:00
currentLine = strtok(NULL, "\r\n");
2025-05-17 21:29:46 -04:00
}
if (!sectionDeleted && !deleteGlobal)
2025-05-20 17:32:37 -04:00
{
2025-05-23 22:36:35 -04:00
delete[] fileContent;
delete[] newContent;
2025-05-17 21:29:46 -04:00
return false;
}
2025-05-23 22:36:35 -04:00
// Open the file again for writing
file = fopen(filename, "wb");
2025-05-20 17:32:37 -04:00
if (!file)
{
2025-05-23 22:36:35 -04:00
delete[] fileContent;
delete[] newContent;
2025-05-17 21:29:46 -04:00
return false;
}
2025-05-20 17:32:37 -04:00
2025-05-23 22:36:35 -04:00
// Write the updated content to the file
fwrite(newContent, sizeof(char), strlen(newContent), file);
2025-05-20 17:32:37 -04:00
2025-05-23 22:36:35 -04:00
// Clean up
2025-05-20 17:32:37 -04:00
fclose(file);
2025-05-23 22:36:35 -04:00
delete[] fileContent;
delete[] newContent;
2025-05-17 21:29:46 -04:00
return true;
}