2 Copyright 2004-2005 Chris Tallon
3 Copyright 2004-2005 University Of Bradford
5 This file is part of VOMP.
7 VOMP is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 VOMP is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with VOMP; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 log = Log::getInstance();
31 int Config::init(char* takeFileName)
33 if (initted) return 1;
35 pthread_mutex_init(&fileLock, NULL);
37 if (strlen(takeFileName) > (MAX_FILENAME_LENGTH - 1))
39 log->log("Config", Log::DEBUG, "Config error: Config filename too long");
43 strcpy(fileName, takeFileName);
44 strcpy(fileNameTemp, takeFileName);
45 strcat(fileNameTemp, ".tmp");
47 file = fopen(fileName, "r");
50 file = fopen(fileName, "w");
53 log->log("Config", Log::DEBUG, "Config error: Could not access config file");
60 log->log("Config", Log::DEBUG, "Opened config file: %s", fileName);
70 int Config::shutdown()
72 if (!initted) return 1;
74 pthread_mutex_lock(&fileLock);
76 pthread_mutex_unlock(&fileLock);
77 pthread_mutex_destroy(&fileLock);
82 int Config::openFile()
84 if (!initted) return 0;
85 if (pthread_mutex_lock(&fileLock))
87 log->log("Config", Log::DEBUG, "Config error: Could not get lock");
92 log->log("Config", Log::DEBUG, "Config error: Initted 0 after lock");
93 pthread_mutex_unlock(&fileLock);
97 file = fopen(fileName, "r");
100 log->log("Config", Log::DEBUG, "Config error: Could not open config file");
101 pthread_mutex_unlock(&fileLock);
107 void Config::closeFile()
109 if (!initted) return;
113 pthread_mutex_unlock(&fileLock);
116 int Config::readLine()
118 if (!initted || !file) { log->log("Config", Log::DEBUG, "1"); return 0; }
119 if (!fgets(buffer, BUFFER_LENGTH-1, file)) { /*log->log("Config", Log::DEBUG, "2");*/ return 0; }
120 lastLineLength = strlen(buffer);
121 // log->log("Config", Log::DEBUG, "buffer before trim: '%s'", buffer);
123 // log->log("Config", Log::DEBUG, "buffer after trim: '%s'", buffer);
129 FILE* Config::copyToHere(long position)
131 FILE* newFile = fopen(fileNameTemp, "w");
133 if (!newFile) return NULL;
138 while (newPos < position)
140 fgets(buffer, BUFFER_LENGTH-1, file);
141 fputs(buffer, newFile);
142 newPos += strlen(buffer);
147 int Config::copyRest(FILE* newFile)
151 while(fgets(buffer, BUFFER_LENGTH-1, file))
153 fputs(buffer, newFile);
161 if (newFile) rename(fileNameTemp, fileName);
163 pthread_mutex_unlock(&fileLock);
167 int Config::deleteValue(const char* section, char* key)
169 if (!initted) return 0;
170 if (!openFile()) return 0;
172 if (!findSection(section))
175 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
181 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
185 FILE* newFile = copyToHere(ftell(file) - lastLineLength);
186 fgets(buffer, BUFFER_LENGTH-1, file);
188 return copyRest(newFile);
191 int Config::setValueLong(const char* section, char* key, long newValue)
194 sprintf(longBuffer, "%li", newValue);
195 return setValueString(section, key, longBuffer);
198 int Config::setValueLongLong(char* section, char* key, long long newValue)
201 sprintf(longBuffer, "%lli", newValue);
202 return setValueString(section, key, longBuffer);
205 int Config::setValueDouble(char* section, char* key, double newValue)
207 char doubleBuffer[50];
208 sprintf(doubleBuffer, "%f", newValue);
209 return setValueString(section, key, doubleBuffer);
212 int Config::setValueString(const char* section, const char* key, const char* newValue)
214 if (!initted) return 0;
215 if (!openFile()) return 0;
217 if (findSection(section))
221 FILE* newFile = copyToHere(ftell(file) - lastLineLength);
225 log->log("Config", Log::DEBUG, "Config error: Could not write temp config file");
229 fgets(buffer, BUFFER_LENGTH-1, file);
230 fprintf(newFile, "%s = %s\n", key, newValue);
231 return copyRest(newFile);
236 findSection(section);
237 FILE* newFile = copyToHere(ftell(file));
241 log->log("Config", Log::DEBUG, "Config error: Could not write temp config file");
245 fprintf(newFile, "%s = %s\n", key, newValue);
246 return copyRest(newFile);
252 fseek(file, 0, SEEK_END);
253 FILE* newFile = copyToHere(ftell(file));
257 log->log("Config", Log::DEBUG, "Config error: Could not write temp config file");
261 fprintf(newFile, "[%s]\n%s = %s\n", section, key, newValue);
262 return copyRest(newFile);
266 char* Config::getSectionKeyNames(const char* section, int& numberOfReturns, int& allKeysSize)
270 char* allKeys = NULL;
271 int allKeysIndex = 0;
275 if (!initted) return NULL;
276 if (!openFile()) return NULL;
277 if (!findSection(section)) return NULL;
279 char foundKey[BUFFER_LENGTH];
283 // Is this line a section header? if so, exit
284 if ((buffer[0] == '[') && (buffer[strlen(buffer)-1] == ']')) break;
286 equalspos = strstr(buffer, "=");
287 if (!equalspos) continue; // if there is no = then it's not a key
288 memcpy(foundKey, buffer, equalspos-buffer);
289 foundKey[equalspos-buffer] = '\0';
291 keyLength = strlen(foundKey);
292 allKeysSize += keyLength + 1;
293 allKeys = (char*)realloc(allKeys, allKeysSize);
294 memcpy(&allKeys[allKeysIndex], foundKey, keyLength);
295 allKeysIndex += keyLength;
296 allKeys[allKeysIndex] = '\0';
308 int Config::findSection(const char* section)
310 if (!initted || !file) return 0;
311 if (strlen(section) > (BUFFER_LENGTH-2))
313 log->log("Config", Log::DEBUG, "Config error: Section given exceeds max length");
317 char toFind[BUFFER_LENGTH];
320 strcat(toFind, section);
325 // log->log("Config", Log::DEBUG, "to find '%s' this line '%s'", toFind, buffer);
326 if (!strcmp(toFind, buffer)) return 1;
331 int Config::findKey(const char* key)
333 if (!initted || !file) return 0;
335 if (strlen(key) > (BUFFER_LENGTH-1))
337 log->log("Config", Log::DEBUG, "Config error: Key given exceeds max length");
341 char prepForTest[BUFFER_LENGTH];
343 // do a rough search first, this could match substrings that we don't want
346 // Is this line a section header? if so, exit
347 if ((buffer[0] == '[') && (buffer[strlen(buffer)-1] == ']')) return 0;
348 if (strstr(buffer, key))
350 // rough search found match
351 char* equalspos = strstr(buffer, "=");
352 if (!equalspos) continue;
353 memcpy(prepForTest, buffer, equalspos-buffer);
354 prepForTest[equalspos-buffer] = '\0';
357 if (!strcmp(key, prepForTest))
359 // in buffer, set all up to equals to space, then trim!
360 for(char* curPos = buffer; curPos <= equalspos; curPos++)
372 char* Config::getValueString(const char* section, const char* key)
374 if (!initted) return NULL;
375 if (!openFile()) return NULL;
377 if (!findSection(section))
380 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
386 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
390 char* returnString = new char[strlen(buffer)+1];
391 strcpy(returnString, buffer);
398 long Config::getValueLong(const char* section, const char* key, int* failure)
401 if (!initted) return 0;
402 if (!openFile()) return 0;
404 if (!findSection(section))
407 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
413 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
419 long retVal = strtol(buffer, &check, 10);
420 if ((retVal == 0) && (check == buffer)) *failure = 1;
426 long long Config::getValueLongLong(char* section, char* key, int* failure)
429 if (!initted) return 0;
430 if (!openFile()) return 0;
432 if (!findSection(section))
435 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
441 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
447 long long retVal = strtoll(buffer, &check, 10);
448 if ((retVal == 0) && (check == buffer)) *failure = 1;
454 double Config::getValueDouble(char* section, char* key, int* failure)
457 if (!initted) return 0;
458 if (!openFile()) return 0;
460 if (!findSection(section))
463 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
469 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
476 double retVal = strtod(buffer, &check);
477 if ((retVal == 0) && (check == buffer)) *failure = 1;
486 void Config::trim(char* str)
488 int pos, len, start, end;
492 for(pos = 0; pos < len; pos++)
494 if ((str[pos] == '#') || (str[pos] == ';'))
496 // Mod. If #/; is at start of line ok. Else, if it is after a space, ok.
498 if ((pos == 0) || (isspace(str[pos - 1])))
512 while(isspace(str[start])) start++;
513 while(isspace(str[end-1]))
522 for(pos = start; pos < end; pos++) str[pos - start] = str[pos];
523 str[end - start] = '\0';