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

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