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

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