libc - Fixed an embarrasing bug in strchr :|
[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, 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 = 1;
264                 
265                 // - Default, Long or LongLong?
266                 isLongLong = 0;
267                 if(c == 'l')    // Long is actually the default on x86
268                 {
269                         c = *__format++;
270                         if(c == 'l') {
271                                 c = *__format++;
272                                 isLongLong = 1;
273                         }
274                 }
275                 
276                 // - Now get the format code
277                 p = tmpBuf;
278                 switch(c)
279                 {
280                 case 'd':
281                 case 'i':
282                         GETVAL();
283                         if( isLongLong && val >> 63 ) {
284                                 PUTCH('-');
285                                 val = -val;
286                         }
287                         else if( !isLongLong && val >> 31 ) {
288                                 PUTCH('-');
289                                 val = -(Sint32)val;
290                         }
291                         itoa(tmpBuf, val, 10, minSize, pad);
292                         goto printString;
293                 case 'u':
294                         GETVAL();
295                         itoa(tmpBuf, val, 10, minSize, pad);
296                         goto printString;
297                 case 'X':
298                         if(BITS == 64)
299                                 isLongLong = 1; // TODO: Handle non-x86 64-bit archs
300                         GETVAL();
301                         itoa(tmpBuf, val, 16, minSize, pad);
302                         goto printString;
303                         
304                 case 'x':
305                         GETVAL();
306                         itoa(tmpBuf, val, 16, minSize, pad);
307                         goto printString;
308                 case 'o':
309                         GETVAL();
310                         itoa(tmpBuf, val, 8, minSize, pad);
311                         goto printString;
312                 case 'b':
313                         GETVAL();
314                         itoa(tmpBuf, val, 2, minSize, pad);
315                         goto printString;
316
317                 case 'B':       //Boolean
318                         val = va_arg(args, unsigned int);
319                         if(val) p = "True";
320                         else    p = "False";
321                         goto printString;
322                 
323                 // String - Null Terminated Array
324                 case 's':
325                         p = va_arg(args, char*);        // Get Argument
326                         if( !CheckString(p) )   continue;       // Avoid #PFs  
327                 printString:
328                         if(!p)          p = "(null)";
329                         len = strlen(p);
330                         if( !bPadLeft ) while(len++ < minSize)  PUTCH(pad);
331                         while(*p)       PUTCH(*p++);
332                         if( bPadLeft )  while(len++ < minSize)  PUTCH(pad);
333                         break;
334                 
335                 case 'C':       // Non-Null Terminated Character Array
336                         p = va_arg(args, char*);
337                         if( !CheckMem(p, minSize) )     continue;       // No #PFs please
338                         if(!p)  goto printString;
339                         while(minSize--)        PUTCH(*p++);
340                         break;
341                 
342                 // Single Character
343                 case 'c':
344                 default:
345                         GETVAL();
346                         PUTCH( (Uint8)val );
347                         break;
348                 }
349         }
350         
351         if(__s && pos != __maxlen)
352                 __s[pos] = '\0';
353         
354         return pos;
355 }
356 #undef PUTCH
357
358 /**
359  */
360 int sprintf(char *__s, const char *__format, ...)
361 {
362         va_list args;
363          int    ret;
364         
365         va_start(args, __format);
366         ret = vsnprintf(__s, -1, __format, args);
367         va_end(args);
368         
369         return ret;
370 }
371
372 /**
373  * \fn int tolower(int c)
374  * \brief Converts a character to lower case
375  */
376 int tolower(int c)
377 {
378         if('A' <= c && c <= 'Z')
379                 return c - 'A' + 'a';
380         return c;
381 }
382
383 /**
384  * \fn int strucmp(const char *Str1, const char *Str2)
385  * \brief Compare \a Str1 and \a Str2 case-insensitively
386  */
387 int strucmp(const char *Str1, const char *Str2)
388 {
389         while(*Str1 && tolower(*Str1) == tolower(*Str2))
390                 Str1++, Str2++;
391         return tolower(*Str1) - tolower(*Str2);
392 }
393
394 /**
395  * \brief Locate a byte in a string
396  */
397 char *strchr(const char *__s, int __c)
398 {
399         for( ; *__s; __s ++ )
400         {
401                 if( *__s == __c )       return (char*)__s;
402         }
403         return NULL;
404 }
405
406 /**
407  * \fn int strpos(const char *Str, char Ch)
408  * \brief Search a string for an ascii character
409  */
410 int strpos(const char *Str, char Ch)
411 {
412          int    pos;
413         for(pos=0;Str[pos];pos++)
414         {
415                 if(Str[pos] == Ch)      return pos;
416         }
417         return -1;
418 }
419
420 /**
421  * \fn Uint8 ByteSum(void *Ptr, int Size)
422  * \brief Adds the bytes in a memory region and returns the sum
423  */
424 Uint8 ByteSum(const void *Ptr, int Size)
425 {
426         Uint8   sum = 0;
427         const Uint8     *data = Ptr;
428         while(Size--)   sum += *(data++);
429         return sum;
430 }
431
432 /**
433  * \fn size_t strlen(const char *__str)
434  * \brief Get the length of string
435  */
436 size_t strlen(const char *__str)
437 {
438         size_t  ret = 0;
439         while(*__str++) ret++;
440         return ret;
441 }
442
443 /**
444  * \fn char *strcpy(char *__str1, const char *__str2)
445  * \brief Copy a string to a new location
446  */
447 char *strcpy(char *__str1, const char *__str2)
448 {
449         while(*__str2)
450                 *__str1++ = *__str2++;
451         *__str1 = '\0'; // Terminate String
452         return __str1;
453 }
454
455 /**
456  * \fn char *strncpy(char *__str1, const char *__str2, size_t max)
457  * \brief Copy a string to a new location
458  */
459 char *strncpy(char *__str1, const char *__str2, size_t max)
460 {
461         while(*__str2 && max-- >= 1)
462                 *__str1++ = *__str2++;
463         if(max)
464                 *__str1 = '\0'; // Terminate String
465         return __str1;
466 }
467
468 /**
469  * \fn int strcmp(const char *str1, const char *str2)
470  * \brief Compare two strings return the difference between
471  *        the first non-matching characters.
472  */
473 int strcmp(const char *str1, const char *str2)
474 {
475         while(*str1 && *str1 == *str2)
476                 str1++, str2++;
477         return *str1 - *str2;
478 }
479
480 /**
481  * \fn int strncmp(const char *Str1, const char *Str2, size_t num)
482  * \brief Compare strings \a Str1 and \a Str2 to a maximum of \a num characters
483  */
484 int strncmp(const char *Str1, const char *Str2, size_t num)
485 {
486         if(num == 0)    return 0;       // TODO: Check what should officially happen here
487         while(--num && *Str1 && *Str1 == *Str2)
488                 Str1++, Str2++;
489         return *Str1-*Str2;
490 }
491
492 #if 0
493 /**
494  * \fn char *strdup(const char *Str)
495  * \brief Duplicates a string
496  */
497 char *strdup(const char *Str)
498 {
499         char    *ret;
500         ret = malloc(strlen(Str)+1);
501         if( !ret )      return NULL;
502         strcpy(ret, Str);
503         return ret;
504 }
505 #else
506
507 /**
508  * \fn char *_strdup(const char *File, int Line, const char *Str)
509  * \brief Duplicates a string
510  */
511 char *_strdup(const char *File, int Line, const char *Str)
512 {
513         char    *ret;
514         ret = Heap_Allocate(File, Line, strlen(Str)+1);
515         if( !ret )      return NULL;
516         strcpy(ret, Str);
517         return ret;
518 }
519 #endif
520
521 /**
522  * \brief Split a string using the passed character
523  * \return NULL terminated array of strings on the heap
524  * \param __str String to split
525  * \param __ch  Character to split by
526  */
527 char **str_split(const char *__str, char __ch)
528 {
529          int    i, j;
530          int    len = 1;
531         char    **ret;
532         char    *start;
533         
534         for( i = 0; __str[i]; i++ )
535         {
536                 if(__str[i] == __ch)
537                         len ++;
538         }
539         
540         ret = malloc( sizeof(char*)*(len+1) + (i + 1) );
541         if( !ret )      return NULL;
542         
543         j = 1;
544         start = (char *)&ret[len+1];
545         ret[0] = start;
546         for( i = 0; __str[i]; i++ )
547         {
548                 if(__str[i] == __ch) {
549                         *start++ = '\0';
550                         ret[j++] = start;
551                 }
552                 else {
553                         *start++ = __str[i]; 
554                 }
555         }
556         *start = '\0';
557         ret[j] = NULL;
558         
559         return ret;
560 }
561
562 /**
563  * \fn int DivUp(int num, int dem)
564  * \brief Divide two numbers, rounding up
565  * \param num   Numerator
566  * \param dem   Denominator
567  */
568 int DivUp(int num, int dem)
569 {
570         return (num+dem-1)/dem;
571 }
572
573 /**
574  * \fn int strpos8(const char *str, Uint32 search)
575  * \brief Search a string for a UTF-8 character
576  */
577 int strpos8(const char *str, Uint32 Search)
578 {
579          int    pos;
580         Uint32  val = 0;
581         for(pos=0;str[pos];pos++)
582         {
583                 // ASCII Range
584                 if(Search < 128) {
585                         if(str[pos] == Search)  return pos;
586                         continue;
587                 }
588                 if(*(Uint8*)(str+pos) < 128)    continue;
589                 
590                 pos += ReadUTF8( (Uint8*)&str[pos], &val );
591                 if(val == Search)       return pos;
592         }
593         return -1;
594 }
595
596 /**
597  * \fn int ReadUTF8(Uint8 *str, Uint32 *Val)
598  * \brief Read a UTF-8 character from a string
599  */
600 int ReadUTF8(const Uint8 *str, Uint32 *Val)
601 {
602         *Val = 0xFFFD;  // Assume invalid character
603         
604         // ASCII
605         if( !(*str & 0x80) ) {
606                 *Val = *str;
607                 return 1;
608         }
609         
610         // Middle of a sequence
611         if( (*str & 0xC0) == 0x80 ) {
612                 return 1;
613         }
614         
615         // Two Byte
616         if( (*str & 0xE0) == 0xC0 ) {
617                 *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
618                 str ++;
619                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
620                 *Val |= (*str & 0x3F);  // Lower 6 Bits
621                 return 2;
622         }
623         
624         // Three Byte
625         if( (*str & 0xF0) == 0xE0 ) {
626                 *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
627                 str ++;
628                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
629                 *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
630                 str ++;
631                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
632                 *Val |= (*str & 0x3F);  // Lower 6 Bits
633                 return 3;
634         }
635         
636         // Four Byte
637         if( (*str & 0xF1) == 0xF0 ) {
638                 *Val = (*str & 0x07) << 18;     // Upper 3 Bits
639                 str ++;
640                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
641                 *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
642                 str ++;
643                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
644                 *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
645                 str ++;
646                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
647                 *Val |= (*str & 0x3F);  // Lower 6 Bits
648                 return 4;
649         }
650         
651         // UTF-8 Doesn't support more than four bytes
652         return 4;
653 }
654
655 /**
656  * \fn int WriteUTF8(Uint8 *str, Uint32 Val)
657  * \brief Write a UTF-8 character sequence to a string
658  */
659 int WriteUTF8(Uint8 *str, Uint32 Val)
660 {
661         // ASCII
662         if( Val < 128 ) {
663                 *str = Val;
664                 return 1;
665         }
666         
667         // Two Byte
668         if( Val < 0x8000 ) {
669                 *str = 0xC0 | (Val >> 6);
670                 str ++;
671                 *str = 0x80 | (Val & 0x3F);
672                 return 2;
673         }
674         
675         // Three Byte
676         if( Val < 0x10000 ) {
677                 *str = 0xE0 | (Val >> 12);
678                 str ++;
679                 *str = 0x80 | ((Val >> 6) & 0x3F);
680                 str ++;
681                 *str = 0x80 | (Val & 0x3F);
682                 return 3;
683         }
684         
685         // Four Byte
686         if( Val < 0x110000 ) {
687                 *str = 0xF0 | (Val >> 18);
688                 str ++;
689                 *str = 0x80 | ((Val >> 12) & 0x3F);
690                 str ++;
691                 *str = 0x80 | ((Val >> 6) & 0x3F);
692                 str ++;
693                 *str = 0x80 | (Val & 0x3F);
694                 return 4;
695         }
696         
697         // UTF-8 Doesn't support more than four bytes
698         return 0;
699 }
700
701 /**
702  * \fn Uint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
703  * \brief Converts a date into an Acess Timestamp
704  */
705 Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
706 {
707         Sint64  stamp;
708         stamp = sec;
709         stamp += mins*60;
710         stamp += hrs*3600;
711         
712         stamp += day*3600*24;
713         stamp += month*DAYS_BEFORE[month]*3600*24;
714         if(     (
715                 ((year&3) == 0 || year%100 != 0)
716                 || (year%100 == 0 && ((year/100)&3) == 0)
717                 ) && month > 1) // Leap year and after feb
718                 stamp += 3600*24;
719         
720         stamp += ((365*4+1) * ((year-2000)&~3)) * 3600*24;      // Four Year Segments
721         stamp += ((year-2000)&3) * 365*3600*24; // Inside four year segment
722         stamp += UNIX_TO_2K;
723         
724         return stamp * 1000;
725 }
726
727 /**
728  * \fn int rand()
729  * \brief Pseudo random number generator
730  */
731 int rand(void)
732 {
733         #if 0
734         static Uint     state = RANDOM_SEED;
735         Uint    old = state;
736         // Get the next state value
737         giRandomState = (RANDOM_A*state + RANDOM_C);
738         // Check if it has changed, and if it hasn't, change it
739         if(state == old)        state += RANDOM_SPRUCE;
740         return state;
741         #else
742         // http://en.wikipedia.org/wiki/Xorshift
743         // 2010-10-03
744         static Uint32   x = 123456789;
745         static Uint32   y = 362436069;
746         static Uint32   z = 521288629;
747         static Uint32   w = 88675123; 
748         Uint32  t;
749  
750         t = x ^ (x << 11);
751         x = y; y = z; z = w;
752         return w = w ^ (w >> 19) ^ t ^ (t >> 8); 
753         #endif
754 }
755
756 /* *
757  * \name Memory Validation
758  * \{
759  */
760 /**
761  * \brief Checks if a string resides fully in valid memory
762  */
763 int CheckString(const char *String)
764 {
765         if( !MM_GetPhysAddr( (tVAddr)String ) )
766                 return 0;
767         
768         // Check 1st page
769         if( MM_IsUser( (tVAddr)String ) )
770         {
771                 // Traverse String
772                 while( *String )
773                 {
774                         if( !MM_IsUser( (tVAddr)String ) )
775                                 return 0;
776                         // Increment string pointer
777                         String ++;
778                 }
779                 return 1;
780         }
781         else if( MM_GetPhysAddr( (tVAddr)String ) )
782         {
783                 // Traverse String
784                 while( *String )
785                 {
786                         if( !MM_GetPhysAddr( (tVAddr)String ) )
787                                 return 0;
788                         // Increment string pointer
789                         String ++;
790                 }
791                 return 1;
792         }
793         return 0;
794 }
795
796 /**
797  * \brief Check if a sized memory region is valid memory
798  */
799 int CheckMem(const void *Mem, int NumBytes)
800 {
801         tVAddr  addr = (tVAddr)Mem;
802         
803         if( MM_IsUser( addr ) )
804         {
805                 while( NumBytes-- )
806                 {
807                         if( !MM_IsUser( addr ) )
808                                 return 0;
809                         addr ++;
810                 }
811                 return 1;
812         }
813         else if( MM_GetPhysAddr( addr ) )
814         {
815                 while( NumBytes-- )
816                 {
817                         if( !MM_GetPhysAddr( addr ) )
818                                 return 0;
819                         addr ++;
820                 }
821                 return 1;
822         }
823         return 0;
824 }
825 /* *
826  * \}
827  */
828
829 /**
830  * \brief Search a string array for \a Needle
831  * \note Helper function for eTplDrv_IOCtl::DRV_IOCTL_LOOKUP
832  */
833 int ModUtil_LookupString(const char **Array, const char *Needle)
834 {
835          int    i;
836         if( !CheckString(Needle) )      return -1;
837         for( i = 0; Array[i]; i++ )
838         {
839                 if(strcmp(Array[i], Needle) == 0)       return i;
840         }
841         return -1;
842 }
843
844 int ModUtil_SetIdent(char *Dest, const char *Value)
845 {
846         if( !CheckMem(Dest, 32) )       return -1;
847         strncpy(Dest, Value, 32);
848         return 1;
849 }
850
851 /**
852  * \brief Convert a string of hexadecimal digits into a byte stream
853  */
854 int     UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString)
855 {
856          int    i;
857         
858         for( i = 0; i < DestSize*2; i += 2 )
859         {
860                 Uint8   val = 0;
861                 
862                 if(SourceString[i] == '\0')     break;
863                 
864                 if('0' <= SourceString[i] && SourceString[i] <= '9')
865                         val |= (SourceString[i]-'0') << 4;
866                 else if('A' <= SourceString[i] && SourceString[i] <= 'F')
867                         val |= (SourceString[i]-'A'+10) << 4;
868                 else if('a' <= SourceString[i] && SourceString[i] <= 'f')
869                         val |= (SourceString[i]-'a'+10) << 4;
870                         
871                 if(SourceString[i+1] == '\0')   break;
872                 
873                 if('0' <= SourceString[i+1] && SourceString[i+1] <= '9')
874                         val |= (SourceString[i+1] - '0');
875                 else if('A' <= SourceString[i+1] && SourceString[i+1] <= 'F')
876                         val |= (SourceString[i+1] - 'A' + 10);
877                 else if('a' <= SourceString[i+1] && SourceString[i+1] <= 'f')
878                         val |= (SourceString[i+1] - 'a' + 10);
879                 
880                 Dest[i/2] = val;
881         }
882         return i/2;
883 }

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