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

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