Changed random values again
[tpg/acess2.git] / Kernel / lib.c
1 /*
2  * Acess2
3  * Common Library Functions
4  */
5 #include <common.h>
6
7 // === CONSTANTS ===
8 #define RANDOM_SEED     0xACE55052
9 #define RANDOM_A        0x00731ADE
10 #define RANDOM_C        12345
11 //                          Jan Feb Mar Apr May  Jun  Jul  Aug  Sept Oct  Nov  Dec
12 const short DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
13 #define UNIX_TO_2K      ((30*365*3600*24) + (7*3600*24))        //Normal years + leap years
14
15 // === PROTOTYPES ===
16  int    ReadUTF8(Uint8 *str, Uint32 *Val);
17
18 // === GLOBALS ===
19 static Uint     giRandomState = RANDOM_SEED;
20
21 // === CODE ===
22 static const char cUCDIGITS[] = "0123456789ABCDEF";
23 /**
24  * \fn static void itoa(char *buf, Uint num, int base, int minLength, char pad)
25  * \brief Convert an integer into a character string
26  */
27 void itoa(char *buf, Uint num, int base, int minLength, char pad)
28 {
29         char    tmpBuf[BITS];
30          int    pos=0, i;
31
32         // Sanity check
33         if(!buf)        return;
34         
35         // Sanity Check
36         if(base > 16 || base < 2) {
37                 buf[0] = 0;
38                 return;
39         }
40         
41         // Convert 
42         while(num > base-1) {
43                 tmpBuf[pos] = cUCDIGITS[ num % base ];
44                 num /= (Uint)base;              // Shift `num` right 1 digit
45                 pos++;
46         }
47         tmpBuf[pos++] = cUCDIGITS[ num % base ];                // Last digit of `num`
48         
49         // Put in reverse
50         i = 0;
51         minLength -= pos;
52         while(minLength-- > 0)  buf[i++] = pad;
53         while(pos-- > 0)                buf[i++] = tmpBuf[pos]; // Reverse the order of characters
54         buf[i] = 0;
55 }
56
57 /**
58  * \fn int tolower(int __c)
59  * \brief Converts a character to lower case
60  */
61 int tolower(int c)
62 {
63         if('A' <= c && c <= 'Z')
64                 return c - 'A' + 'a';
65         return c;
66 }
67
68 /**
69  * \fn int strucmp(char *Str1, char *Str2)
70  * \brief Compare \a Str1 and \a Str2 case-insensitively
71  */
72 int strucmp(char *Str1, char *Str2)
73 {
74         while(*Str1 && tolower(*Str1) == tolower(*Str2))
75                 Str1++, Str2++;
76         return tolower(*Str1) - tolower(*Str2);
77 }
78
79 /**
80  * \fn int strpos(char *Str, char Ch)
81  * \brief Search a string for an ascii character
82  */
83 int strpos(char *Str, char Ch)
84 {
85          int    pos;
86         for(pos=0;Str[pos];pos++)
87         {
88                 if(Str[pos] == Ch)      return pos;
89         }
90         return -1;
91 }
92
93 /**
94  */
95 int ByteSum(void *Ptr, int Size)
96 {
97          int    sum = 0;
98         while(Size--)   sum += *(Uint8*)Ptr++;
99         return sum;
100 }
101
102 /**
103  * \fn Uint strlen(char *__str)
104  * \brief Get the length of string
105  */
106 Uint strlen(char *__str)
107 {
108         Uint    ret = 0;
109         while(*__str++) ret++;
110         return ret;
111 }
112
113 /**
114  * \fn char *strcpy(char *__str1, char *__str2)
115  * \brief Copy a string to a new location
116  */
117 char *strcpy(char *__str1, char *__str2)
118 {
119         while(*__str2)
120                 *__str1++ = *__str2++;
121         *__str1 = '\0'; // Terminate String
122         return __str1;
123 }
124
125 /**
126  * \fn int strcmp(char *str1, char *str2)
127  * \brief Compare two strings return the difference between
128  *        the first non-matching characters.
129  */
130 int strcmp(char *str1, char *str2)
131 {
132         while(*str1 && *str1 == *str2)
133                 str1++, str2++;
134         return *str1 - *str2;
135 }
136
137 /**
138  * \fn int strncmp(char *Str1, char *Str2, size_t num)
139  * \brief Compare strings \a Str1 and \a Str2 to a maximum of \a num characters
140  */
141 int strncmp(char *Str1, char *Str2, size_t num)
142 {
143         while(num-- && *Str1 && *Str1 == *Str2)
144                 Str1++, Str2++;
145         return *Str1-*Str2;
146 }
147
148 /**
149  * \fn char *strdup(char *str)
150  * \brief Duplicates a string
151  */
152 char *strdup(char *str)
153 {
154         char    *ret;
155         ret = malloc(strlen(str)+1);
156         strcpy(ret, str);
157         return ret;
158 }
159
160 /**
161  * \fn int strpos8(char *str, Uint32 search)
162  * \brief Search a string for a UTF-8 character
163  */
164 int strpos8(char *str, Uint32 Search)
165 {
166          int    pos;
167         Uint32  val = 0;
168         for(pos=0;str[pos];pos++)
169         {
170                 // ASCII Range
171                 if(Search < 128) {
172                         if(str[pos] == Search)  return pos;
173                         continue;
174                 }
175                 if(*(Uint8*)(str+pos) < 128)    continue;
176                 
177                 pos += ReadUTF8( (Uint8*)&str[pos], &val );
178                 if(val == Search)       return pos;
179         }
180         return -1;
181 }
182
183 /**
184  * \fn int ReadUTF8(Uint8 *str, Uint32 *Val)
185  * \brief Read a UTF-8 character from a string
186  */
187 int ReadUTF8(Uint8 *str, Uint32 *Val)
188 {
189         *Val = 0xFFFD;  // Assume invalid character
190         
191         // ASCII
192         if( !(*str & 0x80) ) {
193                 *Val = *str;
194                 return 1;
195         }
196         
197         // Middle of a sequence
198         if( (*str & 0xC0) == 0x80 ) {
199                 return 1;
200         }
201         
202         // Two Byte
203         if( (*str & 0xE0) == 0xC0 ) {
204                 *Val = (*str & 0x1F) << 6;      // Upper 6 Bits
205                 str ++;
206                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
207                 *Val |= (*str & 0x3F);  // Lower 6 Bits
208                 return 2;
209         }
210         
211         // Three Byte
212         if( (*str & 0xF0) == 0xE0 ) {
213                 *Val = (*str & 0x0F) << 12;     // Upper 4 Bits
214                 str ++;
215                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
216                 *Val |= (*str & 0x3F) << 6;     // Middle 6 Bits
217                 str ++;
218                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
219                 *Val |= (*str & 0x3F);  // Lower 6 Bits
220                 return 3;
221         }
222         
223         // Four Byte
224         if( (*str & 0xF1) == 0xF0 ) {
225                 *Val = (*str & 0x07) << 18;     // Upper 3 Bits
226                 str ++;
227                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
228                 *Val |= (*str & 0x3F) << 12;    // Middle-upper 6 Bits
229                 str ++;
230                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
231                 *Val |= (*str & 0x3F) << 6;     // Middle-lower 6 Bits
232                 str ++;
233                 if( (*str & 0xC0) != 0x80)      return -1;      // Validity check
234                 *Val |= (*str & 0x3F);  // Lower 6 Bits
235                 return 4;
236         }
237         
238         // UTF-8 Doesn't support more than four bytes
239         return 4;
240 }
241
242 /**
243  * \fn int WriteUTF8(Uint8 *str, Uint32 Val)
244  * \brief Write a UTF-8 character sequence to a string
245  */
246 int WriteUTF8(Uint8 *str, Uint32 Val)
247 {
248         // ASCII
249         if( Val < 128 ) {
250                 *str = Val;
251                 return 1;
252         }
253         
254         // Two Byte
255         if( Val < 0x8000 ) {
256                 *str = 0xC0 | (Val >> 6);
257                 str ++;
258                 *str = 0x80 | (Val & 0x3F);
259                 return 2;
260         }
261         
262         // Three Byte
263         if( Val < 0x10000 ) {
264                 *str = 0xE0 | (Val >> 12);
265                 str ++;
266                 *str = 0x80 | ((Val >> 6) & 0x3F);
267                 str ++;
268                 *str = 0x80 | (Val & 0x3F);
269                 return 3;
270         }
271         
272         // Four Byte
273         if( Val < 0x110000 ) {
274                 *str = 0xF0 | (Val >> 18);
275                 str ++;
276                 *str = 0x80 | ((Val >> 12) & 0x3F);
277                 str ++;
278                 *str = 0x80 | ((Val >> 6) & 0x3F);
279                 str ++;
280                 *str = 0x80 | (Val & 0x3F);
281                 return 4;
282         }
283         
284         // UTF-8 Doesn't support more than four bytes
285         return 0;
286 }
287
288 /**
289  * \fn Uint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
290  * \brief Converts a date into an Acess Timestamp
291  */
292 Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
293 {
294         Sint64  stamp;
295         stamp = sec;
296         stamp += mins*60;
297         stamp += hrs*3600;
298         
299         stamp += day*3600*24;
300         stamp += month*DAYS_BEFORE[month]*3600*24;
301         if(     (
302                 ((year&3) == 0 || year%100 != 0)
303                 || (year%100 == 0 && ((year/100)&3) == 0)
304                 ) && month > 1) // Leap year and after feb
305                 stamp += 3600*24;
306         
307         stamp += ((365*4+1) * ((year-2000)&~3)) * 3600*24;      // Foour Year Segments
308         stamp += ((year-2000)&3) * 365*3600*24; // Inside four year segment
309         stamp += UNIX_TO_2K;
310         
311         return stamp * 1000;
312 }
313
314 /**
315  * \fn Uint rand()
316  * \brief Pseudo random number generator
317  * \note Unknown effectiveness (made up on the spot)
318  */
319 Uint rand()
320 {
321         #if 0
322         Uint    ret = giRandomState;
323          int    roll = randomState & 31;
324         randomState = (randomState << roll) | (randomState >> (32-roll));
325         randomState ^= 0x9A3C5E78;
326         return ret;
327         #else
328         giRandomState = (RANDOM_A*giRandomState + RANDOM_C) & 0xFFFFFFFF;
329         Log("giRandomState = 0x%x", giRandomState);
330         return giRandomState;
331         #endif
332 }
333
334 EXPORT(timestamp);
335 EXPORT(ReadUTF8);

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