Slight change to VMM defines
[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, Uint 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 Uint    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, Uint num, int base, int minLength, char pad)
149  * \brief Convert an integer into a character string
150  */
151 void itoa(char *buf, Uint num, int base, int minLength, char pad)
152 {
153         char    tmpBuf[BITS];
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                         #endif
298                         GETVAL();
299                         itoa(p, val, 16, minSize, pad);
300                         goto printString;
301                         
302                 case 'x':
303                         GETVAL();
304                         itoa(p, val, 16, minSize, pad);
305                         goto printString;
306                 case 'o':
307                         GETVAL();
308                         itoa(p, val, 8, minSize, pad);
309                         goto printString;
310                 case 'b':
311                         GETVAL();
312                         itoa(p, val, 2, minSize, pad);
313                         goto printString;
314
315                 case 'B':       //Boolean
316                         val = va_arg(args, unsigned int);
317                         if(val) p = "True";
318                         else    p = "False";
319                         goto printString;
320                 
321                 // String - Null Terminated Array
322                 case 's':
323                         p = va_arg(args, char*);        // Get Argument
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(!p)  goto printString;
335                         while(minSize--)        PUTCH(*p++);
336                         break;
337                 
338                 // Single Character
339                 case 'c':
340                 default:
341                         GETVAL();
342                         PUTCH( (Uint8)val );
343                         break;
344                 }
345         }
346         
347         if(__s && pos != __maxlen)
348                 __s[pos] = '\0';
349         
350         return pos;
351 }
352 #undef PUTCH
353
354 /**
355  */
356 int sprintf(char *__s, const char *__format, ...)
357 {
358         va_list args;
359          int    ret;
360         
361         va_start(args, __format);
362         ret = vsnprintf(__s, -1, __format, args);
363         va_end(args);
364         
365         return ret;
366 }
367
368 /**
369  * \fn int tolower(int c)
370  * \brief Converts a character to lower case
371  */
372 int tolower(int c)
373 {
374         if('A' <= c && c <= 'Z')
375                 return c - 'A' + 'a';
376         return c;
377 }
378
379 /**
380  * \fn int strucmp(const char *Str1, const char *Str2)
381  * \brief Compare \a Str1 and \a Str2 case-insensitively
382  */
383 int strucmp(const char *Str1, const char *Str2)
384 {
385         while(*Str1 && tolower(*Str1) == tolower(*Str2))
386                 Str1++, Str2++;
387         return tolower(*Str1) - tolower(*Str2);
388 }
389
390 /**
391  * \brief Locate a byte in a string
392  */
393 char *strchr(const char *__s, int __c)
394 {
395         for( ; *__s; __s ++ )
396         {
397                 if( *__s == __c )       return (char*)__s;
398         }
399         return NULL;
400 }
401
402 /**
403  * \fn int strpos(const char *Str, char Ch)
404  * \brief Search a string for an ascii character
405  */
406 int strpos(const char *Str, char Ch)
407 {
408          int    pos;
409         for(pos=0;Str[pos];pos++)
410         {
411                 if(Str[pos] == Ch)      return pos;
412         }
413         return -1;
414 }
415
416 /**
417  * \fn Uint8 ByteSum(void *Ptr, int Size)
418  * \brief Adds the bytes in a memory region and returns the sum
419  */
420 Uint8 ByteSum(void *Ptr, int Size)
421 {
422         Uint8   sum = 0;
423         while(Size--)   sum += *(Uint8*)Ptr++;
424         return sum;
425 }
426
427 /**
428  * \fn Uint strlen(const char *__str)
429  * \brief Get the length of string
430  */
431 Uint strlen(const char *__str)
432 {
433         Uint    ret = 0;
434         while(*__str++) ret++;
435         return ret;
436 }
437
438 /**
439  * \fn char *strcpy(char *__str1, const char *__str2)
440  * \brief Copy a string to a new location
441  */
442 char *strcpy(char *__str1, const char *__str2)
443 {
444         while(*__str2)
445                 *__str1++ = *__str2++;
446         *__str1 = '\0'; // Terminate String
447         return __str1;
448 }
449
450 /**
451  * \fn char *strncpy(char *__str1, const char *__str2, size_t max)
452  * \brief Copy a string to a new location
453  */
454 char *strncpy(char *__str1, const char *__str2, size_t max)
455 {
456         while(*__str2 && max-- >= 1)
457                 *__str1++ = *__str2++;
458         if(max)
459                 *__str1 = '\0'; // Terminate String
460         return __str1;
461 }
462
463 /**
464  * \fn int strcmp(const char *str1, const char *str2)
465  * \brief Compare two strings return the difference between
466  *        the first non-matching characters.
467  */
468 int strcmp(const char *str1, const char *str2)
469 {
470         while(*str1 && *str1 == *str2)
471                 str1++, str2++;
472         return *str1 - *str2;
473 }
474
475 /**
476  * \fn int strncmp(const char *Str1, const char *Str2, size_t num)
477  * \brief Compare strings \a Str1 and \a Str2 to a maximum of \a num characters
478  */
479 int strncmp(const char *Str1, const char *Str2, size_t num)
480 {
481         if(num == 0)    return 0;       // TODO: Check what should officially happen here
482         while(--num && *Str1 && *Str1 == *Str2)
483                 Str1++, Str2++;
484         return *Str1-*Str2;
485 }
486
487 #if 0
488 /**
489  * \fn char *strdup(const char *Str)
490  * \brief Duplicates a string
491  */
492 char *strdup(const char *Str)
493 {
494         char    *ret;
495         ret = malloc(strlen(Str)+1);
496         if( !ret )      return NULL;
497         strcpy(ret, Str);
498         return ret;
499 }
500 #else
501
502 /**
503  * \fn char *_strdup(const char *File, int Line, const char *Str)
504  * \brief Duplicates a string
505  */
506 char *_strdup(const char *File, int Line, const char *Str)
507 {
508         char    *ret;
509         ret = Heap_Allocate(File, Line, strlen(Str)+1);
510         if( !ret )      return NULL;
511         strcpy(ret, Str);
512         return ret;
513 }
514 #endif
515
516 /**
517  * \brief Split a string using the passed character
518  * \return NULL terminated array of strings on the heap
519  * \param __str String to split
520  * \param __ch  Character to split by
521  */
522 char **str_split(const char *__str, char __ch)
523 {
524          int    i, j;
525          int    len = 1;
526         char    **ret;
527         char    *start;
528         
529         for( i = 0; __str[i]; i++ )
530         {
531                 if(__str[i] == __ch)
532                         len ++;
533         }
534         
535         ret = malloc( sizeof(char*)*(len+1) + (i + 1) );
536         if( !ret )      return NULL;
537         
538         j = 1;
539         start = (char *)&ret[len+1];
540         ret[0] = start;
541         for( i = 0; __str[i]; i++ )
542         {
543                 if(__str[i] == __ch) {
544                         *start++ = '\0';
545                         ret[j++] = start;
546                 }
547                 else {
548                         *start++ = __str[i]; 
549                 }
550         }
551         *start = '\0';
552         ret[j] = NULL;
553         
554         return ret;
555 }
556
557 /**
558  * \fn int DivUp(int num, int dem)
559  * \brief Divide two numbers, rounding up
560  * \param num   Numerator
561  * \param dem   Denominator
562  */
563 int DivUp(int num, int dem)
564 {
565         return (num+dem-1)/dem;
566 }
567
568 /**
569  * \fn int strpos8(const char *str, Uint32 search)
570  * \brief Search a string for a UTF-8 character
571  */
572 int strpos8(const char *str, Uint32 Search)
573 {
574          int    pos;
575         Uint32  val = 0;
576         for(pos=0;str[pos];pos++)
577         {
578                 // ASCII Range
579                 if(Search < 128) {
580                         if(str[pos] == Search)  return pos;
581                         continue;
582                 }
583                 if(*(Uint8*)(str+pos) < 128)    continue;
584                 
585                 pos += ReadUTF8( (Uint8*)&str[pos], &val );
586                 if(val == Search)       return pos;
587         }
588         return -1;
589 }
590
591 /**
592  * \fn int ReadUTF8(Uint8 *str, Uint32 *Val)
593  * \brief Read a UTF-8 character from a string
594  */
595 int ReadUTF8(Uint8 *str, Uint32 *Val)
596 {
597         *Val = 0xFFFD;  // Assume invalid character
598         
599         // ASCII
600         if( !(*str & 0x80) ) {
601                 *Val = *str;
602                 return 1;
603         }
604         
605         // Middle of a sequence
606         if( (*str & 0xC0) == 0x80 ) {
607                 return 1;
608         }
609         
610         // Two Byte
611         if( (*str & 0xE0) == 0xC0 ) {
612                 *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
613                 str ++;
614                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
615                 *Val |= (*str & 0x3F);  // Lower 6 Bits
616                 return 2;
617         }
618         
619         // Three Byte
620         if( (*str & 0xF0) == 0xE0 ) {
621                 *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
622                 str ++;
623                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
624                 *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
625                 str ++;
626                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
627                 *Val |= (*str & 0x3F);  // Lower 6 Bits
628                 return 3;
629         }
630         
631         // Four Byte
632         if( (*str & 0xF1) == 0xF0 ) {
633                 *Val = (*str & 0x07) << 18;     // Upper 3 Bits
634                 str ++;
635                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
636                 *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
637                 str ++;
638                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
639                 *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
640                 str ++;
641                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
642                 *Val |= (*str & 0x3F);  // Lower 6 Bits
643                 return 4;
644         }
645         
646         // UTF-8 Doesn't support more than four bytes
647         return 4;
648 }
649
650 /**
651  * \fn int WriteUTF8(Uint8 *str, Uint32 Val)
652  * \brief Write a UTF-8 character sequence to a string
653  */
654 int WriteUTF8(Uint8 *str, Uint32 Val)
655 {
656         // ASCII
657         if( Val < 128 ) {
658                 *str = Val;
659                 return 1;
660         }
661         
662         // Two Byte
663         if( Val < 0x8000 ) {
664                 *str = 0xC0 | (Val >> 6);
665                 str ++;
666                 *str = 0x80 | (Val & 0x3F);
667                 return 2;
668         }
669         
670         // Three Byte
671         if( Val < 0x10000 ) {
672                 *str = 0xE0 | (Val >> 12);
673                 str ++;
674                 *str = 0x80 | ((Val >> 6) & 0x3F);
675                 str ++;
676                 *str = 0x80 | (Val & 0x3F);
677                 return 3;
678         }
679         
680         // Four Byte
681         if( Val < 0x110000 ) {
682                 *str = 0xF0 | (Val >> 18);
683                 str ++;
684                 *str = 0x80 | ((Val >> 12) & 0x3F);
685                 str ++;
686                 *str = 0x80 | ((Val >> 6) & 0x3F);
687                 str ++;
688                 *str = 0x80 | (Val & 0x3F);
689                 return 4;
690         }
691         
692         // UTF-8 Doesn't support more than four bytes
693         return 0;
694 }
695
696 /**
697  * \fn Uint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
698  * \brief Converts a date into an Acess Timestamp
699  */
700 Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
701 {
702         Sint64  stamp;
703         stamp = sec;
704         stamp += mins*60;
705         stamp += hrs*3600;
706         
707         stamp += day*3600*24;
708         stamp += month*DAYS_BEFORE[month]*3600*24;
709         if(     (
710                 ((year&3) == 0 || year%100 != 0)
711                 || (year%100 == 0 && ((year/100)&3) == 0)
712                 ) && month > 1) // Leap year and after feb
713                 stamp += 3600*24;
714         
715         stamp += ((365*4+1) * ((year-2000)&~3)) * 3600*24;      // Four Year Segments
716         stamp += ((year-2000)&3) * 365*3600*24; // Inside four year segment
717         stamp += UNIX_TO_2K;
718         
719         return stamp * 1000;
720 }
721
722 /**
723  * \fn Uint rand()
724  * \brief Pseudo random number generator
725  * \note Unknown effectiveness (made up on the spot)
726  */
727 Uint 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