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

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