PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/Tools/FileFormats/Parse.cpp

https://github.com/shashankthebest/robocup
C++ | 248 lines | 183 code | 29 blank | 36 comment | 90 complexity | 0c96dca0758bfca347cedf1f9725ffad MD5 | raw file
Possible License(s): GPL-3.0
  1. #include "Parse.h"
  2. #include <iostream>
  3. #include <string.h>
  4. using namespace std;
  5. #define strcmpi strcmp
  6. Parse::Parse() {
  7. // hmm !
  8. }
  9. // Detects both CR and LF characters
  10. bool Parse::IsTerminator(const char c) {
  11. if (c == char(13) || c == (char)10)
  12. return true;
  13. return false;
  14. }
  15. // Only DOS has these.
  16. bool Parse::IsLF(const char c) {
  17. if (c == (char)13)
  18. return true;
  19. return false;
  20. }
  21. // Detects spaces AND tab characters.
  22. bool Parse::IsSpace(const char c) {
  23. if (c == ' ' || c == '\t')
  24. return true;
  25. return false;
  26. }
  27. void Parse::WriteFile(const char* filename, const char* buffer, int buffersize) {
  28. printf("Config: Writing %s.\n",filename);
  29. FILE* f = fopen("/ms/open-r/mw/test.t","wb");
  30. if (f != NULL) {
  31. fwrite(buffer,1,buffersize,f);
  32. fclose(f);
  33. } else {
  34. cout << "Parse: unable to open file for writing" << endl << flush;
  35. }
  36. }
  37. // This code is dirty, but it seems to be indestructible. I haven't found anything
  38. // that can crash it outright.
  39. // It parses the specified file as a config file, looking for key,value pairs. These
  40. // are stored in a vector using RegisterPair().
  41. bool Parse::ParseFile(const char* filename) {
  42. //printf("Config: Loading %s.\n", filename);
  43. FILE* f = fopen(filename,"rb");
  44. if (f == NULL) {
  45. printf("Config: Unable to open file %s.\n",filename);
  46. return false;
  47. }
  48. fseek(f,0,SEEK_END);
  49. long filesize = ftell(f);
  50. rewind(f);
  51. char* filebuffer = (char*) malloc(filesize);
  52. if (filebuffer == NULL) {
  53. printf("Config: Unable to malloc %d bytes required to parse %s.\n",(int)filesize,filename);
  54. return false;
  55. }
  56. fread(filebuffer,1,filesize,f);
  57. fclose(f);
  58. int i = 0;
  59. int linenumber=0;
  60. while (i < filesize) {
  61. char* keystring = (char*)malloc(MAX_KEYLENGTH);
  62. char* valstring = (char*)malloc(MAX_VALLENGTH);
  63. linenumber++;
  64. int k = 0;
  65. // ignore opening spaces
  66. while (i < filesize && IsSpace(filebuffer[i])) i++;
  67. // read up to =
  68. while (filebuffer[i] != '=' && IsTerminator(filebuffer[i]) == false && i < filesize && k < MAX_KEYLENGTH) {
  69. keystring[k] = filebuffer[i];
  70. k++;
  71. i++;
  72. }
  73. // if keystring is empty or starts with a [, # or //, we ignore this line.
  74. if (k == 0 || keystring[0] == '[' || keystring[0] == '#' || (k > 1 && keystring[0] == '/' && keystring[1] == '/')) {
  75. // ignore line !
  76. while (i < filesize && IsTerminator(filebuffer[i]) == false) i++;
  77. i++;
  78. if (IsLF(filebuffer[i-1])) i++;
  79. free(keystring);
  80. free(valstring);
  81. continue;
  82. }
  83. // check for non-empty key, with NO equals. if this wasn't caught above, then we have an invalid line !
  84. if (filebuffer[i] != '=' || k >= MAX_KEYLENGTH) {
  85. while (i < filesize && IsTerminator(filebuffer[i]) == false) i++;
  86. i++;
  87. // did anyone ever understand this?
  88. if (IsLF(filebuffer[i-1])) i++;
  89. printf("Config: Error on line %d of file %s - ",linenumber,filename);
  90. if (k >= MAX_KEYLENGTH) {
  91. printf("Key too long.\n");
  92. } else printf("Missing equals.\n");
  93. free(keystring);
  94. free(valstring);
  95. continue;
  96. }
  97. // remove trailing spaces
  98. while (k > 0 && IsSpace(keystring[k-1])) k--;
  99. keystring[k]='\0';
  100. k=0;
  101. // ignore =
  102. i++;
  103. // ignore whitespace after =
  104. while (i < filesize && IsSpace(filebuffer[i])) i++;
  105. // read till end of line.
  106. while (i < filesize && IsTerminator(filebuffer[i]) == false && k < MAX_VALLENGTH) {
  107. valstring[k] = filebuffer[i];
  108. k++;
  109. i++;
  110. }
  111. if (k >= MAX_VALLENGTH) {
  112. while (i < filesize && IsTerminator(filebuffer[i]) == false) i++;
  113. i++;
  114. if (IsLF(filebuffer[i-1])) i++;
  115. printf("Config: Error on line %d of file %s - ",linenumber,filename);
  116. printf("Value was too long.\n");
  117. continue;
  118. }
  119. i++;
  120. // make sure we really did hit the end of the line... need to be in the right place for next read. this is dos's fault !
  121. if (IsLF(filebuffer[i-1])) i++;
  122. // remove trailing spaces
  123. while (k > 0 && IsSpace(valstring[k-1])) k--;
  124. valstring[k]='\0';
  125. RegisterPair(keystring,valstring);
  126. }
  127. free(filebuffer);
  128. return true;
  129. }
  130. // store the specified key,value pair in our vector.
  131. // if the key already exists, it is overwritten (with a warning)
  132. void Parse::RegisterPair(char* k,char* v) {
  133. Pair* p = FindPairFailFast(k);
  134. // key, value pair already exists
  135. if (p != NULL) {
  136. // value changed when we reloaded it ! warn user.
  137. if (strcmpi(p->val,v)!=0) {
  138. printf("Config: WARNING! Pair (%s,%s) is now (%s,%s).\n",p->key,p->val, k, v);
  139. }
  140. free(p->val);
  141. p->val = v;
  142. return;
  143. }
  144. Pair newp;
  145. newp.key = k;
  146. newp.val = v;
  147. keyValuePairs.push_back(newp);
  148. if (strlen(v) != 0) {
  149. //printf("Config: Registered (%s,%s).\n",newp.key,newp.val);
  150. } else {
  151. //printf("Config: Registered (%s,%s) (Value field empty!).\n",newp.key,newp.val);
  152. }
  153. }
  154. Pair* Parse::FindPair(const char* k) {
  155. for (unsigned int i = 0; i < keyValuePairs.size(); i++) {
  156. if (strcmpi(keyValuePairs[i].key,k)==0) {
  157. return &keyValuePairs[i];
  158. }
  159. }
  160. printf("Config: Unable to find key %s.\n",k);
  161. return NULL;
  162. }
  163. Pair* Parse::FindPairFailFast(const char* k) {
  164. for (unsigned int i = 0; i < keyValuePairs.size(); i++) {
  165. if (strcmpi(keyValuePairs[i].key,k)==0) {
  166. return &keyValuePairs[i];
  167. }
  168. }
  169. return NULL;
  170. }
  171. bool Parse::HasKey(const char* k){
  172. for (unsigned int i = 0; i < keyValuePairs.size(); i++) {
  173. if (strcmpi(keyValuePairs[i].key,k)==0) {
  174. return true;
  175. }
  176. }
  177. return false;
  178. }
  179. int Parse::GetAsInt(const char* k) {
  180. Pair* p = FindPair(k);
  181. if (p != NULL) {
  182. return atoi(p->val);
  183. }
  184. return -1;
  185. }
  186. double Parse::GetAsDouble(const char* k) {
  187. Pair* p = FindPair(k);
  188. if (p != NULL) {
  189. return atof(p->val);
  190. }
  191. return -1.0;
  192. }
  193. // Use with care !
  194. char* Parse::GetAsString(const char* k) {
  195. Pair* p = FindPair(k);
  196. if (p != NULL) {
  197. return p->val;
  198. }
  199. return NULL;
  200. }
  201. bool Parse::GetAsBool(const char* k) {
  202. Pair* p = FindPair(k);
  203. if (p != NULL) {
  204. // nb strcmpi is not ANSI C !
  205. if (strcmpi(p->val,"on")==0) {
  206. return true;
  207. } else if (strcmpi(p->val,"true") == 0) {
  208. return true;
  209. }
  210. }
  211. return false;
  212. }
  213. //int main() {
  214. // Parse p;
  215. // p.ParseFile("test.cfg");
  216. // char* test = p.GetAsString("test");
  217. // p.RegisterPair("test","hello");
  218. // test = p.GetAsString("test");
  219. //}