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

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