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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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);
65 int Config::shutdown()
67 if (!initted) return 1;
69 pthread_mutex_lock(&fileLock);
71 pthread_mutex_unlock(&fileLock);
72 pthread_mutex_destroy(&fileLock);
77 int Config::openFile()
79 if (!initted) return 0;
80 if (pthread_mutex_lock(&fileLock))
82 log->log("Config", Log::DEBUG, "Config error: Could not get lock");
87 log->log("Config", Log::DEBUG, "Config error: Initted 0 after lock");
88 pthread_mutex_unlock(&fileLock);
92 file = fopen(fileName, "r");
95 log->log("Config", Log::DEBUG, "Config error: Could not open config file");
96 pthread_mutex_unlock(&fileLock);
102 void Config::closeFile()
104 if (!initted) return;
108 pthread_mutex_unlock(&fileLock);
111 int Config::readLine()
113 if (!initted || !file) { log->log("Config", Log::DEBUG, "1"); return 0; }
114 if (!fgets(buffer, BUFFER_LENGTH-1, file)) { log->log("Config", Log::DEBUG, "2"); return 0; }
115 lastLineLength = strlen(buffer);
116 log->log("Config", Log::DEBUG, "buffer before trim: '%s'", buffer);
118 log->log("Config", Log::DEBUG, "buffer after trim: '%s'", buffer);
124 FILE* Config::copyToHere(long position)
126 FILE* newFile = fopen(fileNameTemp, "w");
128 if (!newFile) return NULL;
133 while (newPos < position)
135 fgets(buffer, BUFFER_LENGTH-1, file);
136 fputs(buffer, newFile);
137 newPos += strlen(buffer);
142 int Config::copyRest(FILE* newFile)
146 while(fgets(buffer, BUFFER_LENGTH-1, file))
148 fputs(buffer, newFile);
156 if (newFile) rename(fileNameTemp, fileName);
158 pthread_mutex_unlock(&fileLock);
162 int Config::deleteValue(char* section, char* key)
164 if (!initted) return 0;
165 if (!openFile()) return 0;
167 if (!findSection(section))
170 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
176 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
180 FILE* newFile = copyToHere(ftell(file) - lastLineLength);
181 fgets(buffer, BUFFER_LENGTH-1, file);
183 return copyRest(newFile);
186 int Config::setValueLong(char* section, char* key, long newValue)
189 sprintf(longBuffer, "%li", newValue);
190 return setValueString(section, key, longBuffer);
193 int Config::setValueLongLong(char* section, char* key, long long newValue)
196 sprintf(longBuffer, "%lli", newValue);
197 return setValueString(section, key, longBuffer);
200 int Config::setValueDouble(char* section, char* key, double newValue)
202 char doubleBuffer[50];
203 sprintf(doubleBuffer, "%f", newValue);
204 return setValueString(section, key, doubleBuffer);
207 int Config::setValueString(char* section, char* key, char* newValue)
209 if (!initted) return 0;
210 if (!openFile()) return 0;
212 if (findSection(section))
216 FILE* newFile = copyToHere(ftell(file) - lastLineLength);
220 log->log("Config", Log::DEBUG, "Config error: Could not write temp config file");
224 fgets(buffer, BUFFER_LENGTH-1, file);
225 fprintf(newFile, "%s = %s\n", key, newValue);
226 return copyRest(newFile);
231 findSection(section);
232 FILE* newFile = copyToHere(ftell(file));
236 log->log("Config", Log::DEBUG, "Config error: Could not write temp config file");
240 fprintf(newFile, "%s = %s\n", key, newValue);
241 return copyRest(newFile);
247 fseek(file, 0, SEEK_END);
248 FILE* newFile = copyToHere(ftell(file));
252 log->log("Config", Log::DEBUG, "Config error: Could not write temp config file");
256 fprintf(newFile, "[%s]\n%s = %s\n", section, key, newValue);
257 return copyRest(newFile);
261 char* Config::getSectionKeyNames(char* section, int& numberOfReturns, int& allKeysSize)
265 char* allKeys = NULL;
266 int allKeysIndex = 0;
270 if (!initted) return NULL;
271 if (!openFile()) return NULL;
272 if (!findSection(section)) return NULL;
274 char foundKey[BUFFER_LENGTH];
278 // Is this line a section header? if so, exit
279 if ((buffer[0] == '[') && (buffer[strlen(buffer)-1] == ']')) break;
281 equalspos = strstr(buffer, "=");
282 if (!equalspos) continue; // if there is no = then it's not a key
283 memcpy(foundKey, buffer, equalspos-buffer);
284 foundKey[equalspos-buffer] = '\0';
286 keyLength = strlen(foundKey);
287 allKeysSize += keyLength + 1;
288 allKeys = (char*)realloc(allKeys, allKeysSize);
289 memcpy(&allKeys[allKeysIndex], foundKey, keyLength);
290 allKeysIndex += keyLength;
291 allKeys[allKeysIndex] = '\0';
303 int Config::findSection(char* section)
305 if (!initted || !file) return 0;
306 if (strlen(section) > (BUFFER_LENGTH-2))
308 log->log("Config", Log::DEBUG, "Config error: Section given exceeds max length");
312 char toFind[BUFFER_LENGTH];
315 strcat(toFind, section);
320 log->log("Config", Log::DEBUG, "to find '%s' this line '%s'", toFind, buffer);
321 if (!strcmp(toFind, buffer)) return 1;
326 int Config::findKey(char* key)
328 if (!initted || !file) return 0;
330 if (strlen(key) > (BUFFER_LENGTH-1))
332 log->log("Config", Log::DEBUG, "Config error: Key given exceeds max length");
336 char prepForTest[BUFFER_LENGTH];
338 // do a rough search first, this could match substrings that we don't want
341 // Is this line a section header? if so, exit
342 if ((buffer[0] == '[') && (buffer[strlen(buffer)-1] == ']')) return 0;
343 if (strstr(buffer, key))
345 // rough search found match
346 char* equalspos = strstr(buffer, "=");
347 if (!equalspos) continue;
348 memcpy(prepForTest, buffer, equalspos-buffer);
349 prepForTest[equalspos-buffer] = '\0';
352 if (!strcmp(key, prepForTest))
354 // in buffer, set all up to equals to space, then trim!
355 for(char* curPos = buffer; curPos <= equalspos; curPos++)
367 char* Config::getValueString(char* section, char* key)
369 if (!initted) return NULL;
370 if (!openFile()) return NULL;
372 if (!findSection(section))
375 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
381 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
385 char* returnString = new char[strlen(buffer)+1];
386 strcpy(returnString, buffer);
393 long Config::getValueLong(char* section, char* key, int* failure)
396 if (!initted) return 0;
397 if (!openFile()) return 0;
399 if (!findSection(section))
402 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
408 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
414 long retVal = strtol(buffer, &check, 10);
415 if ((retVal == 0) && (check == buffer)) *failure = 1;
421 long long Config::getValueLongLong(char* section, char* key, int* failure)
424 if (!initted) return 0;
425 if (!openFile()) return 0;
427 if (!findSection(section))
430 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
436 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
442 long long retVal = strtoll(buffer, &check, 10);
443 if ((retVal == 0) && (check == buffer)) *failure = 1;
449 double Config::getValueDouble(char* section, char* key, int* failure)
452 if (!initted) return 0;
453 if (!openFile()) return 0;
455 if (!findSection(section))
458 log->log("Config", Log::DEBUG, "Config error: Section %s not found", section);
464 log->log("Config", Log::DEBUG, "Config error: Key %s not found", key);
471 double retVal = strtod(buffer, &check);
472 if ((retVal == 0) && (check == buffer)) *failure = 1;
481 void Config::trim(char* str)
483 int pos, len, start, end;
487 for(pos = 0; pos < len; pos++)
489 if ((str[pos] == '#') || (str[pos] == ';'))
491 // Mod. If #/; is at start of line ok. Else, if it is after a space, ok.
493 if ((pos == 0) || (isspace(str[pos - 1])))
507 while(isspace(str[start])) start++;
508 while(isspace(str[end-1]))
517 for(pos = start; pos < end; pos++) str[pos - start] = str[pos];
518 str[end - start] = '\0';