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

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