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

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