/[dtapublic]/projs/trunk/shared_source/c_datd/bstrfunc.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_datd/bstrfunc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 56 - (show annotations) (download)
Sat Oct 29 01:53:01 2016 UTC (7 years, 11 months ago) by dashley
File MIME type: text/plain
File size: 31738 byte(s)
License and property (keyword) changes.
1 //$Header$
2 //-------------------------------------------------------------------------------------------------
3 //This file is part of "David T. Ashley's Shared Source Code", a set of shared components
4 //integrated into many of David T. Ashley's projects.
5 //-------------------------------------------------------------------------------------------------
6 //This source code and any program in which it is compiled/used is provided under the MIT License,
7 //reproduced below.
8 //-------------------------------------------------------------------------------------------------
9 //Permission is hereby granted, free of charge, to any person obtaining a copy of
10 //this software and associated documentation files(the "Software"), to deal in the
11 //Software without restriction, including without limitation the rights to use,
12 //copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the
13 //Software, and to permit persons to whom the Software is furnished to do so,
14 //subject to the following conditions :
15 //
16 //The above copyright notice and this permission notice shall be included in all
17 //copies or substantial portions of the Software.
18 //
19 //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
22 //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 //SOFTWARE.
26 //-------------------------------------------------------------------------------------------------
27 #define MODULE_BSTRFUNC
28
29 #include <assert.h>
30 #include <malloc.h>
31 #include <process.h>
32 #include <stddef.h>
33 #include <string.h>
34
35
36 #if defined(APP_TYPE_SIMPLE_DOS_CONSOLE)
37 #include "ccmalloc.h"
38 #elif defined(APP_TYPE_IJUSCRIPTER_IJUCONSOLE)
39 #include "tclalloc.h"
40 #else
41 /* Do nothing. */
42 #endif
43
44 #include "bstrfunc.h"
45 #include "ccmalloc.h"
46 #include "charfunc.h"
47
48
49 /******************************************************************/
50 /*** CUSTOM ALLOCATION FUNCTIONS *******************************/
51 /******************************************************************/
52 //We need wrappers because this software module will be used in
53 //more than one kind of software. This could also be done with
54 //macros, but I like function wrappers better because there
55 //is less ambiguity and more ability to collect information if
56 //something goes wrong.
57 //
58 //07/24/01: Visual inspection only. Function deemed too
59 //simple for unit testing.
60 void *BSTRFUNC_malloc( size_t size )
61 {
62 #if defined(APP_TYPE_SIMPLE_DOS_CONSOLE)
63 return(CCMALLOC_malloc(size));
64 #elif defined(APP_TYPE_IJUSCRIPTER_IJUCONSOLE)
65 return(TclpAlloc(size));
66 #else
67 return(malloc(size));
68 #endif
69 }
70
71
72 //07/24/01: Visual inspection only. Function deemed too
73 //simple for unit testing.
74 void *BSTRFUNC_calloc( size_t num, size_t size )
75 {
76 #if defined(APP_TYPE_SIMPLE_DOS_CONSOLE)
77 return(CCMALLOC_calloc(num, size));
78 #elif defined(APP_TYPE_IJUSCRIPTER_IJUCONSOLE)
79 return(TclpCalloc(num, size));
80 #else
81 return(calloc(num, size));
82 #endif
83 }
84
85
86 //07/24/01: Visual inspection only. Function deemed too
87 //simple for unit testing.
88 void *BSTRFUNC_realloc( void *memblock, size_t size )
89 {
90 #if defined(APP_TYPE_SIMPLE_DOS_CONSOLE)
91 return(CCMALLOC_realloc(memblock, size));
92 #elif defined(APP_TYPE_IJUSCRIPTER_IJUCONSOLE)
93 return(TclpRealloc(memblock, size));
94 #else
95 return(realloc(memblock, size));
96 #endif
97 }
98
99
100 //07/24/01: Visual inspection only. Function deemed too
101 //simple for unit testing.
102 void BSTRFUNC_free( void *memblock )
103 {
104 #if defined(APP_TYPE_SIMPLE_DOS_CONSOLE)
105 CCMALLOC_free(memblock);
106 #elif defined(APP_TYPE_IJUSCRIPTER_IJUCONSOLE)
107 TclpFree(memblock);
108 #else
109 free(memblock);
110 #endif
111 }
112
113
114 //07/18/01: Visual inspection and unit tests passed.
115 int BSTRFUNC_is_uint_wo_commas(const char *arg)
116 {
117 assert(arg != NULL);
118
119 if (!*arg)
120 return(0);
121
122 if (arg[0] == '0')
123 {
124 if (arg[1])
125 {
126 return(0);
127 }
128 else
129 {
130 return(1);
131 }
132 }
133 else
134 {
135 while (*arg)
136 {
137 if ((*arg < '0') || (*arg > '9'))
138 return(0);
139 arg++;
140 }
141
142 return(1);
143 }
144 }
145
146
147 //07/28/01: Visual inspection only.
148 int BSTRFUNC_is_sint_wo_commas(const char *arg)
149 {
150 //This function will use its unsigned counterpart.
151 //
152 //Eyeball the input parameter.
153 assert(arg != NULL);
154
155 if (!*arg) //Empty string ain't an integer.
156 return(0);
157
158 if (*arg == '-')
159 {
160 if (arg[1] == '0')
161 return(0);
162 else
163 return(BSTRFUNC_is_uint_wo_commas(arg+1));
164 }
165 else
166 {
167 return(BSTRFUNC_is_uint_wo_commas(arg));
168 }
169 }
170
171
172 //07/18/01: Visual inspection and unit tests passed.
173 int BSTRFUNC_is_uint_w_commas(const char *arg)
174 {
175 int state;
176
177 //Input pointer cannot be NULL.
178 assert(arg != NULL);
179
180 //Can't be empty string.
181 if (!*arg)
182 return(0);
183
184 //If the first digit is 0, that must be the only digit.
185 if (arg[0] == '0')
186 {
187 if (arg[1])
188 {
189 return(0);
190 }
191 else
192 {
193 return(1);
194 }
195 }
196
197 //The remainder of this function is an efficient state
198 //machine recognizer. The state machine involved is
199 //pretty simple and was drawn and discarded on a sheet
200 //of paper. It doesn't need to be filed because it is
201 //so basic.
202 if ((*arg < '0') || (*arg > '9'))
203 return(0);
204
205 state = 0;
206 arg++;
207
208 while(1)
209 {
210 switch (state)
211 {
212 case 0 : if (!*arg)
213 {
214 return(1);
215 }
216 else if (*arg == ',')
217 {
218 state = 3;
219 }
220 else if ((*arg >= '0') && (*arg <= '9'))
221 {
222 state = 1;
223 }
224 else
225 {
226 return(0);
227 }
228 break;
229 case 1 : if (!*arg)
230 {
231 return(1);
232 }
233 else if (*arg == ',')
234 {
235 state = 3;
236 }
237 else if ((*arg >= '0') && (*arg <= '9'))
238 {
239 state = 2;
240 }
241 else
242 {
243 return(0);
244 }
245 break;
246 case 2 : if (!*arg)
247 {
248 return(1);
249 }
250 else if (*arg == ',')
251 {
252 state = 3;
253 }
254 else if ((*arg >= '0') && (*arg <= '9'))
255 {
256 return(0);
257 }
258 else
259 {
260 return(0);
261 }
262 break;
263 case 3 : if (!*arg)
264 {
265 return(0);
266 }
267 else if (*arg == ',')
268 {
269 return(0);
270 }
271 else if ((*arg >= '0') && (*arg <= '9'))
272 {
273 state = 4;
274 }
275 else
276 {
277 return(0);
278 }
279 break;
280 case 4 : if (!*arg)
281 {
282 return(0);
283 }
284 else if (*arg == ',')
285 {
286 return(0);
287 }
288 else if ((*arg >= '0') && (*arg <= '9'))
289 {
290 state = 5;
291 }
292 else
293 {
294 return(0);
295 }
296 break;
297 case 5 : if (!*arg)
298 {
299 return(0);
300 }
301 else if (*arg == ',')
302 {
303 return(0);
304 }
305 else if ((*arg >= '0') && (*arg <= '9'))
306 {
307 state = 6;
308 }
309 else
310 {
311 return(0);
312 }
313 break;
314 case 6 : if (!*arg)
315 {
316 return(1);
317 }
318 else if (*arg == ',')
319 {
320 state = 3;
321 }
322 else if ((*arg >= '0') && (*arg <= '9'))
323 {
324 return(0);
325 }
326 else
327 {
328 return(0);
329 }
330 break;
331 default:
332 abort();
333 break;
334 }
335
336 arg++;
337 }
338
339 //We should never get here.
340 }
341
342
343 //07/28/01: Visual inspection only.
344 int BSTRFUNC_is_sint_w_commas(const char *arg)
345 {
346 //This function will use its unsigned counterpart.
347 //
348 //Eyeball the input parameter.
349 assert(arg != NULL);
350
351 if (!*arg) //Empty string ain't an integer.
352 return(0);
353
354 if (*arg == '-')
355 {
356 if (arg[1] == '0')
357 return(0);
358 else
359 return(BSTRFUNC_is_uint_w_commas(arg+1));
360 }
361 else
362 {
363 return(BSTRFUNC_is_uint_w_commas(arg));
364 }
365 }
366
367
368 //07/18/01: Visual verification only due to simplicity.
369 void BSTRFUNC_str_reverse(char *s)
370 {
371 int l, begin, end;
372 char temp;
373
374 assert(s != NULL);
375
376 l = strlen(s);
377
378 begin = 0;
379 end = l-1;
380
381 while ((end-begin) >=1)
382 {
383 temp = s[begin];
384 s[begin] = s[end];
385 s[end] = temp;
386 begin++;
387 end--;
388 }
389 }
390
391
392 void BSTRFUNC_parse_gen_sci_not_num(const char *s,
393 int *failure,
394 char *mant_sign,
395 size_t *mant_bdp,
396 size_t *mant_bdp_len,
397 size_t *mant_adp,
398 size_t *mant_adp_len,
399 char *exp_sign,
400 size_t *exp,
401 size_t *exp_len)
402 {
403 //For the parameters that can be NULL, these are the
404 //local copies we keep. We will assign these back to
405 //the caller's area when appropriate before we leave.
406 char i_mant_sign, i_exp_sign;
407 size_t i_mant_bdp, i_mant_bdp_len, i_mant_adp, i_mant_adp_len,
408 i_exp, i_exp_len;
409 size_t i;
410 int state;
411 const char *arg;
412
413 //Check out the parameters that can't be NULL.
414 assert(s != NULL);
415 assert(failure != NULL);
416
417 //Initialize all variables to defaults.
418 *failure = 0 ;
419 i_mant_sign = 'N';
420 i_exp_sign = 'N';
421 i_mant_bdp = 0 ;
422 i_mant_bdp_len = 0 ;
423 i_mant_adp = 0 ;
424 i_mant_adp_len = 0 ;
425 i_exp = 0 ;
426 i_exp_len = 0 ;
427 i = 0 ;
428 state = 0 ;
429
430 //Process the string. This is a big 10-state state
431 //machine. Because of the complexity, I've included
432 //some state definitions as well in the comments.
433 arg = s;
434
435 while(1)
436 {
437 switch (state)
438 {
439 //Initial state from which we start processing.
440 case 0 : if (!*arg)
441 {
442 //The string is empty. This is not OK.
443 //Error out.
444 *failure = 1;
445 goto term_seq;
446 }
447 else if (*arg == '-')
448 {
449 //Leading - on the number. Fine.
450 i_mant_sign = '-';
451 state = 1;
452 }
453 else if (*arg == '+')
454 {
455 //Leading + on the number. Fine.
456 i_mant_sign = '+';
457 state = 2;
458 }
459 else if (*arg == '.')
460 {
461 //Leading . on the number. Fine.
462 state = 5;
463 }
464 else if (*arg == '0')
465 {
466 i_mant_bdp = arg - s;
467 state = 4;
468 }
469 else if ((*arg >= '1') && (*arg <= '9'))
470 {
471 i_mant_bdp = arg - s;
472 state = 3;
473 }
474 else
475 {
476 //Unidentifiable crap. This is not OK.
477 //Error out.
478 *failure = 1;
479 goto term_seq;
480 }
481 break;
482 //The leading character of the string was '-'. We
483 //are processing a negative number.
484 case 1 : if (!*arg)
485 {
486 //The string is empty. This is not OK because
487 //it means the string was "-".
488 //Error out.
489 *failure = 1;
490 goto term_seq;
491 }
492 else if (*arg == '.')
493 {
494 //We have a - followed by a decimal point.
495 //This is impolite form, but will accept
496 //it as a number.
497 state = 5;
498 }
499 else if (*arg == '0')
500 {
501 //We have a '-' followed by a '0'.
502 //Seems reasonable.
503 i_mant_bdp = arg - s;
504 state = 4;
505 }
506 else if ((*arg >= '1') && (*arg <= '9'))
507 {
508 //We have a '-' followed by a non-zero
509 //digit. Seems reasonable.
510 i_mant_bdp = arg - s;
511 state = 3;
512 }
513 else
514 {
515 //Unidentifiable crap. This is not OK.
516 //Error out.
517 *failure = 1;
518 goto term_seq;
519 }
520 break;
521 //The leading character of the string was '+'. We
522 //are processing an explicitly declared positive number.
523 case 2 : if (!*arg)
524 {
525 //The string is empty. This is not OK because
526 //it means the string was "+".
527 //Error out.
528 *failure = 1;
529 goto term_seq;
530 }
531 else if (*arg == '.')
532 {
533 //We have a + followed by a decimal point.
534 //This is impolite form, but will accept
535 //it as a number.
536 state = 5;
537 }
538 else if (*arg == '0')
539 {
540 //We have a '-' followed by a '0'.
541 //Seems reasonable.
542 i_mant_bdp = arg - s;
543 state = 4;
544 }
545 else if ((*arg >= '1') && (*arg <= '9'))
546 {
547 //We have a '+' followed by a non-zero
548 //digit. Seems reasonable.
549 i_mant_bdp = arg - s;
550 state = 3;
551 }
552 else
553 {
554 //Unidentifiable crap. This is not OK.
555 //Error out.
556 *failure = 1;
557 goto term_seq;
558 }
559 break;
560 //We've encountered a non-zero digit either first as part
561 //of the string or later after + or -. We are processing
562 //a mantissa that does not begin with "0".
563 case 3 : if (!*arg)
564 {
565 //We've reached the end of the string. This is
566 //fine because we have a simple integer of the
567 //form NNNN, +NNNN, or -NNNN. No problem with that.
568 i_mant_bdp_len = (arg - s) - i_mant_bdp;
569 *failure = 0;
570 goto term_seq;
571 }
572 else if (*arg == '.')
573 {
574 //Number followed by decimal point. This
575 //means the mantissa is terminating. No issue.
576 i_mant_bdp_len = (arg - s) - i_mant_bdp;
577 state = 5;
578 }
579 else if ((*arg >= '0') && (*arg <= '9'))
580 {
581 //Yet more digits. Seems reasonable.
582 //The assignment isn't necessary, but it
583 //is aesthetic.
584 state = 3;
585 }
586 else if ((*arg == 'e') || (*arg == 'E'))
587 {
588 //Beginning of an exponent. This again
589 //means the mantissa is terminating. No issue.
590 i_mant_bdp_len = (arg - s) - i_mant_bdp;
591 state = 6;
592 }
593 else
594 {
595 //Unidentifiable crap. This is not OK.
596 //Error out.
597 *failure = 1;
598 goto term_seq;
599 }
600 break;
601 //We're processing a mantissa that begins with zero. There
602 //is only one zero allowed before the decimal point.
603 case 4 : if (!*arg)
604 {
605 //We've reached the end of the string. This is
606 //fine because it means we have zero. I'm going
607 //to be unusually permissive and allow -0 and +0,
608 //which isn't traditional.
609 i_mant_bdp_len = (arg - s) - i_mant_bdp;
610 *failure = 0;
611 goto term_seq;
612 }
613 else if (*arg == '.')
614 {
615 //Zero followed by decimal point. This
616 //means the mantissa is terminating. No issue.
617 i_mant_bdp_len = (arg - s) - i_mant_bdp;
618 state = 5;
619 }
620 else if ((*arg == 'e') || (*arg == 'E'))
621 {
622 //Beginning of an exponent. This again
623 //means the mantissa is terminating. No issue.
624 i_mant_bdp_len = (arg - s) - i_mant_bdp;
625 state = 6;
626 }
627 else
628 {
629 //Unidentifiable crap. This is not OK.
630 //Error out.
631 *failure = 1;
632 goto term_seq;
633 }
634 break;
635 //A decimal point has been found in the string.
636 //This marks the end of the mantissa, for sure.
637 case 5 : if (!*arg)
638 {
639 //We've reached the end of the string. There are
640 //two possibilities here. Either there have been no
641 //digits before the decimal points, which is a no-no,
642 //or there have been digits, which is fine.
643 if (i_mant_bdp_len)
644 {
645 *failure = 0;
646 goto term_seq;
647 }
648 else
649 {
650 *failure = 1;
651 goto term_seq;
652 }
653 }
654 else if ((*arg >= '0') && (*arg <= '9'))
655 {
656 //Digits after the decimal point. Need to
657 //begin the portion after the decimal point.
658 i_mant_adp = arg - s;
659 state = 10;
660 }
661 else if ((*arg == 'e') || (*arg == 'E'))
662 {
663 //Beginning of an exponent. This means
664 //that have no digits after the decimal point.
665 //This is OK.
666 state = 6;
667 }
668 else
669 {
670 //Unidentifiable crap. This is not OK.
671 //Error out.
672 *failure = 1;
673 goto term_seq;
674 }
675 break;
676 //The exponent has begin.
677 case 6: if (!*arg)
678 {
679 //The string is empty. This is not OK
680 //because it would mean an E with nothing
681 //following it. This is a no-no.
682 //Error out.
683 *failure = 1;
684 goto term_seq;
685 }
686 else if (*arg == '-')
687 {
688 //Leading - on the exponent. Fine.
689 i_exp_sign = '-';
690 state = 8;
691 }
692 else if (*arg == '+')
693 {
694 //Leading + on the exponent. Fine.
695 i_exp_sign = '+';
696 state = 7;
697 }
698 else if ((*arg >= '0') && (*arg <= '9'))
699 {
700 //Beginning the digits of the exponent. Fine.
701 i_exp = arg - s;
702 state = 9;
703 }
704 else
705 {
706 //Unidentifiable crap. This is not OK.
707 //Error out.
708 *failure = 1;
709 goto term_seq;
710 }
711 break;
712
713 //Had a + sign before the exponent. Now expecting digits.
714 case 7: if (!*arg)
715 {
716 //The string is empty. This is not OK
717 //because it would mean an E+ with nothing
718 //following it. This is a no-no.
719 //Error out.
720 *failure = 1;
721 goto term_seq;
722 }
723 else if ((*arg >= '0') && (*arg <= '9'))
724 {
725 //Beginning the digits of the exponent. Fine.
726 i_exp = arg - s;
727 state = 9;
728 }
729 else
730 {
731 //Unidentifiable crap. This is not OK.
732 //Error out.
733 *failure = 1;
734 goto term_seq;
735 }
736 break;
737 //Had a - sign before the exponent. Now expecting digits.
738 case 8: if (!*arg)
739 {
740 //The string is empty. This is not OK
741 //because it would mean an E- with nothing
742 //following it. This is a no-no.
743 //Error out.
744 *failure = 1;
745 goto term_seq;
746 }
747 else if ((*arg >= '0') && (*arg <= '9'))
748 {
749 //Beginning the digits of the exponent. Fine.
750 i_exp = arg - s;
751 state = 9;
752 }
753 else
754 {
755 //Unidentifiable crap. This is not OK.
756 //Error out.
757 *failure = 1;
758 goto term_seq;
759 }
760 break;
761 //Had one digit of exponent. Am processing remaining ones.
762 case 9 : if (!*arg)
763 {
764 //We've reached the end of the string. This is
765 //fine because we have an exponent of the
766 //form NNNN, +NNNN, or -NNNN. No problem with that.
767 i_exp_len = (arg - s) - i_exp;
768 *failure = 0;
769 goto term_seq;
770 }
771 else if ((*arg >= '0') && (*arg <= '9'))
772 {
773 //Yet more digits. Seems reasonable.
774 //The assignment isn't necessary, but it
775 //is aesthetic.
776 state = 9;
777 }
778 else
779 {
780 //Unidentifiable crap. This is not OK.
781 //Error out.
782 *failure = 1;
783 goto term_seq;
784 }
785 break;
786 //Processing digits after decimal point. This state is out
787 //of sequence because added it after on diagram.
788 case 10: if (!*arg)
789 {
790 //We've reached the end of the string. This is
791 //fine.
792 i_mant_adp_len = (arg - s) - i_mant_adp;
793 *failure = 0;
794 goto term_seq;
795 }
796 else if ((*arg >= '0') && (*arg <= '9'))
797 {
798 //Yet more digits. Seems reasonable.
799 //The assignment isn't necessary, but it
800 //is aesthetic.
801 state = 10;
802 }
803 else if ((*arg == 'e') || (*arg == 'E'))
804 {
805 //Beginning of an exponent. This terminates
806 //the digits after the decimal point.
807 i_mant_adp_len = (arg - s) - i_mant_adp;
808 state = 6;
809 }
810 else
811 {
812 //Unidentifiable crap. This is not OK.
813 //Error out.
814 *failure = 1;
815 goto term_seq;
816 }
817 break;
818 default:
819 abort();
820 break;
821 }
822
823 arg++;
824 }
825
826
827 //This is the setup for returning to the caller. We can
828 //only fill in those data pointer for the caller that are
829 //not NULL.
830 term_seq:
831 if (mant_sign)
832 *mant_sign = i_mant_sign;
833 if (mant_bdp)
834 *mant_bdp = i_mant_bdp;
835 if (mant_bdp_len)
836 *mant_bdp_len = i_mant_bdp_len;
837 if (mant_adp)
838 *mant_adp = i_mant_adp;
839 if (mant_adp_len)
840 *mant_adp_len = i_mant_adp_len;
841 if (exp_sign)
842 *exp_sign = i_exp_sign;
843 if (exp)
844 *exp = i_exp;
845 if (exp_len)
846 *exp_len = i_exp_len;
847 }
848
849
850 //07/18/01: Has passed visual verification plus unit tests.
851 void BSTRFUNC_commanate(char *s)
852 {
853 int l;
854 int ncommas;
855 char *putpt, *getpt;
856 int ndigits;
857
858 //Adds commas to a numeric string. The space
859 //must exist in the area passed.
860 assert(s);
861
862 //If the leading character on the string is a
863 //'-', bump the pointer. Then everything
864 //else applies as for an unsigned.
865 if (*s == '-')
866 s++;
867
868 //Be sure the string currently meets the syntax for
869 //a signed integer. If not, don't even touch it.
870 if (!BSTRFUNC_is_uint_wo_commas(s))
871 return;
872
873 //Get the length of the current string.
874 l = strlen(s);
875
876 //Let's agree, just in case something slipped through
877 //the cracks, that zero length strings are not of
878 //interest to us.
879 if (l==0)
880 return;
881
882 //The number of commas to add is precisely
883 //(N-1) div 3.
884 if (l==0)
885 ncommas = 0;
886 else
887 ncommas = (l-1)/3;
888
889 //Walk through the string, adding commas.
890 getpt = s + l - 1;
891 putpt = s + l + ncommas;
892
893 *putpt = 0; //Write the zero terminator.
894 putpt--;
895
896 ndigits = 0;
897
898 while ((putpt > s) && (getpt > s))
899 {
900 *putpt = *getpt;
901 putpt--;
902 getpt--;
903 ndigits++;
904 if (((ndigits % 3) == 0) && (putpt != s))
905 {
906 *putpt = ',';
907 putpt--;
908 }
909 assert((putpt >= s) && (getpt>=s));
910 }
911 }
912
913
914 //07/28/01: Visual inspection only.
915 void BSTRFUNC_decommanate(char *s)
916 {
917 char *src, *dst;
918
919 assert(s != NULL);
920
921 src = dst = s;
922
923 while(1)
924 {
925 if (!*src)
926 {
927 *dst = 0;
928 break;
929 }
930 else if (*src == ',')
931 {
932 src++;
933 }
934 else
935 {
936 *dst = *src;
937 src++;
938 dst++;
939 }
940 }
941 }
942
943
944 void BSTRFUNC_parse_str_to_uint32(const char *s,
945 unsigned int *rv,
946 int *error)
947 {
948 unsigned _int64 temp;
949 int digval;
950
951 //Eyeball the input arguments.
952 assert(s != NULL);
953 assert(error != NULL);
954
955 //Start off believing there is no error.
956 *error = 0;
957
958 //The string has to parse out as an unsigned integer or an
959 //unsigned integer with commas, or we won't touch it.
960 if (!BSTRFUNC_is_uint_wo_commas(s) && !BSTRFUNC_is_uint_w_commas(s))
961 {
962 *error = 1;
963 return;
964 }
965
966 //OK, we know we have an unsigned integer, either without commas,
967 //or with properly placed commas. Our only worry now is that it
968 //is of a size that will fit in 32 bits. The way we can deal with
969 //this is to format it into 64 bits and watch for overflow.
970 temp = 0;
971
972 while (*s)
973 {
974 digval = CHARFUNC_digit_to_val(*s);
975 if (digval >= 0)
976 {
977 temp *= 10;
978 temp += digval;
979 if ((temp >> 32) & 0xFFFFFFFF)
980 {
981 //We've had an overflow.
982 *error = 1;
983 return;
984 }
985 }
986 s++;
987 }
988
989 *rv = (unsigned int)temp;
990 }
991
992
993 const char *BSTRFUNC_cvcinfo(void)
994 {
995 return("$Header$");
996 }
997
998
999 const char *BSTRFUNC_hvcinfo(void)
1000 {
1001 return(BSTRFUNC_H_VERSION);
1002 }
1003
1004 //End of bstrfunc.c.

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25