Fixed default minium size in vsnprintf being 1 (should be 0)
[tpg/acess2.git] / Kernel / lib.c
1 /*
2  * Acess2
3  * Common Library Functions
4  */
5 #include <acess.h>
6
7 // === CONSTANTS ===
8 #define RANDOM_SEED     0xACE55052
9 #define RANDOM_A        0x00731ADE
10 #define RANDOM_C        12345
11 #define RANDOM_SPRUCE   0xf12b039
12 //                          Jan Feb Mar Apr May  Jun  Jul  Aug  Sept Oct  Nov  Dec
13 const short DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
14 #define UNIX_TO_2K      ((30*365*3600*24) + (7*3600*24))        //Normal years + leap years
15
16 // === PROTOTYPES ===
17 #if 0
18  int    atoi(const char *string);
19 void    itoa(char *buf, Uint64 num, int base, int minLength, char pad);
20  int    vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args);
21  int    sprintf(char *__s, const char *__format, ...);
22 #endif
23  int    tolower(int c);
24 #if 0
25  int    strucmp(const char *Str1, const char *Str2);
26 char    *strchr(const char *__s, int __c);
27  int    strpos(const char *Str, char Ch);
28  Uint8  ByteSum(void *Ptr, int Size);
29 size_t  strlen(const char *__s);
30 char    *strcpy(char *__str1, const char *__str2);
31 char    *strncpy(char *__str1, const char *__str2, size_t max);
32  int    strcmp(const char *str1, const char *str2);
33  int    strncmp(const char *str1, const char *str2, size_t num);
34 char    *_strdup(const char *File, int Line, const char *Str);
35 char    **str_split(const char *__str, char __ch);
36  int    strpos8(const char *str, Uint32 Search);
37  int    ReadUTF8(Uint8 *str, Uint32 *Val);
38  int    WriteUTF8(Uint8 *str, Uint32 Val);
39  int    DivUp(int num, int dem);
40 Sint64  timestamp(int sec, int mins, int hrs, int day, int month, int year);
41  int    rand(void);
42  
43  int    CheckString(char *String);
44  int    CheckMem(void *Mem, int NumBytes);
45  
46  int    ModUtil_LookupString(char **Array, char *Needle);
47  int    ModUtil_SetIdent(char *Dest, char *Value);
48  
49  int    UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString);
50 #endif
51
52 // === EXPORTS ===
53 EXPORT(atoi);
54 EXPORT(itoa);
55 EXPORT(vsnprintf);
56 EXPORT(sprintf);
57 EXPORT(tolower);
58 EXPORT(strucmp);
59 EXPORT(strchr);
60 EXPORT(strpos);
61 EXPORT(ByteSum);
62 EXPORT(strlen);
63 EXPORT(strcpy);
64 EXPORT(strncpy);
65 EXPORT(strcmp);
66 EXPORT(strncmp);
67 //EXPORT(strdup);
68 EXPORT(_strdup);        // Takes File/Line too
69 EXPORT(str_split);
70 EXPORT(strpos8);
71 EXPORT(DivUp);
72 EXPORT(ReadUTF8);
73 EXPORT(WriteUTF8);
74 EXPORT(timestamp);
75 EXPORT(CheckString);
76 EXPORT(CheckMem);
77 EXPORT(ModUtil_LookupString);
78 EXPORT(ModUtil_SetIdent);
79 EXPORT(UnHex);
80
81 // === CODE ===
82 /**
83  * \brief Convert a string into an integer
84  */
85 int atoi(const char *string)
86 {
87          int    ret = 0;
88          int    bNeg = 0;
89         
90         //Log("atoi: (string='%s')", string);
91         
92         // Clear non-numeric characters
93         while( !('0' <= *string && *string <= '9') && *string != '-' )  string++;
94         if( *string == '-' ) {
95                 bNeg = 1;
96                 while( !('0' <= *string && *string <= '9') )    string++;
97         }
98         
99         if(*string == '0')
100         {
101                 string ++;
102                 if(*string == 'x')
103                 {
104                         // Hex
105                         string ++;
106                         for( ;; string ++ )
107                         {
108                                 if('0' <= *string && *string <= '9') {
109                                         ret *= 16;
110                                         ret += *string - '0';
111                                 }
112                                 else if('A' <= *string && *string <= 'F') {
113                                         ret *= 16;
114                                         ret += *string - 'A' + 10;
115                                 }
116                                 else if('a' <= *string && *string <= 'f') {
117                                         ret *= 16;
118                                         ret += *string - 'a' + 10;
119                                 }
120                                 else
121                                         break;
122                         }
123                 }
124                 else    // Octal
125                 {
126                         for( ; '0' <= *string && *string <= '7'; string ++ )
127                         {
128                                 ret *= 8;
129                                 ret += *string - '0';
130                         }
131                 }
132         }
133         else    // Decimal
134         {
135                 for( ; '0' <= *string && *string <= '9'; string++)
136                 {
137                         ret *= 10;
138                         ret += *string - '0';
139                 }
140         }
141         
142         if(bNeg)        ret = -ret;
143         
144         //Log("atoi: RETURN %i", ret);
145         
146         return ret;
147 }
148
149 static const char cUCDIGITS[] = "0123456789ABCDEF";
150 /**
151  * \fn void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
152  * \brief Convert an integer into a character string
153  */
154 void itoa(char *buf, Uint64 num, int base, int minLength, char pad)
155 {
156         char    tmpBuf[64+1];
157          int    pos=0, i;
158
159         // Sanity check
160         if(!buf)        return;
161         
162         // Sanity Check
163         if(base > 16 || base < 2) {
164                 buf[0] = 0;
165                 return;
166         }
167         
168         // Convert 
169         while(num > base-1) {
170                 tmpBuf[pos] = cUCDIGITS[ num % base ];
171                 num /= (Uint)base;              // Shift `num` right 1 digit
172                 pos++;
173         }
174         tmpBuf[pos++] = cUCDIGITS[ num % base ];                // Last digit of `num`
175         
176         // Put in reverse
177         i = 0;
178         minLength -= pos;
179         while(minLength-- > 0)  buf[i++] = pad;
180         while(pos-- > 0)                buf[i++] = tmpBuf[pos]; // Reverse the order of characters
181         buf[i] = 0;
182 }
183
184 /**
185  * \brief Append a character the the vsnprintf output
186  */
187 #define PUTCH(c)        do{\
188         char ch=(c);\
189         if(pos==__maxlen){return pos;}\
190         if(__s){__s[pos++]=ch;}else{pos++;}\
191         }while(0)
192 #define GETVAL()        do {\
193         if(isLongLong)  val = va_arg(args, Uint64);\
194         else    val = va_arg(args, unsigned int);\
195         }while(0)
196 /**
197  * \brief VArg String Number Print Formatted
198  */
199 int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args)
200 {
201         char    c, pad = ' ';
202          int    minSize = 0, precision = -1, len;
203         char    tmpBuf[34];     // For Integers
204         const char      *p = NULL;
205          int    isLongLong = 0;
206         Uint64  val;
207         size_t  pos = 0;
208         // Flags
209          int    bPadLeft = 0;
210         
211         //Log("vsnprintf: (__s=%p, __maxlen=%i, __format='%s', ...)", __s, __maxlen, __format);
212         
213         while((c = *__format++) != 0)
214         {
215                 // Non control character
216                 if(c != '%') { PUTCH(c); continue; }
217                 
218                 c = *__format++;
219                 //Log("pos = %i", pos);
220                 
221                 // Literal %
222                 if(c == '%') { PUTCH('%'); continue; }
223                 
224                 // Pointer - Done first for debugging
225                 if(c == 'p') {
226                         Uint    ptr = va_arg(args, Uint);
227                         PUTCH('*');     PUTCH('0');     PUTCH('x');
228                         itoa(tmpBuf, ptr, 16, BITS/4, '0');
229                         p = tmpBuf;
230                         goto printString;
231                 }
232                 
233                 // - Padding Side Flag
234                 if(c == '-') {
235                         bPadLeft = 1;
236                         c = *__format++;
237                 }
238                 
239                 // - Padding
240                 if(c == '0') {
241                         pad = '0';
242                         c = *__format++;
243                 }
244                 else
245                         pad = ' ';
246                 
247                 // - Minimum length
248                 if(c == '*') {  // Dynamic length
249                         minSize = va_arg(args, unsigned int);
250                         c = *__format++;
251                 }
252                 else if('1' <= c && c <= '9')
253                 {
254                         minSize = 0;
255                         while('0' <= c && c <= '9')
256                         {
257                                 minSize *= 10;
258                                 minSize += c - '0';
259                                 c = *__format++;
260                         }
261                 }
262                 else
263                         minSize = 0;
264                 
265                 // - Precision
266                 precision = -1;
267                 if( c == '.' ) {
268                         c = *__format++;
269                         
270                         if(c == '*') {  // Dynamic length
271                                 precision = va_arg(args, unsigned int);
272                                 c = *__format++;
273                         }
274                         else if('1' <= c && c <= '9')
275                         {
276                                 precision = 0;
277                                 while('0' <= c && c <= '9')
278                                 {
279                                         precision *= 10;
280                                         precision += c - '0';
281                                         c = *__format++;
282                                 }
283                         }
284                 }
285                 
286                 // - Default, Long or LongLong?
287                 isLongLong = 0;
288                 if(c == 'l')    // Long is actually the default on x86
289                 {
290                         c = *__format++;
291                         if(c == 'l') {
292                                 c = *__format++;
293                                 isLongLong = 1;
294                         }
295                 }
296                 
297                 // - Now get the format code
298                 p = tmpBuf;
299                 switch(c)
300                 {
301                 case 'd':
302                 case 'i':
303                         GETVAL();
304                         if( isLongLong && val >> 63 ) {
305                                 PUTCH('-');
306                                 val = -val;
307                         }
308                         else if( !isLongLong && val >> 31 ) {
309                                 PUTCH('-');
310                                 val = -(Sint32)val;
311                         }
312                         itoa(tmpBuf, val, 10, minSize, pad);
313                         goto printString;
314                 case 'u':
315                         GETVAL();
316                         itoa(tmpBuf, val, 10, minSize, pad);
317                         goto printString;
318                 case 'X':
319                         if(BITS == 64)
320                                 isLongLong = 1; // TODO: Handle non-x86 64-bit archs
321                         GETVAL();
322                         itoa(tmpBuf, val, 16, minSize, pad);
323                         goto printString;
324                         
325                 case 'x':
326                         GETVAL();
327                         itoa(tmpBuf, val, 16, minSize, pad);
328                         goto printString;
329                 case 'o':
330                         GETVAL();
331                         itoa(tmpBuf, val, 8, minSize, pad);
332                         goto printString;
333                 case 'b':
334                         GETVAL();
335                         itoa(tmpBuf, val, 2, minSize, pad);
336                         goto printString;
337
338                 case 'B':       //Boolean
339                         val = va_arg(args, unsigned int);
340                         if(val) p = "True";
341                         else    p = "False";
342                         goto printString;
343                 
344                 // String - Null Terminated Array
345                 case 's':
346                         p = va_arg(args, char*);        // Get Argument
347                         if( !CheckString(p) )   p = "(inval)";  // Avoid #PFs  
348                 printString:
349                         if(!p)          p = "(null)";
350                         len = strlen(p);
351                         if( !bPadLeft ) while(len++ < minSize)  PUTCH(pad);
352                         while(*p && precision--)        PUTCH(*p++);
353                         if( bPadLeft )  while(len++ < minSize)  PUTCH(pad);
354                         break;
355                 
356                 case 'C':       // Non-Null Terminated Character Array
357                         p = va_arg(args, char*);
358                         if( !CheckMem(p, minSize) )     continue;       // No #PFs please
359                         if(!p)  goto printString;
360                         while(minSize--)        PUTCH(*p++);
361                         break;
362                 
363                 // Single Character
364                 case 'c':
365                 default:
366                         GETVAL();
367                         PUTCH( (Uint8)val );
368                         break;
369                 }
370         }
371         
372         if(__s && pos != __maxlen)
373                 __s[pos] = '\0';
374         
375         return pos;
376 }
377 #undef PUTCH
378
379 /**
380  */
381 int sprintf(char *__s, const char *__format, ...)
382 {
383         va_list args;
384          int    ret;
385         
386         va_start(args, __format);
387         ret = vsnprintf(__s, -1, __format, args);
388         va_end(args);
389         
390         return ret;
391 }
392
393 /**
394  * \fn int tolower(int c)
395  * \brief Converts a character to lower case
396  */
397 int tolower(int c)
398 {
399         if('A' <= c && c <= 'Z')
400                 return c - 'A' + 'a';
401         return c;
402 }
403
404 /**
405  * \fn int strucmp(const char *Str1, const char *Str2)
406  * \brief Compare \a Str1 and \a Str2 case-insensitively
407  */
408 int strucmp(const char *Str1, const char *Str2)
409 {
410         while(*Str1 && tolower(*Str1) == tolower(*Str2))
411                 Str1++, Str2++;
412         return tolower(*Str1) - tolower(*Str2);
413 }
414
415 /**
416  * \brief Locate a byte in a string
417  */
418 char *strchr(const char *__s, int __c)
419 {
420         for( ; *__s; __s ++ )
421         {
422                 if( *__s == __c )       return (char*)__s;
423         }
424         return NULL;
425 }
426
427 /**
428  * \fn int strpos(const char *Str, char Ch)
429  * \brief Search a string for an ascii character
430  */
431 int strpos(const char *Str, char Ch)
432 {
433          int    pos;
434         for(pos=0;Str[pos];pos++)
435         {
436                 if(Str[pos] == Ch)      return pos;
437         }
438         return -1;
439 }
440
441 /**
442  * \fn Uint8 ByteSum(void *Ptr, int Size)
443  * \brief Adds the bytes in a memory region and returns the sum
444  */
445 Uint8 ByteSum(const void *Ptr, int Size)
446 {
447         Uint8   sum = 0;
448         const Uint8     *data = Ptr;
449         while(Size--)   sum += *(data++);
450         return sum;
451 }
452
453 /**
454  * \fn size_t strlen(const char *__str)
455  * \brief Get the length of string
456  */
457 size_t strlen(const char *__str)
458 {
459         size_t  ret = 0;
460         while(*__str++) ret++;
461         return ret;
462 }
463
464 /**
465  * \fn char *strcpy(char *__str1, const char *__str2)
466  * \brief Copy a string to a new location
467  */
468 char *strcpy(char *__str1, const char *__str2)
469 {
470         while(*__str2)
471                 *__str1++ = *__str2++;
472         *__str1 = '\0'; // Terminate String
473         return __str1;
474 }
475
476 /**
477  * \fn char *strncpy(char *__str1, const char *__str2, size_t max)
478  * \brief Copy a string to a new location
479  */
480 char *strncpy(char *__str1, const char *__str2, size_t max)
481 {
482         while(*__str2 && max-- >= 1)
483                 *__str1++ = *__str2++;
484         if(max)
485                 *__str1 = '\0'; // Terminate String
486         return __str1;
487 }
488
489 /**
490  * \fn int strcmp(const char *str1, const char *str2)
491  * \brief Compare two strings return the difference between
492  *        the first non-matching characters.
493  */
494 int strcmp(const char *str1, const char *str2)
495 {
496         while(*str1 && *str1 == *str2)
497                 str1++, str2++;
498         return *str1 - *str2;
499 }
500
501 /**
502  * \fn int strncmp(const char *Str1, const char *Str2, size_t num)
503  * \brief Compare strings \a Str1 and \a Str2 to a maximum of \a num characters
504  */
505 int strncmp(const char *Str1, const char *Str2, size_t num)
506 {
507         if(num == 0)    return 0;       // TODO: Check what should officially happen here
508         while(--num && *Str1 && *Str1 == *Str2)
509                 Str1++, Str2++;
510         return *Str1-*Str2;
511 }
512
513 #if 0
514 /**
515  * \fn char *strdup(const char *Str)
516  * \brief Duplicates a string
517  */
518 char *strdup(const char *Str)
519 {
520         char    *ret;
521         ret = malloc(strlen(Str)+1);
522         if( !ret )      return NULL;
523         strcpy(ret, Str);
524         return ret;
525 }
526 #else
527
528 /**
529  * \fn char *_strdup(const char *File, int Line, const char *Str)
530  * \brief Duplicates a string
531  */
532 char *_strdup(const char *File, int Line, const char *Str)
533 {
534         char    *ret;
535         ret = Heap_Allocate(File, Line, strlen(Str)+1);
536         if( !ret )      return NULL;
537         strcpy(ret, Str);
538         return ret;
539 }
540 #endif
541
542 /**
543  * \brief Split a string using the passed character
544  * \return NULL terminated array of strings on the heap
545  * \param __str String to split
546  * \param __ch  Character to split by
547  */
548 char **str_split(const char *__str, char __ch)
549 {
550          int    i, j;
551          int    len = 1;
552         char    **ret;
553         char    *start;
554         
555         for( i = 0; __str[i]; i++ )
556         {
557                 if(__str[i] == __ch)
558                         len ++;
559         }
560         
561         ret = malloc( sizeof(char*)*(len+1) + (i + 1) );
562         if( !ret )      return NULL;
563         
564         j = 1;
565         start = (char *)&ret[len+1];
566         ret[0] = start;
567         for( i = 0; __str[i]; i++ )
568         {
569                 if(__str[i] == __ch) {
570                         *start++ = '\0';
571                         ret[j++] = start;
572                 }
573                 else {
574                         *start++ = __str[i]; 
575                 }
576         }
577         *start = '\0';
578         ret[j] = NULL;
579         
580         return ret;
581 }
582
583 /**
584  * \fn int DivUp(int num, int dem)
585  * \brief Divide two numbers, rounding up
586  * \param num   Numerator
587  * \param dem   Denominator
588  */
589 int DivUp(int num, int dem)
590 {
591         return (num+dem-1)/dem;
592 }
593
594 /**
595  * \fn int strpos8(const char *str, Uint32 search)
596  * \brief Search a string for a UTF-8 character
597  */
598 int strpos8(const char *str, Uint32 Search)
599 {
600          int    pos;
601         Uint32  val = 0;
602         for(pos=0;str[pos];pos++)
603         {
604                 // ASCII Range
605                 if(Search < 128) {
606                         if(str[pos] == Search)  return pos;
607                         continue;
608                 }
609                 if(*(Uint8*)(str+pos) < 128)    continue;
610                 
611                 pos += ReadUTF8( (Uint8*)&str[pos], &val );
612                 if(val == Search)       return pos;
613         }
614         return -1;
615 }
616
617 /**
618  * \fn int ReadUTF8(Uint8 *str, Uint32 *Val)
619  * \brief Read a UTF-8 character from a string
620  */
621 int ReadUTF8(const Uint8 *str, Uint32 *Val)
622 {
623         *Val = 0xFFFD;  // Assume invalid character
624         
625         // ASCII
626         if( !(*str & 0x80) ) {
627                 *Val = *str;
628                 return 1;
629         }
630         
631         // Middle of a sequence
632         if( (*str & 0xC0) == 0x80 ) {
633                 return 1;
634         }
635         
636         // Two Byte
637         if( (*str & 0xE0) == 0xC0 ) {
638                 *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
639                 str ++;
640                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
641                 *Val |= (*str & 0x3F);  // Lower 6 Bits
642                 return 2;
643         }
644         
645         // Three Byte
646         if( (*str & 0xF0) == 0xE0 ) {
647                 *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
648                 str ++;
649                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
650                 *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
651                 str ++;
652                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
653                 *Val |= (*str & 0x3F);  // Lower 6 Bits
654                 return 3;
655         }
656         
657         // Four Byte
658         if( (*str & 0xF1) == 0xF0 ) {
659                 *Val = (*str & 0x07) << 18;     // Upper 3 Bits
660                 str ++;
661                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
662                 *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
663                 str ++;
664                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
665                 *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
666                 str ++;
667                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
668                 *Val |= (*str & 0x3F);  // Lower 6 Bits
669                 return 4;
670         }
671         
672         // UTF-8 Doesn't support more than four bytes
673         return 4;
674 }
675
676 /**
677  * \fn int WriteUTF8(Uint8 *str, Uint32 Val)
678  * \brief Write a UTF-8 character sequence to a string
679  */
680 int WriteUTF8(Uint8 *str, Uint32 Val)
681 {
682         // ASCII
683         if( Val < 128 ) {
684                 *str = Val;
685                 return 1;
686         }
687         
688         // Two Byte
689         if( Val < 0x8000 ) {
690                 *str = 0xC0 | (Val >> 6);
691                 str ++;
692                 *str = 0x80 | (Val & 0x3F);
693                 return 2;
694         }
695         
696         // Three Byte
697         if( Val < 0x10000 ) {
698                 *str = 0xE0 | (Val >> 12);
699                 str ++;
700                 *str = 0x80 | ((Val >> 6) & 0x3F);
701                 str ++;
702                 *str = 0x80 | (Val & 0x3F);
703                 return 3;
704         }
705         
706         // Four Byte
707         if( Val < 0x110000 ) {
708                 *str = 0xF0 | (Val >> 18);
709                 str ++;
710                 *str = 0x80 | ((Val >> 12) & 0x3F);
711                 str ++;
712                 *str = 0x80 | ((Val >> 6) & 0x3F);
713                 str ++;
714                 *str = 0x80 | (Val & 0x3F);
715                 return 4;
716         }
717         
718         // UTF-8 Doesn't support more than four bytes
719         return 0;
720 }
721
722 /**
723  * \fn Uint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
724  * \brief Converts a date into an Acess Timestamp
725  */
726 Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
727 {
728         Sint64  stamp;
729         stamp = sec;
730         stamp += mins*60;
731         stamp += hrs*3600;
732         
733         stamp += day*3600*24;
734         stamp += month*DAYS_BEFORE[month]*3600*24;
735         if(     (
736                 ((year&3) == 0 || year%100 != 0)
737                 || (year%100 == 0 && ((year/100)&3) == 0)
738                 ) && month > 1) // Leap year and after feb
739                 stamp += 3600*24;
740         
741         stamp += ((365*4+1) * ((year-2000)&~3)) * 3600*24;      // Four Year Segments
742         stamp += ((year-2000)&3) * 365*3600*24; // Inside four year segment
743         stamp += UNIX_TO_2K;
744         
745         return stamp * 1000;
746 }
747
748 /**
749  * \fn int rand()
750  * \brief Pseudo random number generator
751  */
752 int rand(void)
753 {
754         #if 0
755         static Uint     state = RANDOM_SEED;
756         Uint    old = state;
757         // Get the next state value
758         giRandomState = (RANDOM_A*state + RANDOM_C);
759         // Check if it has changed, and if it hasn't, change it
760         if(state == old)        state += RANDOM_SPRUCE;
761         return state;
762         #else
763         // http://en.wikipedia.org/wiki/Xorshift
764         // 2010-10-03
765         static Uint32   x = 123456789;
766         static Uint32   y = 362436069;
767         static Uint32   z = 521288629;
768         static Uint32   w = 88675123; 
769         Uint32  t;
770  
771         t = x ^ (x << 11);
772         x = y; y = z; z = w;
773         return w = w ^ (w >> 19) ^ t ^ (t >> 8); 
774         #endif
775 }
776
777 /* *
778  * \name Memory Validation
779  * \{
780  */
781 /**
782  * \brief Checks if a string resides fully in valid memory
783  */
784 int CheckString(const char *String)
785 {
786         if( !MM_GetPhysAddr( (tVAddr)String ) )
787                 return 0;
788         
789         // Check 1st page
790         if( MM_IsUser( (tVAddr)String ) )
791         {
792                 // Traverse String
793                 while( *String )
794                 {
795                         if( !MM_IsUser( (tVAddr)String ) )
796                                 return 0;
797                         // Increment string pointer
798                         String ++;
799                 }
800                 return 1;
801         }
802         else if( MM_GetPhysAddr( (tVAddr)String ) )
803         {
804                 // Traverse String
805                 while( *String )
806                 {
807                         if( !MM_GetPhysAddr( (tVAddr)String ) )
808                                 return 0;
809                         // Increment string pointer
810                         String ++;
811                 }
812                 return 1;
813         }
814         return 0;
815 }
816
817 /**
818  * \brief Check if a sized memory region is valid memory
819  */
820 int CheckMem(const void *Mem, int NumBytes)
821 {
822         tVAddr  addr = (tVAddr)Mem;
823         
824         if( MM_IsUser( addr ) )
825         {
826                 while( NumBytes-- )
827                 {
828                         if( !MM_IsUser( addr ) )
829                                 return 0;
830                         addr ++;
831                 }
832                 return 1;
833         }
834         else if( MM_GetPhysAddr( addr ) )
835         {
836                 while( NumBytes-- )
837                 {
838                         if( !MM_GetPhysAddr( addr ) )
839                                 return 0;
840                         addr ++;
841                 }
842                 return 1;
843         }
844         return 0;
845 }
846 /* *
847  * \}
848  */
849
850 /**
851  * \brief Search a string array for \a Needle
852  * \note Helper function for eTplDrv_IOCtl::DRV_IOCTL_LOOKUP
853  */
854 int ModUtil_LookupString(const char **Array, const char *Needle)
855 {
856          int    i;
857         if( !CheckString(Needle) )      return -1;
858         for( i = 0; Array[i]; i++ )
859         {
860                 if(strcmp(Array[i], Needle) == 0)       return i;
861         }
862         return -1;
863 }
864
865 int ModUtil_SetIdent(char *Dest, const char *Value)
866 {
867         if( !CheckMem(Dest, 32) )       return -1;
868         strncpy(Dest, Value, 32);
869         return 1;
870 }
871
872 /**
873  * \brief Convert a string of hexadecimal digits into a byte stream
874  */
875 int     UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString)
876 {
877          int    i;
878         
879         for( i = 0; i < DestSize*2; i += 2 )
880         {
881                 Uint8   val = 0;
882                 
883                 if(SourceString[i] == '\0')     break;
884                 
885                 if('0' <= SourceString[i] && SourceString[i] <= '9')
886                         val |= (SourceString[i]-'0') << 4;
887                 else if('A' <= SourceString[i] && SourceString[i] <= 'F')
888                         val |= (SourceString[i]-'A'+10) << 4;
889                 else if('a' <= SourceString[i] && SourceString[i] <= 'f')
890                         val |= (SourceString[i]-'a'+10) << 4;
891                         
892                 if(SourceString[i+1] == '\0')   break;
893                 
894                 if('0' <= SourceString[i+1] && SourceString[i+1] <= '9')
895                         val |= (SourceString[i+1] - '0');
896                 else if('A' <= SourceString[i+1] && SourceString[i+1] <= 'F')
897                         val |= (SourceString[i+1] - 'A' + 10);
898                 else if('a' <= SourceString[i+1] && SourceString[i+1] <= 'f')
899                         val |= (SourceString[i+1] - 'a' + 10);
900                 
901                 Dest[i/2] = val;
902         }
903         return i/2;
904 }

UCC git Repository :: git.ucc.asn.au