3 * Common Library Functions
8 #define RANDOM_SEED 0xACE55052
9 #define RANDOM_A 0x00731ADE
10 #define RANDOM_C 0xBEEF1000
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
16 int ReadUTF8(Uint8 *str, Uint32 *Val);
19 static Uint giRandomState = RANDOM_SEED;
22 static const char cUCDIGITS[] = "0123456789ABCDEF";
24 * \fn static void itoa(char *buf, Uint num, int base, int minLength, char pad)
25 * \brief Convert an integer into a character string
27 void itoa(char *buf, Uint num, int base, int minLength, char pad)
36 if(base > 16 || base < 2) {
43 tmpBuf[pos] = cUCDIGITS[ num % base ];
44 num /= (Uint)base; // Shift `num` right 1 digit
47 tmpBuf[pos++] = cUCDIGITS[ num % base ]; // Last digit of `num`
52 while(minLength-- > 0) buf[i++] = pad;
53 while(pos-- > 0) buf[i++] = tmpBuf[pos]; // Reverse the order of characters
58 * \fn int tolower(int __c)
59 * \brief Converts a character to lower case
63 if('A' <= c && c <= 'Z')
69 * \fn int strucmp(char *Str1, char *Str2)
70 * \brief Compare \a Str1 and \a Str2 case-insensitively
72 int strucmp(char *Str1, char *Str2)
74 while(*Str1 && tolower(*Str1) == tolower(*Str2))
76 return tolower(*Str1) - tolower(*Str2);
80 * \fn int strpos(char *Str, char Ch)
81 * \brief Search a string for an ascii character
83 int strpos(char *Str, char Ch)
86 for(pos=0;Str[pos];pos++)
88 if(Str[pos] == Ch) return pos;
95 int ByteSum(void *Ptr, int Size)
98 while(Size--) sum += *(Uint8*)Ptr++;
103 * \fn Uint strlen(char *__str)
104 * \brief Get the length of string
106 Uint strlen(char *__str)
109 while(*__str++) ret++;
114 * \fn char *strcpy(char *__str1, char *__str2)
115 * \brief Copy a string to a new location
117 char *strcpy(char *__str1, char *__str2)
120 *__str1++ = *__str2++;
121 *__str1 = '\0'; // Terminate String
126 * \fn int strcmp(char *str1, char *str2)
127 * \brief Compare two strings return the difference between
128 * the first non-matching characters.
130 int strcmp(char *str1, char *str2)
132 while(*str1 && *str1 == *str2)
134 return *str1 - *str2;
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
141 int strncmp(char *Str1, char *Str2, size_t num)
143 while(num-- && *Str1 && *Str1 == *Str2)
149 * \fn char *strdup(char *str)
150 * \brief Duplicates a string
152 char *strdup(char *str)
155 ret = malloc(strlen(str)+1);
161 * \fn int strpos8(char *str, Uint32 search)
162 * \brief Search a string for a UTF-8 character
164 int strpos8(char *str, Uint32 Search)
168 for(pos=0;str[pos];pos++)
172 if(str[pos] == Search) return pos;
175 if(*(Uint8*)(str+pos) < 128) continue;
177 pos += ReadUTF8( (Uint8*)&str[pos], &val );
178 if(val == Search) return pos;
184 * \fn int ReadUTF8(Uint8 *str, Uint32 *Val)
185 * \brief Read a UTF-8 character from a string
187 int ReadUTF8(Uint8 *str, Uint32 *Val)
189 *Val = 0xFFFD; // Assume invalid character
192 if( !(*str & 0x80) ) {
197 // Middle of a sequence
198 if( (*str & 0xC0) == 0x80 ) {
203 if( (*str & 0xE0) == 0xC0 ) {
204 *Val = (*str & 0x1F) << 6; // Upper 6 Bits
206 if( (*str & 0xC0) != 0x80) return -1; // Validity check
207 *Val |= (*str & 0x3F); // Lower 6 Bits
212 if( (*str & 0xF0) == 0xE0 ) {
213 *Val = (*str & 0x0F) << 12; // Upper 4 Bits
215 if( (*str & 0xC0) != 0x80) return -1; // Validity check
216 *Val |= (*str & 0x3F) << 6; // Middle 6 Bits
218 if( (*str & 0xC0) != 0x80) return -1; // Validity check
219 *Val |= (*str & 0x3F); // Lower 6 Bits
224 if( (*str & 0xF1) == 0xF0 ) {
225 *Val = (*str & 0x07) << 18; // Upper 3 Bits
227 if( (*str & 0xC0) != 0x80) return -1; // Validity check
228 *Val |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
230 if( (*str & 0xC0) != 0x80) return -1; // Validity check
231 *Val |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
233 if( (*str & 0xC0) != 0x80) return -1; // Validity check
234 *Val |= (*str & 0x3F); // Lower 6 Bits
238 // UTF-8 Doesn't support more than four bytes
243 * \fn int WriteUTF8(Uint8 *str, Uint32 Val)
244 * \brief Write a UTF-8 character sequence to a string
246 int WriteUTF8(Uint8 *str, Uint32 Val)
256 *str = 0xC0 | (Val >> 6);
258 *str = 0x80 | (Val & 0x3F);
263 if( Val < 0x10000 ) {
264 *str = 0xE0 | (Val >> 12);
266 *str = 0x80 | ((Val >> 6) & 0x3F);
268 *str = 0x80 | (Val & 0x3F);
273 if( Val < 0x110000 ) {
274 *str = 0xF0 | (Val >> 18);
276 *str = 0x80 | ((Val >> 12) & 0x3F);
278 *str = 0x80 | ((Val >> 6) & 0x3F);
280 *str = 0x80 | (Val & 0x3F);
284 // UTF-8 Doesn't support more than four bytes
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
292 Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
299 stamp += day*3600*24;
300 stamp += month*DAYS_BEFORE[month]*3600*24;
302 ((year&3) == 0 || year%100 != 0)
303 || (year%100 == 0 && ((year/100)&3) == 0)
304 ) && month > 1) // Leap year and after feb
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
316 * \brief Pseudo random number generator
317 * \note Unknown effectiveness (made up on the spot)
322 Uint ret = giRandomState;
323 int roll = randomState & 31;
324 randomState = (randomState << roll) | (randomState >> (32-roll));
325 randomState ^= 0x9A3C5E78;
328 giRandomState = (RANDOM_A*giRandomState + RANDOM_C) & 0xFFFFFFFF;
329 Log("giRandomState = 0x%x", giRandomState);
330 return giRandomState;