#include "IniUtility.h" #include #include #include "pointerVector.h" namespace { char* trim(char* str) { if (str == NULL) return NULL; // Trim leading spaces char* start = str; while (*start == ' ' || *start == '\t' || *start == '\r' || *start == '\n') start++; // Trim trailing spaces char* end = start + strlen(start) - 1; while (end > start && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n')) end--; *(end + 1) = '\0'; return start; } 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; } } return false; } 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); return true; } return false; } } char* IniUtility::GetValue(const char* filename, const char* section, const char* key) { FILE* file = fopen(filename, "r"); if (!file) return strdup(""); char line[MAX_LINE_SIZE], currentSection[256]; char keyStr[256]; strcpy(keyStr, key); bool inGlobalSection = isNullOrEmpty(section); while (fgets(line, sizeof(line), file)) { char* trimmedLine = trim(line); if (*trimmedLine == '\0' || *trimmedLine == ';') continue; if (isSection(trimmedLine, currentSection)) { inGlobalSection = false; if (strcmp(currentSection, section) == 0) { inGlobalSection = true; } continue; } char foundKey[256], foundValue[MAX_VALUE_SIZE]; bool hasSpaces; if (isKeyValuePair(trimmedLine, foundKey, foundValue, hasSpaces)) { if ((inGlobalSection || strcmp(currentSection, section) == 0) && strcmp(foundKey, key) == 0) { char* result = strdup(foundValue); fclose(file); return result; } } } fclose(file); return strdup(""); } bool IniUtility::SetValue(const char* filename, const char* section, const char* key, const char* value) { FILE* file = fopen(filename, "rb"); bool fileExists = (file != NULL); char* fileContent = NULL; long fileSize = 0; if (fileExists) { // Get file size fseek(file, 0, SEEK_END); fileSize = ftell(file); fseek(file, 0, SEEK_SET); 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); } // Prepare buffer for the new content char* newContent = new char[fileSize + 1280]; // Allocate some extra space for new content if (!newContent) { if (fileContent) delete[] fileContent; return false; } newContent[0] = '\0'; // Start with an empty string char line[MAX_LINE_SIZE], currentSection[256], previousSection[256] = ""; char keyStr[256], valueStr[MAX_VALUE_SIZE]; strcpy(keyStr, key); strcpy(valueStr, value); bool keyUpdated = false; bool inGlobalSection = true; bool firstFormatDetected = false; bool useSpaces = false; // Determines if spaces should be used around '=' if (fileExists && fileContent) { char* currentLine = strtok(fileContent, "\r\n"); while (currentLine) { strncpy(line, currentLine, sizeof(line) - 1); line[sizeof(line) - 1] = '\0'; // Ensure null-termination char* trimmedLine = trim(line); if (*trimmedLine == '\0' || *trimmedLine == ';') { strcat(newContent, line); strcat(newContent, "\r\n"); currentLine = strtok(NULL, "\r\n"); continue; } 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"); } } if (!keyUpdated) { // Add the new section and key-value if it wasn't found and updated if ((!inGlobalSection && strcmp(currentSection, section) != 0) || (inGlobalSection && !isNullOrEmpty(section))) { strcat(newContent, "["); strcat(newContent, section); strcat(newContent, "]\r\n"); } strcat(newContent, keyStr); strcat(newContent, useSpaces ? " = " : "="); strcat(newContent, valueStr); strcat(newContent, "\r\n"); } // Open the file again for writing file = fopen(filename, "wb"); if (!file) { if (fileContent) delete[] fileContent; delete[] newContent; return false; } // Write the updated content to the file fwrite(newContent, sizeof(char), strlen(newContent), file); // Clean up fclose(file); if (fileContent) delete[] fileContent; delete[] newContent; return true; } pointerVector* IniUtility::GetSectionNames(const char* filename) { FILE* file = fopen(filename, "r"); if (!file) { return new pointerVector(false); } char line[MAX_LINE_SIZE]; pointerVector* sections = new pointerVector(false); while (fgets(line, sizeof(line), file)) { char sectionName[256]; if (isSection(trim(line), sectionName)) { char* section = strdup(sectionName); sections->add(section); } } fclose(file); return sections; } pointerVector* IniUtility::GetSectionKeys(const char* filename, const char* section) { FILE* file = fopen(filename, "r"); if (!file) { return new pointerVector(false); } char line[MAX_LINE_SIZE], currentSection[256]; pointerVector* keys = new pointerVector(false); bool inGlobalSection = isNullOrEmpty(section); while (fgets(line, sizeof(line), file)) { char* trimmedLine = trim(line); if (*trimmedLine == '\0' || *trimmedLine == ';') continue; if (isSection(trimmedLine, currentSection)) { inGlobalSection = false; if (strcmp(currentSection, section) == 0) { inGlobalSection = true; } continue; } if (inGlobalSection || strcmp(currentSection, section) == 0) { char key[256], value[MAX_VALUE_SIZE]; bool hasSpaces; if (isKeyValuePair(trimmedLine, key, value, hasSpaces)) { char* keyCStr = strdup(key); keys->add(keyCStr); } } } fclose(file); return keys; } bool IniUtility::DeleteKey(const char* filename, const char* section, const char* key) { FILE* file = fopen(filename, "rb"); if (!file) { return false; } // 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) { fclose(file); return false; } // 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 char line[MAX_LINE_SIZE], currentSection[256]; bool keyDeleted = false; bool inGlobalSection = isNullOrEmpty(section); char* currentLine = strtok(fileContent, "\r\n"); while (currentLine) { strncpy(line, currentLine, sizeof(line) - 1); line[sizeof(line) - 1] = '\0'; // Ensure null-termination char* trimmedLine = trim(line); if (*trimmedLine == '\0' || *trimmedLine == ';') { strcat(newContent, line); strcat(newContent, "\r\n"); currentLine = strtok(NULL, "\r\n"); continue; } char foundKey[256], foundValue[MAX_VALUE_SIZE]; bool hasSpaces; if (isSection(trimmedLine, currentSection)) { strcat(newContent, line); strcat(newContent, "\r\n"); inGlobalSection = false; currentLine = strtok(NULL, "\r\n"); continue; } if ((inGlobalSection || strcmp(currentSection, section) == 0) && isKeyValuePair(trimmedLine, foundKey, foundValue, hasSpaces)) { if (strcmp(foundKey, key) == 0) { keyDeleted = true; currentLine = strtok(NULL, "\r\n"); continue; // Skip writing this line to delete the key } } strcat(newContent, line); strcat(newContent, "\r\n"); currentLine = strtok(NULL, "\r\n"); } if (!keyDeleted) { delete[] fileContent; delete[] newContent; return false; } // Open the file again for writing file = fopen(filename, "wb"); if (!file) { delete[] fileContent; delete[] newContent; return false; } // Write the updated content to the file fwrite(newContent, sizeof(char), strlen(newContent), file); // Clean up fclose(file); delete[] fileContent; delete[] newContent; return true; } bool IniUtility::DeleteSection(const char* filename, const char* section) { FILE* file = fopen(filename, "rb"); if (!file) { return false; } // 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) { fclose(file); return false; } // 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 char line[MAX_LINE_SIZE]; bool sectionDeleted = false; bool inTargetSection = false; bool deleteGlobal = isNullOrEmpty(section); char* currentLine = strtok(fileContent, "\r\n"); while (currentLine) { strncpy(line, currentLine, sizeof(line) - 1); line[sizeof(line) - 1] = '\0'; // Ensure null-termination char* trimmedLine = trim(line); if (*trimmedLine == '\0' || *trimmedLine == ';') { if (!inTargetSection) { strcat(newContent, line); strcat(newContent, "\r\n"); } currentLine = strtok(NULL, "\r\n"); continue; } char sectionName[256]; if (isSection(trimmedLine, sectionName)) { if (inTargetSection) { inTargetSection = false; sectionDeleted = true; // Mark section deletion complete } if (!deleteGlobal && strcmp(sectionName, section) == 0) { inTargetSection = true; sectionDeleted = true; currentLine = strtok(NULL, "\r\n"); continue; // Skip writing this section } } if (!inTargetSection) { strcat(newContent, line); strcat(newContent, "\r\n"); } currentLine = strtok(NULL, "\r\n"); } if (!sectionDeleted && !deleteGlobal) { delete[] fileContent; delete[] newContent; return false; } // Open the file again for writing file = fopen(filename, "wb"); if (!file) { delete[] fileContent; delete[] newContent; return false; } // Write the updated content to the file fwrite(newContent, sizeof(char), strlen(newContent), file); // Clean up fclose(file); delete[] fileContent; delete[] newContent; return true; }