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

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