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

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