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

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