1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <time.h>
5 #include <math.h>
6 #include <sys/types.h>
7 #ifdef __MSW__
8 # include <windows.h>
9 #else
10 # include <sys/time.h>
11 #endif
12
13 #include "../include/strexp.h"
14 #include "../include/string.h"
15
16 #include "sartime.h"
17
18 time_t SARGetCurMilliTime(void);
19 unsigned int SARRandom(unsigned int seed_offset);
20 float SARRandomCoeff(unsigned int seed_offset);
21
22 int SARParseTimeOfDay(
23 const char *string,
24 int *h, int *m, int *s
25 );
26 int SARParseLatitudeDMS(const char *string, float *dms);
27 int SARParseLongitudeDMS(const char *string, float *dms);
28
29
30 #define ATOI(s) (((s) != NULL) ? atoi(s) : 0)
31 #define ATOL(s) (((s) != NULL) ? atol(s) : 0)
32 #define ATOF(s) (((s) != NULL) ? atof(s) : 0.0f)
33 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
34
35 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
36 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
37 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
38 #define IS_STRING_EMPTY(s) (((s) != NULL) ? (*(s) == '\0') : TRUE)
39
40 #define RADTODEG(r) ((r) * 180 / PI)
41 #define DEGTORAD(d) ((d) * PI / 180)
42
43
44 /*
45 * Returns the current time since midnight in milliseconds from the
46 * system.
47 */
SARGetCurMilliTime(void)48 time_t SARGetCurMilliTime(void)
49 {
50 #ifdef __MSW__
51 SYSTEMTIME t; /* Current time of day structure. */
52
53 GetSystemTime(&t);
54 return(
55 (time_t)(
56 (((((t.wHour * 60.0) + t.wMinute) * 60) + t.wSecond) * 1000) +
57 t.wMilliseconds
58 )
59 );
60 #else
61 struct timeval tv[1];
62
63 if(gettimeofday(tv, NULL) < 0)
64 return(-1);
65
66 return(((tv->tv_sec % 86400) * 1000) + (tv->tv_usec / 1000));
67 #endif
68 }
69
70 /*
71 * Returns a random number in the range of 0 to 0xffffffff.
72 *
73 * If you call this function more than once per cycle then you
74 * should pass seed_offset as a unique value each time to better
75 * obtain a more random number.
76 */
SARRandom(unsigned int seed_offset)77 unsigned int SARRandom(unsigned int seed_offset)
78 {
79 #if defined(RAND_MAX)
80 /* srand((unsigned int)cur_millitime + seed_offset); */
81 return(rand());
82 #else
83 static u_int32_t gSeed = 1234145;
84 #ifdef __MSW__
85 long result = gSeed * (long)1103515245 + 12345;
86 #else
87 int64_t result = gSeed * (int64_t)1103515245 + 12345;
88 #endif
89 gSeed = (u_int32_t)result;
90
91 return((u_int32_t)(result >> 16));
92 #endif
93 }
94
95 /*
96 * Returns a random coefficient from 0.0 to 1.0, setting the seed
97 * as the current time in milliseconds plus the given seed_offset.
98 *
99 * If you call this function more than once per cycle then you
100 * should pass seed_offset as a unique value each time to better
101 * obtain a more random number.
102 */
SARRandomCoeff(unsigned int seed_offset)103 float SARRandomCoeff(unsigned int seed_offset)
104 {
105 #if defined(RAND_MAX)
106 /* srand((unsigned int)cur_millitime + seed_offset); */
107 return((float)rand() / (float)RAND_MAX);
108 #else
109 return((float)SARRandom(seed_offset) / (float)0xffffffff);
110 #endif
111 }
112
113
114 /*
115 * Parses the given string which should be in the format
116 * "h:m:s". Two available formats 24 and 12 hour are supported,
117 * where the 12 hour is checked for by searching for an in
118 * string 'p' character (case insensitive).
119 *
120 * String is terminated by a null or blank character.
121 *
122 * Returns non-zero if parsing failed.
123 */
SARParseTimeOfDay(const char * string,int * h,int * m,int * s)124 int SARParseTimeOfDay(
125 const char *string,
126 int *h, int *m, int *s
127 )
128 {
129 const char *sp;
130 int in_len, is_12hourpm = 0;
131
132 int lstring_len = 80;
133 char *sp2, *sp3;
134 char lstring[80];
135
136 /* Reset inputs. */
137 if(h != NULL)
138 (*h) = 0;
139 if(m != NULL)
140 (*m) = 0;
141 if(s != NULL)
142 (*s) = 0;
143
144 if((string == NULL) ? 1 : ((*string) == '\0'))
145 return(-1);
146
147 /* Check if this is 12 or 24 hour format. */
148 sp = string;
149 in_len = 0;
150 while(((*sp) != '\0') && !ISBLANK(*sp))
151 {
152 if(toupper(*sp) == 'P')
153 is_12hourpm = 1;
154
155 sp++;
156 in_len++;
157 }
158
159 /* Copy input string to local string. */
160 if(in_len > 0)
161 strncpy(
162 lstring, string, MIN(in_len, lstring_len)
163 );
164 else
165 (*lstring) = '\0';
166 lstring[MIN(in_len, lstring_len - 1)] = '\0';
167
168 /* Fetch hour. */
169 sp2 = lstring;
170 sp3 = strchr(sp2, ':');
171 if(sp3 != NULL)
172 {
173 (*sp3) = '\0';
174 if(h != NULL)
175 *h = (ATOI(sp2) + ((is_12hourpm) ? + 12 : 0)) % 24;
176 sp2 = sp3 + 1;
177 }
178 else
179 {
180 if(h != NULL)
181 *h = (ATOI(sp2) + ((is_12hourpm) ? + 12 : 0)) % 24;
182 sp2 = NULL;
183 }
184 if(sp2 == NULL)
185 return(0);
186
187 /* Fetch minute. */
188 sp3 = strchr(sp2, ':');
189 if(sp3 != NULL)
190 {
191 *sp3 = '\0';
192 if(m != NULL)
193 *m = ATOI(sp2) % 60;
194 sp2 = sp3 + 1;
195 }
196 else
197 {
198 if(m != NULL)
199 *m = ATOI(sp2) % 60;
200 sp2 = NULL;
201 }
202 if(sp2 == NULL)
203 return(0);
204
205 /* Fetch seconds. */
206 sp3 = strchr(sp2, ':');
207 if(sp3 != NULL)
208 {
209 *sp3 = '\0';
210 if(s != NULL)
211 *s = ATOI(sp2) % 60;
212 }
213 else
214 {
215 if(s != NULL)
216 *s = ATOI(sp2) % 60;
217 }
218
219 return(0);
220 }
221
222 /*
223 * Parses the given string which should be in the format
224 * "d'm"s" or "d". Examples (respective) "34'10"59" or "34.1833".
225 *
226 * For format "d" a decimal value from .000 to .999 can be used
227 * to represent decimal degrees.
228 *
229 * Degrees is bounded by -90.0 and 90.0.
230 *
231 * String is terminated by a null or blank character.
232 *
233 * Returns non-zero if parsing failed.
234 */
SARParseLatitudeDMS(const char * string,float * dms)235 int SARParseLatitudeDMS(const char *string, float *dms)
236 {
237 const char *sp;
238 int in_len, is_traditional = 0, is_south = 0;
239
240 int lstring_len = 80;
241 char *sp2, *sp3;
242 char lstring[80];
243
244 /* Reset inputs. */
245 if(dms != NULL)
246 *dms = 0.0f;
247
248 if((string != NULL) ? (*string == '\0') : 1)
249 return(-1);
250
251 /* Check if this is in decimal or traditional notation. */
252 sp = string;
253 in_len = 0;
254 while((*sp != '\0') && !ISBLANK(*sp))
255 {
256 if(toupper(*sp) == '\'')
257 is_traditional = 1;
258
259 if(toupper(*sp) == 'S')
260 is_south = 1;
261
262 sp++;
263 in_len++;
264 }
265
266 /* Copy input string to local string. */
267 if(in_len > 0)
268 strncpy(
269 lstring, string, MIN(in_len, lstring_len)
270 );
271 else
272 *lstring = '\0';
273 lstring[MIN(in_len, lstring_len - 1)] = '\0';
274
275 /* Handle by type. */
276 if(is_traditional)
277 {
278 /* Traditional notation. */
279 int d = 0, m = 0, s = 0;
280
281 /* Fetch degrees. */
282 sp2 = lstring;
283 if(sp2 != NULL)
284 {
285 sp3 = strchr(sp2, '\'');
286 if(sp3 != NULL)
287 {
288 *sp3 = '\0';
289 d = ATOI(sp2);
290 sp2 = sp3 + 1;
291 }
292 else
293 {
294 d = ATOI(sp2);
295 sp2 = NULL;
296 }
297 }
298
299 /* Fetch minutes. */
300 if(sp2 != NULL)
301 {
302 sp3 = strchr(sp2, '"');
303 if(sp3 != NULL)
304 {
305 *sp3 = '\0';
306 m = ATOI(sp2);
307 sp2 = sp3 + 1;
308 }
309 else
310 {
311 m = ATOI(sp2);
312 sp2 = NULL;
313 }
314 }
315
316 /* Fetch seconds. */
317 if(sp2 != NULL)
318 {
319 sp3 = strchr(sp2, '"');
320 if(sp3 != NULL)
321 {
322 *sp3 = '\0';
323 s = ATOI(sp2);
324 sp2 = sp3 + 1;
325 }
326 else
327 {
328 s = ATOI(sp2);
329 sp2 = NULL;
330 }
331 }
332
333 /* Convert and add to dms return. */
334 if(dms != NULL)
335 {
336 /* Negative? */
337 if(is_south && (d > 0.0f))
338 *dms = (float)-d -
339 ((float)m / 60.0f) - ((float)s / 60.0f / 100.0f);
340 else if(d < 0)
341 *dms = (float)d -
342 ((float)m / 60.0f) - ((float)s / 60.0f / 100.0f);
343 else
344 *dms = (float)d +
345 ((float)m / 60.0f) + ((float)s / 60.0f / 100.0f);
346 }
347 }
348 else
349 {
350 /* Decimal notation (this is easy). */
351 sp2 = lstring;
352 if(dms != NULL)
353 {
354 float d = (float)ATOF(sp2);
355 if(is_south && (d > 0.0f))
356 *dms = -d;
357 else
358 *dms = d;
359 }
360 }
361
362 return(0);
363 }
364
365 /*
366 * Parses the given string which should be in the format
367 * "d'm"s" or "d". Examples (respective) "34'10"59" or "34.1833".
368 *
369 * For format "d" a decimal value from .000 to .999 can be used
370 * to represent decimal degrees.
371 *
372 * Degrees is bounded by -140.0 and 140.0.
373 *
374 * String is terminated by a null or blank character.
375 *
376 * Returns non-zero if parsing failed.
377 */
SARParseLongitudeDMS(const char * string,float * dms)378 int SARParseLongitudeDMS(const char *string, float *dms)
379 {
380 const char *sp;
381 int in_len, is_traditional = 0, is_west = 0;
382
383 int lstring_len = 80;
384 char *sp2, *sp3;
385 char lstring[80];
386
387 /* Reset inputs. */
388 if(dms != NULL)
389 *dms = 0.0f;
390
391 if((string != NULL) ? (*string == '\0') : 1)
392 return(-1);
393
394 /* Check if this is in decimal or traditional notation. */
395 sp = string;
396 in_len = 0;
397 while((*sp != '\0') && !ISBLANK(*sp))
398 {
399 if(toupper(*sp) == '\'')
400 is_traditional = 1;
401
402 if(toupper(*sp) == 'W')
403 is_west = 1;
404
405 sp++;
406 in_len++;
407 }
408
409 /* Copy input string to local string. */
410 if(in_len > 0)
411 strncpy(
412 lstring, string, MIN(in_len, lstring_len)
413 );
414 else
415 *lstring = '\0';
416 lstring[MIN(in_len, lstring_len - 1)] = '\0';
417
418 /* Handle by type. */
419 if(is_traditional)
420 {
421 /* Traditional notation. */
422 int d = 0, m = 0, s = 0;
423
424 /* Fetch degrees. */
425 sp2 = lstring;
426 if(sp2 != NULL)
427 {
428 sp3 = strchr(sp2, '\'');
429 if(sp3 != NULL)
430 {
431 *sp3 = '\0';
432 d = ATOI(sp2);
433 sp2 = sp3 + 1;
434 }
435 else
436 {
437 d = ATOI(sp2);
438 sp2 = NULL;
439 }
440 }
441
442 /* Fetch minutes. */
443 if(sp2 != NULL)
444 {
445 sp3 = strchr(sp2, '"');
446 if(sp3 != NULL)
447 {
448 *sp3 = '\0';
449 m = ATOI(sp2);
450 sp2 = sp3 + 1;
451 }
452 else
453 {
454 m = ATOI(sp2);
455 sp2 = NULL;
456 }
457 }
458
459 /* Fetch seconds. */
460 if(sp2 != NULL)
461 {
462 sp3 = strchr(sp2, '"');
463 if(sp3 != NULL)
464 {
465 *sp3 = '\0';
466 s = ATOI(sp2);
467 sp2 = sp3 + 1;
468 }
469 else
470 {
471 s = ATOI(sp2);
472 sp2 = NULL;
473 }
474 }
475
476 /* Convert and add to dms return. */
477 if(dms != NULL)
478 {
479 /* Negative? */
480 if(is_west && (d > 0))
481 *dms = (float)-d -
482 ((float)m / 60.0f) - ((float)s / 60.0f / 100.0f);
483 else if(d < 0)
484 *dms = (float)d -
485 ((float)m / 60.0f) - ((float)s / 60.0f / 100.0f);
486 else
487 *dms = (float)d +
488 ((float)m / 60.0f) + ((float)s / 60.0f / 100.0f);
489 }
490 }
491 else
492 {
493 /* Decimal notation (this is easy). */
494 sp2 = lstring;
495 if(dms != NULL)
496 {
497 float d = (float)ATOF(sp2);
498 if(is_west && (d > 0.0f))
499 *dms = -d;
500 else
501 *dms = d;
502 }
503 }
504
505 return(0);
506 }
507
508