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

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