PageRenderTime 25ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/pud/src/posFile.c

http://github.com/zioproto/olsrd-gsoc2012
C | 238 lines | 190 code | 42 blank | 6 comment | 52 complexity | 36d50e2c6b8a222b75cc08b49eb21551 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-3.0, Apache-2.0
  1. #include "posFile.h"
  2. /* Plugin includes */
  3. #include "pud.h"
  4. #include "configuration.h"
  5. /* OLSR includes */
  6. /* System includes */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <regex.h>
  10. #include <sys/stat.h>
  11. #define LINE_LENGTH 256
  12. static const char * regexCommentString = "^([[:space:]]*|[[:space:]#]+.*)$";
  13. static const char * regexNameValueString =
  14. "^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*([^[:space:]]+)[[:space:]]*$";
  15. static const size_t regexNameValuematchCount = 3;
  16. static regex_t regexComment;
  17. static regex_t regexNameValue;
  18. static bool started = false;
  19. typedef struct _CachedStat {
  20. struct timespec st_mtim; /* Time of last modification. */
  21. } CachedStat;
  22. static CachedStat cachedStat;
  23. bool startPositionFile(void) {
  24. if (started) {
  25. return true;
  26. }
  27. if (regcomp(&regexComment, regexCommentString, REG_EXTENDED)) {
  28. pudError(false, "Could not compile regex \"%s\"", regexCommentString);
  29. return false;
  30. }
  31. if (regcomp(&regexNameValue, regexNameValueString, REG_EXTENDED)) {
  32. pudError(false, "Could not compile regex \"%s\"", regexNameValueString);
  33. return false;
  34. }
  35. cachedStat.st_mtim.tv_sec = -1;
  36. cachedStat.st_mtim.tv_nsec = -1;
  37. started = true;
  38. return true;
  39. }
  40. void stopPositionFile(void) {
  41. if (started) {
  42. regfree(&regexNameValue);
  43. regfree(&regexComment);
  44. started = false;
  45. }
  46. }
  47. static bool regexMatch(regex_t * regex, char * line, size_t nmatch, regmatch_t pmatch[]) {
  48. int result = regexec(regex, line, nmatch, pmatch, 0);
  49. if (!result) {
  50. return true;
  51. }
  52. if (result == REG_NOMATCH) {
  53. return false;
  54. }
  55. {
  56. char msgbuf[256];
  57. regerror(result, regex, msgbuf, sizeof(msgbuf));
  58. pudError(false, "Regex match failed: %s", msgbuf);
  59. }
  60. return false;
  61. }
  62. static char line[LINE_LENGTH];
  63. bool readPositionFile(char * fileName, nmeaINFO * nmeaInfo) {
  64. bool retval = false;
  65. struct stat statBuf;
  66. nmeaINFO result;
  67. FILE * fd = NULL;
  68. unsigned int lineNumber = 0;
  69. char * name = NULL;
  70. char * value = NULL;
  71. if (stat(fileName, &statBuf)) {
  72. /* could not access the file */
  73. goto out;
  74. }
  75. if (!memcmp(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim))) {
  76. /* file did not change since last read */
  77. goto out;
  78. }
  79. fd = fopen(fileName, "r");
  80. if (!fd) {
  81. goto out;
  82. }
  83. nmea_zero_INFO(&result);
  84. result.sig = POSFILE_DEFAULT_SIG;
  85. result.fix = POSFILE_DEFAULT_FIX;
  86. result.HDOP = POSFILE_DEFAULT_HDOP;
  87. result.VDOP = POSFILE_CALCULATED_VDOP(result.HDOP);
  88. result.PDOP = POSFILE_CALCULATED_PDOP(result.HDOP);
  89. result.lat = POSFILE_DEFAULT_LAT;
  90. result.lon = POSFILE_DEFAULT_LON;
  91. result.elv = POSFILE_DEFAULT_ELV;
  92. result.speed = POSFILE_DEFAULT_SPEED;
  93. result.direction = POSFILE_DEFAULT_DIRECTION;
  94. memcpy(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim));
  95. while (fgets(line, LINE_LENGTH, fd)) {
  96. regmatch_t pmatch[regexNameValuematchCount];
  97. lineNumber++;
  98. if (regexMatch(&regexComment, line, 0, NULL)) {
  99. continue;
  100. }
  101. if (!regexMatch(&regexNameValue, line, regexNameValuematchCount, pmatch)) {
  102. pudError(false, "Position file \"%s\", line %d uses invalid syntax: %s", fileName, lineNumber, line);
  103. goto out;
  104. }
  105. /* copy name/value */
  106. name = &line[pmatch[1].rm_so];
  107. line[pmatch[1].rm_eo] = '\0';
  108. value = &line[pmatch[2].rm_so];
  109. line[pmatch[2].rm_eo] = '\0';
  110. if (!strncasecmp(POSFILE_NAME_SIG, name, sizeof(line))) {
  111. if (!strncasecmp(POSFILE_VALUE_SIG_BAD, value, sizeof(line))) {
  112. result.sig = NMEA_SIG_BAD;
  113. } else if (!strncasecmp(POSFILE_VALUE_SIG_LOW, value, sizeof(line))) {
  114. result.sig = NMEA_SIG_LOW;
  115. } else if (!strncasecmp(POSFILE_VALUE_SIG_MID, value, sizeof(line))) {
  116. result.sig = NMEA_SIG_MID;
  117. } else if (!strncasecmp(POSFILE_VALUE_SIG_HIGH, value, sizeof(line))) {
  118. result.sig = NMEA_SIG_HIGH;
  119. } else {
  120. pudError(false, "Position file \"%s\", line %d uses an invalid value for \"%s\","
  121. " valid values are [%s|%s\%s|%s]", fileName, lineNumber, POSFILE_NAME_SIG,
  122. POSFILE_VALUE_SIG_BAD, POSFILE_VALUE_SIG_LOW, POSFILE_VALUE_SIG_MID, POSFILE_VALUE_SIG_HIGH);
  123. goto out;
  124. }
  125. } else if (!strncasecmp(POSFILE_NAME_FIX, name, sizeof(line))) {
  126. if (!strncasecmp(POSFILE_VALUE_FIX_BAD, value, sizeof(line))) {
  127. result.fix = NMEA_FIX_BAD;
  128. } else if (!strncasecmp(POSFILE_VALUE_FIX_2D, value, sizeof(line))) {
  129. result.fix = NMEA_FIX_2D;
  130. } else if (!strncasecmp(POSFILE_VALUE_FIX_3D, value, sizeof(line))) {
  131. result.fix = NMEA_FIX_3D;
  132. } else {
  133. pudError(false, "Position file \"%s\", line %d uses an invalid value for \"%s\","
  134. " valid values are [%s\%s|%s]", fileName, lineNumber, POSFILE_NAME_FIX, POSFILE_VALUE_FIX_BAD,
  135. POSFILE_VALUE_FIX_2D, POSFILE_VALUE_FIX_3D);
  136. goto out;
  137. }
  138. } else if (!strncasecmp(POSFILE_NAME_HDOP, name, sizeof(line))) {
  139. double val;
  140. if (!readDouble(POSFILE_NAME_HDOP, value, &val)) {
  141. goto out;
  142. }
  143. result.HDOP = val;
  144. result.VDOP = POSFILE_CALCULATED_VDOP(result.HDOP);
  145. result.PDOP = POSFILE_CALCULATED_PDOP(result.HDOP);
  146. } else if (!strncasecmp(POSFILE_NAME_LAT, name, sizeof(line))) {
  147. double val;
  148. if (!readDouble(POSFILE_NAME_LAT, value, &val)) {
  149. goto out;
  150. }
  151. result.lat = val;
  152. } else if (!strncasecmp(POSFILE_NAME_LON, name, sizeof(line))) {
  153. double val;
  154. if (!readDouble(POSFILE_NAME_LON, value, &val)) {
  155. goto out;
  156. }
  157. result.lon = val;
  158. } else if (!strncasecmp(POSFILE_NAME_ELV, name, sizeof(line))) {
  159. double val;
  160. if (!readDouble(POSFILE_NAME_ELV, value, &val)) {
  161. goto out;
  162. }
  163. result.elv = val;
  164. } else if (!strncasecmp(POSFILE_NAME_SPEED, name, sizeof(line))) {
  165. double val;
  166. if (!readDouble(POSFILE_NAME_SPEED, value, &val)) {
  167. goto out;
  168. }
  169. result.speed = val;
  170. } else if (!strncasecmp(POSFILE_NAME_DIRECTION, name, sizeof(line))) {
  171. double val;
  172. if (!readDouble(POSFILE_NAME_DIRECTION, value, &val)) {
  173. goto out;
  174. }
  175. result.direction = val;
  176. } else {
  177. pudError(false, "Position file \"%s\", line %d uses an invalid option \"%s\","
  178. " valid options are [%s|%s|%s|%s|%s|%s|%s|%s]", fileName, lineNumber, name, POSFILE_NAME_SIG,
  179. POSFILE_NAME_FIX, POSFILE_NAME_HDOP, POSFILE_NAME_LAT, POSFILE_NAME_LON, POSFILE_NAME_ELV,
  180. POSFILE_NAME_SPEED, POSFILE_NAME_DIRECTION);
  181. goto out;
  182. }
  183. }
  184. fclose(fd);
  185. result.smask = POSFILE_SANITISE_SMASK;
  186. nmea_INFO_sanitise(&result);
  187. nmea_INFO_unit_conversion(&result);
  188. if (result.fix == NMEA_FIX_BAD) {
  189. result.smask = 0;
  190. } else {
  191. result.smask = POSFILE_DEFAULT_SMASK;
  192. }
  193. memcpy(nmeaInfo, &result, sizeof(result));
  194. retval = true;
  195. out: return retval;
  196. }