1 : /*****************************************************************************
2 : * myutil.c
3 : *
4 : * DESCRIPTION
5 : * This file contains some simple utility functions.
6 : *
7 : * HISTORY
8 : * 12/2002 Arthur Taylor (MDL / RSIS): Created.
9 : *
10 : * NOTES
11 : *****************************************************************************
12 : */
13 : #include <stdlib.h>
14 : #include <stdio.h>
15 : #include <ctype.h>
16 : #include <string.h>
17 : #include <math.h>
18 : #include <sys/stat.h>
19 : //#include <direct.h>
20 : //#include <dirent.h>
21 : #include "myutil.h"
22 : #include "myassert.h"
23 :
24 : #ifdef MEMWATCH
25 : #include "memwatch.h"
26 : #endif
27 :
28 : /*****************************************************************************
29 : * reallocFGets() -- Arthur Taylor / MDL
30 : *
31 : * PURPOSE
32 : * Read in data from file until a \n is read. Reallocate memory as needed.
33 : * Similar to fgets, except we don't know ahead of time that the line is a
34 : * specific length.
35 : * Assumes that Ptr is either NULL, or points to lenBuff memory.
36 : * Responsibility of caller to free the memory.
37 : *
38 : * ARGUMENTS
39 : * Ptr = An array of data that is of size LenBuff. (Input/Output)
40 : * LenBuff = The Allocated length of Ptr. (Input/Output)
41 : * fp = Input file stream (Input)
42 : *
43 : * RETURNS: size_t
44 : * strlen (buffer)
45 : * 0 = We read only EOF
46 : * 1 = We have "\nEOF" or "<char>EOF"
47 : *
48 : * 12/2002 Arthur Taylor (MDL/RSIS): Created.
49 : *
50 : * NOTES
51 : * 1) Based on getline (see K&R C book (2nd edition) p 29) and on the
52 : * behavior of Tcl's gets routine.
53 : * 2) Chose MIN_STEPSIZE = 80 because pages are usually 80 columns.
54 : * 3) Could switch lenBuff = i + 1 / lenBuff = i to always true.
55 : * Rather not... Less allocs... This way code behaves almost the
56 : * same as fgets except it can expand as needed.
57 : *****************************************************************************
58 : */
59 : #define MIN_STEPSIZE 80
60 0 : size_t reallocFGets (char **Ptr, size_t *LenBuff, FILE *fp)
61 : {
62 0 : char *buffer = *Ptr; /* Local copy of Ptr. */
63 0 : size_t lenBuff = *LenBuff; /* Local copy of LenBuff. */
64 : int c; /* Current char read from stream. */
65 : size_t i; /* Where to store c. */
66 :
67 : myAssert (sizeof (char) == 1);
68 0 : for (i = 0; ((c = getc (fp)) != EOF) && (c != '\n'); ++i) {
69 0 : if (i >= lenBuff) {
70 0 : lenBuff += MIN_STEPSIZE;
71 0 : buffer = (char *) realloc ((void *) buffer, lenBuff);
72 : }
73 0 : buffer[i] = (char) c;
74 : }
75 0 : if (c == '\n') {
76 0 : if (lenBuff <= i + 1) {
77 0 : lenBuff = i + 2; /* Make room for \n\0. */
78 0 : buffer = (char *) realloc ((void *) buffer, lenBuff);
79 : }
80 0 : buffer[i] = (char) c;
81 0 : ++i;
82 : } else {
83 0 : if (lenBuff <= i) {
84 0 : lenBuff = i + 1; /* Make room for \0. */
85 0 : buffer = (char *) realloc ((void *) buffer, lenBuff);
86 : }
87 : }
88 0 : buffer[i] = '\0';
89 0 : *Ptr = buffer;
90 0 : *LenBuff = lenBuff;
91 0 : return i;
92 : }
93 :
94 : #undef MIN_STEPSIZE
95 :
96 : /*****************************************************************************
97 : * mySplit() --
98 : *
99 : * Arthur Taylor / MDL
100 : *
101 : * PURPOSE
102 : * Split a character array according to a given symbol.
103 : * Responsibility of caller to free the memory.
104 : *
105 : * ARGUMENTS
106 : * data = character string to look through. (Input)
107 : * symbol = character to split based on. (Input)
108 : * argc = number of groupings found. (Output)
109 : * argv = characters in each grouping. (Output)
110 : * f_trim = True if we should white space trim each element in list. (Input)
111 : *
112 : * RETURNS: void
113 : *
114 : * HISTORY
115 : * 5/2004 Arthur Taylor (MDL/RSIS): Created.
116 : *
117 : * NOTES
118 : *****************************************************************************
119 : */
120 0 : void mySplit (const char *data, char symbol, size_t *Argc, char ***Argv,
121 : char f_trim)
122 : {
123 : const char *head; /* The head of the current string */
124 : const char *ptr; /* a pointer to walk over the data. */
125 0 : size_t argc = 0; /* Local copy of Argc */
126 0 : char **argv = NULL; /* Local copy of Argv */
127 : size_t len; /* length of current string. */
128 :
129 : myAssert (*Argc == 0);
130 : myAssert (*Argv == NULL);
131 : myAssert (sizeof (char) == 1);
132 :
133 0 : head = data;
134 0 : while (head != NULL) {
135 0 : argv = (char **) realloc ((void *) argv, (argc + 1) * sizeof (char *));
136 0 : ptr = strchr (head, symbol);
137 0 : if (ptr != NULL) {
138 0 : len = ptr - head;
139 0 : argv[argc] = (char *) malloc (len + 1);
140 0 : strncpy (argv[argc], head, len);
141 0 : argv[argc][len] = '\0';
142 0 : if (f_trim) {
143 0 : strTrim (argv[argc]);
144 : }
145 0 : argc++;
146 0 : head = ptr + 1;
147 : /* The following head != NULL is in case data is not '\0' terminated
148 : */
149 0 : if ((head != NULL) && (*head == '\0')) {
150 : /* Handle a break character just before the \0 */
151 : /* This results in not adding a "" to end of list. */
152 0 : head = NULL;
153 : }
154 : } else {
155 : /* Handle from here to end of text. */
156 0 : len = strlen (head);
157 0 : argv[argc] = (char *) malloc (len + 1);
158 0 : strcpy (argv[argc], head);
159 0 : if (f_trim) {
160 0 : strTrim (argv[argc]);
161 : }
162 0 : argc++;
163 0 : head = NULL;
164 : }
165 : }
166 0 : *Argc = argc;
167 0 : *Argv = argv;
168 0 : }
169 :
170 0 : int myAtoI (const char *ptr, sInt4 *value)
171 : {
172 : char *extra; /* The data after the end of the double. */
173 :
174 : myAssert (ptr != NULL);
175 0 : *value = 0;
176 0 : while (*ptr != '\0') {
177 0 : if (isdigit (*ptr) || (*ptr == '+') || (*ptr == '-')) {
178 0 : *value = strtol (ptr, &extra, 10);
179 : myAssert (extra != NULL);
180 0 : if (*extra == '\0') {
181 0 : return 1;
182 : }
183 0 : break;
184 0 : } else if (!isspace ((unsigned char)*ptr)) {
185 0 : return 0;
186 : }
187 0 : ptr++;
188 : }
189 : /* Check if all white space. */
190 0 : if (*ptr == '\0') {
191 0 : return 0;
192 : }
193 : myAssert (extra != NULL);
194 : /* Allow first trailing char for ',' */
195 0 : if (!isspace ((unsigned char)*extra)) {
196 0 : if (*extra != ',') {
197 0 : *value = 0;
198 0 : return 0;
199 : }
200 : }
201 0 : extra++;
202 : /* Make sure the rest is all white space. */
203 0 : while (*extra != '\0') {
204 0 : if (!isspace ((unsigned char)*extra)) {
205 0 : *value = 0;
206 0 : return 0;
207 : }
208 0 : extra++;
209 : }
210 0 : return 1;
211 : }
212 :
213 : /*****************************************************************************
214 : * myAtoF() -- used to be myIsReal()
215 : *
216 : * Arthur Taylor / MDL
217 : *
218 : * PURPOSE
219 : * Returns true if all char are digits except a leading + or -, or a
220 : * trailing ','. Ignores leading or trailing white space. Value is set to
221 : * atof (ptr).
222 : *
223 : * ARGUMENTS
224 : * ptr = character string to look at. (Input)
225 : * value = the converted value of ptr, if ptr is a number. (Output)
226 : *
227 : * RETURNS: int
228 : * 0 = Not a real number,
229 : * 1 = Real number.
230 : *
231 : * HISTORY
232 : * 7/2004 Arthur Taylor (MDL): Updated
233 : * 4/2005 AAT (MDL): Did a code walk through.
234 : *
235 : * NOTES
236 : *****************************************************************************
237 : */
238 0 : int myAtoF (const char *ptr, double *value)
239 : {
240 : char *extra; /* The data after the end of the double. */
241 :
242 : myAssert (ptr != NULL);
243 0 : *value = 0;
244 0 : while (*ptr != '\0') {
245 0 : if (isdigit (*ptr) || (*ptr == '+') || (*ptr == '-') || (*ptr == '.')) {
246 0 : *value = strtod (ptr, &extra);
247 : myAssert (extra != NULL);
248 0 : if (*extra == '\0') {
249 0 : return 1;
250 : }
251 0 : break;
252 0 : } else if (!isspace ((unsigned char)*ptr)) {
253 0 : return 0;
254 : }
255 0 : ptr++;
256 : }
257 : /* Check if all white space. */
258 0 : if (*ptr == '\0') {
259 0 : return 0;
260 : }
261 : myAssert (extra != NULL);
262 : /* Allow first trailing char for ',' */
263 0 : if (!isspace ((unsigned char)*extra)) {
264 0 : if (*extra != ',') {
265 0 : *value = 0;
266 0 : return 0;
267 : }
268 : }
269 0 : extra++;
270 : /* Make sure the rest is all white space. */
271 0 : while (*extra != '\0') {
272 0 : if (!isspace ((unsigned char)*extra)) {
273 0 : *value = 0;
274 0 : return 0;
275 : }
276 0 : extra++;
277 : }
278 0 : return 1;
279 : }
280 :
281 : /* Change of name was to deprecate usage... Switch to myAtoF */
282 0 : int myIsReal_old (const char *ptr, double *value)
283 : {
284 : size_t len, i;
285 :
286 0 : *value = 0;
287 0 : if ((!isdigit (*ptr)) && (*ptr != '.'))
288 0 : if (*ptr != '-')
289 0 : return 0;
290 0 : len = strlen (ptr);
291 0 : for (i = 1; i < len - 1; i++) {
292 0 : if ((!isdigit (ptr[i])) && (ptr[i] != '.'))
293 0 : return 0;
294 : }
295 0 : if ((!isdigit (ptr[len - 1])) && (ptr[len - 1] != '.')) {
296 0 : if (ptr[len - 1] != ',') {
297 0 : return 0;
298 : } else {
299 : /* ptr[len - 1] = '\0';*/
300 0 : *value = atof (ptr);
301 : /* ptr[len - 1] = ',';*/
302 0 : return 1;
303 : }
304 : }
305 0 : *value = atof (ptr);
306 0 : return 1;
307 : }
308 :
309 : /* Return:
310 : * 0 if 'can't stat the file' (most likely not a file)
311 : * 1 if it is a directory
312 : * 2 if it is a file
313 : * 3 if it doesn't understand the file
314 : */
315 : /* mtime may behave oddly...
316 : * stat appeared correct if I was in EST and the file was in EST,
317 : * but was off by 1 hour if I was in EST and the file was in EDT.
318 : * rddirlst.c solved this through use of "clock".
319 : *
320 : * Could return mode: RDCF___rwxrwxrwx where R is 1/0 based on regular file
321 : * D is 1/0 based on directory, first rwx is user permissions...
322 : */
323 0 : int myStat (char *filename, char *perm, sInt4 *size, double *mtime)
324 : {
325 : struct stat stbuf;
326 : char f_cnt;
327 : char *ptr;
328 : int ans;
329 :
330 : myAssert (filename != NULL);
331 :
332 : /* Check for unmatched quotes (apparently stat on MS-Windows lets:
333 : * ./data/ndfd/geodata\" pass, which causes issues later. */
334 0 : f_cnt = 0;
335 0 : for (ptr = filename; *ptr != '\0'; ptr++) {
336 0 : if (*ptr == '"')
337 0 : f_cnt = !f_cnt;
338 : }
339 0 : if (f_cnt) {
340 : /* unmatched quotes. */
341 0 : if (size)
342 0 : *size = 0;
343 0 : if (mtime)
344 0 : *mtime = 0;
345 0 : if (perm)
346 0 : *perm = 0;
347 0 : return 0;
348 : }
349 :
350 : /* Try to stat file. */
351 0 : if ((ans = stat (filename, &stbuf)) == -1) {
352 0 : if ((filename[strlen (filename) - 1] == '/') ||
353 0 : (filename[strlen (filename) - 1] == '\\')) {
354 0 : filename[strlen (filename) - 1] = '\0';
355 0 : ans = stat (filename, &stbuf);
356 : }
357 : }
358 : /* Can't stat */
359 0 : if (ans == -1) {
360 0 : if (size)
361 0 : *size = 0;
362 0 : if (mtime)
363 0 : *mtime = 0;
364 0 : if (perm)
365 0 : *perm = 0;
366 0 : return 0;
367 : }
368 :
369 0 : if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
370 : /* Is a directory */
371 0 : if (size)
372 0 : *size = stbuf.st_size;
373 0 : if (mtime)
374 0 : *mtime = stbuf.st_mtime;
375 0 : if (perm) {
376 0 : *perm = (stbuf.st_mode & S_IREAD) ? 4 : 0;
377 0 : if (stbuf.st_mode & S_IWRITE)
378 0 : *perm += 2;
379 0 : if (stbuf.st_mode & S_IEXEC)
380 0 : *perm += 1;
381 : }
382 0 : return MYSTAT_ISDIR;
383 0 : } else if ((stbuf.st_mode & S_IFMT) == S_IFREG) {
384 : /* Is a file */
385 0 : if (size)
386 0 : *size = stbuf.st_size;
387 0 : if (mtime)
388 0 : *mtime = stbuf.st_mtime;
389 0 : if (perm) {
390 0 : *perm = (stbuf.st_mode & S_IREAD) ? 4 : 0;
391 0 : if (stbuf.st_mode & S_IWRITE)
392 0 : *perm += 2;
393 0 : if (stbuf.st_mode & S_IEXEC)
394 0 : *perm += 1;
395 : }
396 0 : return MYSTAT_ISFILE;
397 : } else {
398 : /* unrecognized file type */
399 0 : if (size)
400 0 : *size = 0;
401 0 : if (mtime)
402 0 : *mtime = 0;
403 0 : if (perm)
404 0 : *perm = 0;
405 0 : return 3;
406 : }
407 : }
408 :
409 : /**
410 : static int FileMatch (const char *filename, const char *filter)
411 : {
412 : const char *ptr1;
413 : const char *ptr2;
414 :
415 : ptr2 = filename;
416 : for (ptr1 = filter; *ptr1 != '\0'; ptr1++) {
417 : if (*ptr1 == '*') {
418 : if (ptr1[1] == '\0') {
419 : return 1;
420 : } else {
421 : ptr2 = strchr (ptr2, ptr1[1]);
422 : if (ptr2 == NULL) {
423 : return 0;
424 : }
425 : }
426 : } else if (*ptr2 == '\0') {
427 : return 0;
428 : } else if (*ptr1 == '?') {
429 : ptr2++;
430 : } else {
431 : if (*ptr1 == *ptr2) {
432 : ptr2++;
433 : } else {
434 : return 0;
435 : }
436 : }
437 : }
438 : return (*ptr2 == '\0');
439 : }
440 : **/
441 :
442 0 : int myGlob (const char *dirName, const char *filter, size_t *Argc,
443 : char ***Argv)
444 : {
445 0 : return 0; // TODO: reimplement for Win32
446 : /*
447 : size_t argc = 0; // Local copy of Argc
448 : char **argv = NULL; // Local copy of Argv
449 : struct dirent *dp;
450 : DIR *dir;
451 :
452 : myAssert (*Argc == 0);
453 : myAssert (*Argv == NULL);
454 :
455 : if ((dir = opendir (dirName)) == NULL)
456 : return -1;
457 :
458 : while ((dp = readdir (dir)) != NULL) {
459 : // Skip self and parent.
460 : if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0)
461 : continue;
462 : if (FileMatch (dp->d_name, filter)) {
463 : argv = (char **) realloc (argv, (argc + 1) * sizeof (char *));
464 : argv[argc] = (char *) malloc ((strlen (dirName) + 1 +
465 : strlen (dp->d_name) +
466 : 1) * sizeof (char));
467 : sprintf (argv[argc], "%s/%s", dirName, dp->d_name);
468 : argc++;
469 : }
470 : }
471 : *Argc = argc;
472 : *Argv = argv;
473 : return 0;
474 : */
475 : }
476 :
477 : /*****************************************************************************
478 : * FileCopy() --
479 : *
480 : * Arthur Taylor / MDL
481 : *
482 : * PURPOSE
483 : * Copy a file from one location to another.
484 : *
485 : * ARGUMENTS
486 : * fileIn = source file to read from. (Input)
487 : * fileOut = destation file to write to. (Input)
488 : *
489 : * RETURNS: int
490 : * 0 = success.
491 : * 1 = problems opening fileIn
492 : * 2 = problems opening fileOut
493 : *
494 : * HISTORY
495 : * 5/2004 Arthur Taylor (MDL/RSIS): Created.
496 : * 4/2005 AAT (MDL): Did a code walk through.
497 : *
498 : * NOTES
499 : *****************************************************************************
500 : */
501 0 : int FileCopy (const char *fileIn, const char *fileOut)
502 : {
503 : FILE *ifp; /* The file pointer to read from. */
504 : FILE *ofp; /* The file pointer to write to. */
505 : int c; /* temporary variable while reading / writing. */
506 :
507 0 : if ((ifp = fopen (fileIn, "rb")) == NULL) {
508 : #ifdef DEBUG
509 : printf ("Couldn't open %s for read\n", fileIn);
510 : #endif
511 0 : return 1;
512 : }
513 0 : if ((ofp = fopen (fileOut, "wb")) == NULL) {
514 : #ifdef DEBUG
515 : printf ("Couldn't open %s for write\n", fileOut);
516 : #endif
517 0 : fclose (ifp);
518 0 : return 2;
519 : }
520 0 : while ((c = getc (ifp)) != EOF) {
521 0 : putc (c, ofp);
522 : }
523 0 : fclose (ifp);
524 0 : fclose (ofp);
525 0 : return 0;
526 : }
527 :
528 : /*****************************************************************************
529 : * FileTail() --
530 : *
531 : * Arthur Taylor / MDL
532 : *
533 : * PURPOSE
534 : * Returns the characters in a filename after the last directory separator.
535 : * Responsibility of caller to free the memory.
536 : *
537 : * ARGUMENTS
538 : * fileName = fileName to look at. (Input)
539 : * tail = Tail of the filename. (Output)
540 : *
541 : * RETURNS: void
542 : *
543 : * HISTORY
544 : * 5/2004 Arthur Taylor (MDL/RSIS): Created.
545 : *
546 : * NOTES
547 : *****************************************************************************
548 : */
549 0 : void FileTail (const char *fileName, char **tail)
550 : {
551 : const char *ptr; /* A pointer to last \ or // in fileName. */
552 :
553 : myAssert (fileName != NULL);
554 : myAssert (sizeof (char) == 1);
555 :
556 0 : ptr = strrchr (fileName, '/');
557 0 : if (ptr == NULL) {
558 0 : ptr = strrchr (fileName, '\\');
559 0 : if (ptr == NULL) {
560 0 : ptr = fileName;
561 : } else {
562 0 : ptr++;
563 : }
564 : } else {
565 0 : ptr++;
566 : }
567 0 : *tail = (char *) malloc (strlen (ptr) + 1);
568 0 : strcpy (*tail, ptr);
569 0 : }
570 :
571 : /*****************************************************************************
572 : * myRound() --
573 : *
574 : * Arthur Taylor / MDL
575 : *
576 : * PURPOSE
577 : * Round a number to a given number of decimal places.
578 : *
579 : * ARGUMENTS
580 : * data = number to round (Input)
581 : * place = How many decimals to round to (Input)
582 : *
583 : * RETURNS: double (rounded value)
584 : *
585 : * HISTORY
586 : * 5/2003 Arthur Taylor (MDL/RSIS): Created.
587 : * 2/2006 AAT: Added the (double) (.5) cast, and the mult by POWERS_OVER_ONE
588 : * instead of division.
589 : *
590 : * NOTES
591 : * 1) It is probably inadvisable to make a lot of calls to this routine,
592 : * considering the fact that a context swap is made, so this is provided
593 : * primarily as an example, but it can be used for some rounding.
594 : *****************************************************************************
595 : */
596 : double POWERS_ONE[] = {
597 : 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
598 : 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17
599 : };
600 :
601 0 : double myRound (double data, uChar place)
602 : {
603 0 : if (place > 17)
604 0 : place = 17;
605 :
606 0 : return (floor (data * POWERS_ONE[place] + 5e-1)) / POWERS_ONE[place];
607 :
608 : /* Tried some other options to see if I could fix test 40 on linux, but
609 : * changing it appears to make other tests fail on other OS's. */
610 : /*
611 : return (((sInt4) (data * POWERS_ONE[place] + .5)) / POWERS_ONE[place]);
612 : */
613 : /*
614 : return (floor (data * POWERS_ONE[place] + .5)) / POWERS_ONE[place];
615 : */
616 : }
617 :
618 : /*****************************************************************************
619 : * strTrim() --
620 : *
621 : * Arthur Taylor / MDL
622 : *
623 : * PURPOSE
624 : * Trim the white space from both sides of a char string.
625 : *
626 : * ARGUMENTS
627 : * str = The string to trim (Input/Output)
628 : *
629 : * RETURNS: void
630 : *
631 : * HISTORY
632 : * 10/2003 Arthur Taylor (MDL/RSIS): Created.
633 : *
634 : * NOTES
635 : * See K&R p106 for strcpy part.
636 : *****************************************************************************
637 : */
638 0 : void strTrim (char *str)
639 : {
640 : size_t i; /* loop counter for traversing str. */
641 : size_t len; /* The length of str. */
642 : char *ptr; /* Pointer to where first non-white space is. */
643 :
644 : /* str shouldn't be null, but if it is, we want to handle it. */
645 : myAssert (str != NULL);
646 0 : if (str == NULL) {
647 0 : return;
648 : }
649 :
650 : /* Remove the trailing white space before working on the leading ones. */
651 0 : len = strlen (str);
652 0 : for (i = len - 1; ((i >= 0) && (isspace ((unsigned char)str[i]))); i--) {
653 : }
654 0 : len = i + 1;
655 0 : str[len] = '\0';
656 :
657 : /* Find first non-white space char. */
658 0 : for (ptr = str; (*ptr != '\0') && (isspace ((unsigned char)*ptr)); ptr++) {
659 : }
660 :
661 0 : if (ptr != str) {
662 : /* Can't do a strcpy here since we don't know that they start at left
663 : * and go right. */
664 0 : while ((*str++ = *ptr++) != '\0') {
665 : }
666 0 : *str = '\0';
667 : }
668 : }
669 :
670 : /*****************************************************************************
671 : * strTrimRight() --
672 : *
673 : * Arthur Taylor / MDL
674 : *
675 : * PURPOSE
676 : * Trim white space and a given char from the right.
677 : *
678 : * ARGUMENTS
679 : * str = The string to trim (Input/Output)
680 : * c = The character to remove. (Input)
681 : *
682 : * RETURNS: void
683 : *
684 : * HISTORY
685 : * 7/2004 Arthur Taylor (MDL/RSIS): Created.
686 : *
687 : * NOTES
688 : *****************************************************************************
689 : */
690 4 : void strTrimRight (char *str, char c)
691 : {
692 : size_t i; /* loop counter for traversing str. */
693 :
694 : /* str shouldn't be null, but if it is, we want to handle it. */
695 : myAssert (str != NULL);
696 4 : if (str == NULL) {
697 0 : return;
698 : }
699 :
700 60 : for (i = strlen (str) - 1;
701 52 : ((i >= 0) && ((isspace ((unsigned char)str[i])) || (str[i] == c))); i--) {
702 : }
703 4 : str[i + 1] = '\0';
704 : }
705 :
706 : /*****************************************************************************
707 : * strCompact() --
708 : *
709 : * Arthur Taylor / MDL
710 : *
711 : * PURPOSE
712 : * Replace any multiple instances of 'c' in the string with 1 instance.
713 : *
714 : * ARGUMENTS
715 : * str = The string to compact (Input/Output)
716 : * c = The character to look for. (Input)
717 : *
718 : * RETURNS: void
719 : *
720 : * HISTORY
721 : * 10/2004 Arthur Taylor (MDL): Created.
722 : *
723 : * NOTES
724 : *****************************************************************************
725 : */
726 0 : void strCompact (char *str, char c)
727 : {
728 : char *ptr; /* The next good value in str to keep. */
729 :
730 : /* str shouldn't be null, but if it is, we want to handle it. */
731 : myAssert (str != NULL);
732 0 : if (str == NULL) {
733 0 : return;
734 : }
735 :
736 0 : ptr = str;
737 0 : while ((*str = *(ptr++)) != '\0') {
738 0 : if (*(str++) == c) {
739 0 : while ((*ptr != '\0') && (*ptr == c)) {
740 0 : ptr++;
741 : }
742 : }
743 : }
744 : }
745 :
746 : /*****************************************************************************
747 : * strReplace() --
748 : *
749 : * Arthur Taylor / MDL
750 : *
751 : * PURPOSE
752 : * Replace all instances of c1 in str with c2.
753 : *
754 : * ARGUMENTS
755 : * str = The string to trim (Input/Output)
756 : * c1 = The character(s) in str to be replaced. (Input)
757 : * c2 = The char to replace c1 with. (Input)
758 : *
759 : * RETURNS: void
760 : *
761 : * HISTORY
762 : * 7/2004 Arthur Taylor (MDL/RSIS): Created.
763 : *
764 : * NOTES
765 : *****************************************************************************
766 : */
767 0 : void strReplace (char *str, char c1, char c2)
768 : {
769 0 : char *ptr = str;
770 :
771 : /* str shouldn't be null, but if it is, we want to handle it. */
772 : myAssert (str != NULL);
773 0 : if (str == NULL) {
774 0 : return;
775 : }
776 :
777 0 : for (ptr = str; *ptr != '\0'; ptr++) {
778 0 : if (*ptr == c1) {
779 0 : *ptr = c2;
780 : }
781 : }
782 : }
783 :
784 : /*****************************************************************************
785 : * strToUpper() --
786 : *
787 : * Arthur Taylor / MDL
788 : *
789 : * PURPOSE
790 : * Convert a string to all uppercase.
791 : *
792 : * ARGUMENTS
793 : * str = The string to adjust (Input/Output)
794 : *
795 : * RETURNS: void
796 : *
797 : * HISTORY
798 : * 10/2003 Arthur Taylor (MDL/RSIS): Created.
799 : *
800 : * NOTES
801 : *****************************************************************************
802 : */
803 0 : void strToUpper (char *str)
804 : {
805 0 : char *ptr = str; /* Used to traverse str. */
806 :
807 : /* str shouldn't be null, but if it is, we want to handle it. */
808 : myAssert (str != NULL);
809 0 : if (str == NULL) {
810 0 : return;
811 : }
812 :
813 0 : while ((*ptr++ = toupper (*str++)) != '\0') {
814 : }
815 : }
816 :
817 : /*****************************************************************************
818 : * strToLower() --
819 : *
820 : * Arthur Taylor / MDL
821 : *
822 : * PURPOSE
823 : * Convert a string to all lowercase.
824 : *
825 : * ARGUMENTS
826 : * str = The string to adjust (Input/Output)
827 : *
828 : * RETURNS: void
829 : *
830 : * HISTORY
831 : * 5/2004 Arthur Taylor (MDL/RSIS): Created.
832 : *
833 : * NOTES
834 : *****************************************************************************
835 : */
836 0 : void strToLower (char *str)
837 : {
838 0 : char *ptr = str; /* Used to traverse str. */
839 :
840 : /* str shouldn't be null, but if it is, we want to handle it. */
841 : myAssert (str != NULL);
842 0 : if (str == NULL) {
843 0 : return;
844 : }
845 :
846 0 : while ((*ptr++ = tolower (*str++)) != '\0') {
847 : }
848 : }
849 :
850 : /*
851 : * Returns: Length of the string.
852 : * History: 1/29/98 AAT Commented.
853 : *
854 : int str2lw (char *s) {
855 : int i = 0, len = strlen (s);
856 : while (i < len) {
857 : s[i] = (char) tolower(s[i]);
858 : i++;
859 : }
860 : return len;
861 : }
862 : */
863 :
864 : /*****************************************************************************
865 : * strcmpNoCase() --
866 : *
867 : * Arthur Taylor / MDL
868 : *
869 : * PURPOSE
870 : * Compare two strings without concern for case.
871 : *
872 : * ARGUMENTS
873 : * str1 = String1 to compare (Input)
874 : * str2 = String2 to compare (Input)
875 : *
876 : * RETURNS: int
877 : * -1 = (str1 < str2)
878 : * 0 = (str1 == str2)
879 : * 1 = (str1 > str2)
880 : *
881 : * HISTORY
882 : * 5/2004 Arthur Taylor (MDL/RSIS): Created.
883 : *
884 : * NOTES
885 : * See K&R p 106
886 : *****************************************************************************
887 : */
888 0 : int strcmpNoCase (const char *str1, const char *str2)
889 : {
890 : /* str1, str2 shouldn't be null, but if it is, we want to handle it. */
891 : myAssert (str1 != NULL);
892 : myAssert (str2 != NULL);
893 0 : if (str1 == NULL) {
894 0 : if (str2 == NULL) {
895 0 : return 0;
896 : } else {
897 0 : return -1;
898 : }
899 : }
900 0 : if (str2 == NULL) {
901 0 : return 1;
902 : }
903 :
904 0 : for (; tolower (*str1) == tolower (*str2); str1++, str2++) {
905 0 : if (*str1 == '\0')
906 0 : return 0;
907 : }
908 0 : return (tolower (*str1) - tolower (*str2) < 0) ? -1 : 1;
909 : /*
910 : strlen1 = strlen (str1);
911 : strlen2 = strlen (str2);
912 : min = (strlen1 < strlen2) ? strlen1 : strlen2;
913 : for (i = 0; i < min; i++) {
914 : c1 = tolower (str1[i]);
915 : c2 = tolower (str2[i]);
916 : if (c1 < c2)
917 : return -1;
918 : if (c1 > c2)
919 : return 1;
920 : }
921 : if (strlen1 < strlen2) {
922 : return -1;
923 : }
924 : if (strlen1 > strlen2) {
925 : return 1;
926 : }
927 : return 0;
928 : */
929 : }
930 :
931 : /*****************************************************************************
932 : * GetIndexFromStr() -- Review 12/2002
933 : *
934 : * Arthur Taylor / MDL
935 : *
936 : * PURPOSE
937 : * Looks through a list of strings (with a NULL value at the end) for a
938 : * given string. Returns the index where it found it.
939 : *
940 : * ARGUMENTS
941 : * str = The string to look for. (Input)
942 : * Opt = The list to look for arg in. (Input)
943 : * Index = The location of arg in Opt (or -1 if it couldn't find it) (Output)
944 : *
945 : * RETURNS: int
946 : * # = Where it found it.
947 : * -1 = Couldn't find it.
948 : *
949 : * HISTORY
950 : * 9/2002 Arthur Taylor (MDL/RSIS): Created.
951 : * 12/2002 (TK,AC,TB,&MS): Code Review.
952 : *
953 : * NOTES
954 : * Why not const char **Opt?
955 : *****************************************************************************
956 : */
957 0 : int GetIndexFromStr (const char *str, char **Opt, int *Index)
958 : {
959 0 : int cnt = 0; /* Current Count in Opt. */
960 :
961 : myAssert (str != NULL);
962 0 : if (str == NULL) {
963 0 : *Index = -1;
964 0 : return -1;
965 : }
966 :
967 0 : for (; *Opt != NULL; Opt++, cnt++) {
968 0 : if (strcmp (str, *Opt) == 0) {
969 0 : *Index = cnt;
970 0 : return cnt;
971 : }
972 : }
973 0 : *Index = -1;
974 0 : return -1;
975 : }
976 :
977 : /*****************************************************************************
978 : * Clock_GetTimeZone() --
979 : *
980 : * Arthur Taylor / MDL
981 : *
982 : * PURPOSE
983 : * Returns the time zone offset in hours to add to local time to get UTC.
984 : * So EST is +5 not -5.
985 : *
986 : * ARGUMENTS
987 : *
988 : * RETURNS: sInt2
989 : *
990 : * HISTORY
991 : * 6/2004 Arthur Taylor (MDL): Created.
992 : * 3/2005 AAT: Found bug... Used to use 1/1/1970 00Z and find the local
993 : * hour. If CET, this means use 1969 date, which causes it to die.
994 : * Switched to 1/2/1970 00Z.
995 : * 3/2005 AAT: timeZone (see CET) can be < 0. don't add 24 if timeZone < 0
996 : *
997 : * NOTES
998 : *****************************************************************************
999 : */
1000 0 : static sChar Clock_GetTimeZone ()
1001 : {
1002 : struct tm time;
1003 : time_t ansTime;
1004 : struct tm *gmTime;
1005 : static sChar timeZone = 127;
1006 :
1007 0 : if (timeZone == 127) {
1008 : /* Cheap method of getting global time_zone variable. */
1009 0 : memset (&time, 0, sizeof (struct tm));
1010 0 : time.tm_year = 70;
1011 0 : time.tm_mday = 2;
1012 0 : ansTime = mktime (&time);
1013 0 : gmTime = gmtime (&ansTime);
1014 0 : timeZone = gmTime->tm_hour;
1015 0 : if (gmTime->tm_mday != 2) {
1016 0 : timeZone -= 24;
1017 : }
1018 : }
1019 0 : return timeZone;
1020 : }
1021 :
1022 : /*****************************************************************************
1023 : * myParseTime() --
1024 : *
1025 : * Arthur Taylor / MDL
1026 : *
1027 : * PURPOSE
1028 : * Parse a string such as "19730724000000" and return time since the
1029 : * beginning of the epoch.
1030 : *
1031 : * ARGUMENTS
1032 : * is = String to read the date from (Input)
1033 : * AnsTime = Time to String2 to compare (Input)
1034 : *
1035 : * RETURNS: int
1036 : * 0 = success
1037 : * 1 = error
1038 : *
1039 : * HISTORY
1040 : * 4/2005 Arthur Taylor (MDL): Commented
1041 : *
1042 : * NOTES
1043 : * Rename (myParseTime -> myParseTime2) because changed error return from
1044 : * -1 to 1
1045 : * Rename (myParseTime2 -> myParseTime3) because I'm trying to phase it out.
1046 : * Use: int Clock_ScanDateNumber (double *clock, char *buffer) instead.
1047 : *****************************************************************************
1048 : */
1049 0 : int myParseTime3 (const char *is, time_t * AnsTime)
1050 : {
1051 : char buffer[5]; /* A temporary variable for parsing "is". */
1052 : sShort2 year; /* The year. */
1053 : uChar mon; /* The month. */
1054 : uChar day; /* The day. */
1055 : uChar hour; /* The hour. */
1056 : uChar min; /* The minute. */
1057 : uChar sec; /* The second. */
1058 : struct tm time; /* A temporary variable to put the time info into. */
1059 :
1060 0 : memset (&time, 0, sizeof (struct tm));
1061 : myAssert (strlen (is) == 14);
1062 0 : if (strlen (is) != 14) {
1063 0 : printf ("%s is not formated correctly\n", is);
1064 0 : return 1;
1065 : }
1066 0 : strncpy (buffer, is, 4);
1067 0 : buffer[4] = '\0';
1068 0 : year = atoi (buffer);
1069 0 : strncpy (buffer, is + 4, 2);
1070 0 : buffer[2] = '\0';
1071 0 : mon = atoi (buffer);
1072 0 : strncpy (buffer, is + 6, 2);
1073 0 : day = atoi (buffer);
1074 0 : strncpy (buffer, is + 8, 2);
1075 0 : hour = atoi (buffer);
1076 0 : strncpy (buffer, is + 10, 2);
1077 0 : min = atoi (buffer);
1078 0 : strncpy (buffer, is + 12, 2);
1079 0 : sec = atoi (buffer);
1080 0 : if ((year > 2001) || (year < 1900) || (mon > 12) || (mon < 1) ||
1081 : (day > 31) || (day < 1) || (hour > 23) || (min > 59) || (sec > 60)) {
1082 0 : printf ("date %s is invalid\n", is);
1083 0 : printf ("%d %d %d %d %d %d\n", year, mon, day, hour, min, sec);
1084 0 : return 1;
1085 : }
1086 0 : time.tm_year = year - 1900;
1087 0 : time.tm_mon = mon - 1;
1088 0 : time.tm_mday = day;
1089 0 : time.tm_hour = hour;
1090 0 : time.tm_min = min;
1091 0 : time.tm_sec = sec;
1092 0 : *AnsTime = mktime (&time) - (Clock_GetTimeZone () * 3600);
1093 0 : return 0;
1094 : }
1095 :
1096 : #ifdef MYUTIL_TEST
1097 : int main (int argc, char **argv)
1098 : {
1099 : char buffer[] = "Hello , World, This, is, a , test\n";
1100 : char buffer2[] = "";
1101 : size_t listLen = 0;
1102 : char **List = NULL;
1103 : size_t i;
1104 : size_t j;
1105 : char ans;
1106 : double value;
1107 : char *tail;
1108 :
1109 : /*
1110 : printf ("1 :: %f\n", clock() / (double) (CLOCKS_PER_SEC));
1111 : for (j = 0; j < 25000; j++) {
1112 : mySplit (buffer, ',', &listLen, &List, 1);
1113 : for (i = 0; i < listLen; i++) {
1114 : free (List[i]);
1115 : }
1116 : free (List);
1117 : List = NULL;
1118 : listLen = 0;
1119 : }
1120 : printf ("1 :: %f\n", clock() / (double) (CLOCKS_PER_SEC));
1121 : */
1122 : mySplit (buffer, ',', &listLen, &List, 1);
1123 : for (i = 0; i < listLen; i++) {
1124 : printf ("%d:'%s'\n", i, List[i]);
1125 : free (List[i]);
1126 : }
1127 : free (List);
1128 : List = NULL;
1129 : listLen = 0;
1130 :
1131 : mySplit (buffer2, ',', &listLen, &List, 1);
1132 : for (i = 0; i < listLen; i++) {
1133 : printf ("%d:'%s'\n", i, List[i]);
1134 : free (List[i]);
1135 : }
1136 : free (List);
1137 : List = NULL;
1138 : listLen = 0;
1139 :
1140 : strcpy (buffer, " 0.95");
1141 : ans = myAtoF (buffer, &value);
1142 : printf ("%d %f : ", ans, value);
1143 : ans = myIsReal_old (buffer, &value);
1144 : printf ("%d %f : '%s'\n", ans, value, buffer);
1145 :
1146 : strcpy (buffer, "0.95");
1147 : ans = myAtoF (buffer, &value);
1148 : printf ("%d %f : ", ans, value);
1149 : ans = myIsReal_old (buffer, &value);
1150 : printf ("%d %f : '%s'\n", ans, value, buffer);
1151 :
1152 : strcpy (buffer, "+0.95");
1153 : ans = myAtoF (buffer, &value);
1154 : printf ("%d %f : ", ans, value);
1155 : ans = myIsReal_old (buffer, &value);
1156 : printf ("%d %f : '%s'\n", ans, value, buffer);
1157 :
1158 : strcpy (buffer, "0.95, ");
1159 : ans = myAtoF (buffer, &value);
1160 : printf ("%d %f : ", ans, value);
1161 : ans = myIsReal_old (buffer, &value);
1162 : printf ("%d %f : '%s'\n", ans, value, buffer);
1163 :
1164 : strcpy (buffer, "0.95,");
1165 : ans = myAtoF (buffer, &value);
1166 : printf ("%d %f : ", ans, value);
1167 : ans = myIsReal_old (buffer, &value);
1168 : printf ("%d %f : '%s'\n", ans, value, buffer);
1169 :
1170 : strcpy (buffer, "0.9.5");
1171 : ans = myAtoF (buffer, &value);
1172 : printf ("%d %f : ", ans, value);
1173 : ans = myIsReal_old (buffer, &value);
1174 : printf ("%d %f : '%s'\n", ans, value, buffer);
1175 :
1176 : strcpy (buffer, " alph 0.9.5");
1177 : ans = myAtoF (buffer, &value);
1178 : printf ("%d %f : ", ans, value);
1179 : ans = myIsReal_old (buffer, &value);
1180 : printf ("%d %f : '%s'\n", ans, value, buffer);
1181 :
1182 : strcpy (buffer, " ");
1183 : ans = myAtoF (buffer, &value);
1184 : printf ("%d %f : ", ans, value);
1185 : ans = myIsReal_old (buffer, &value);
1186 : printf ("%d %f : '%s'\n", ans, value, buffer);
1187 :
1188 : strcpy (buffer, "");
1189 : ans = myAtoF (buffer, &value);
1190 : printf ("%d %f : ", ans, value);
1191 : ans = myIsReal_old (buffer, &value);
1192 : printf ("%d %f : '%s'\n", ans, value, buffer);
1193 :
1194 : tail = NULL;
1195 : FileTail ("test\\me/now", &tail);
1196 : printf ("%s \n", tail);
1197 : free (tail);
1198 : tail = NULL;
1199 : FileTail ("test/me\\now", &tail);
1200 : printf ("%s \n", tail);
1201 : free (tail);
1202 :
1203 : strcpy (buffer, " here ");
1204 : strTrim (buffer);
1205 : printf ("%s\n", buffer);
1206 :
1207 : strcpy (buffer, " here ");
1208 : strCompact (buffer, ' ');
1209 : printf ("'%s'\n", buffer);
1210 : return 0;
1211 : }
1212 : #endif
|