3 * Common Library Functions
8 // Jan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec
9 const short DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
10 #define UNIX_TO_2K ((30*365*3600*24) + (7*3600*24)) //Normal years + leap years
14 Uint8 ByteSum(void *Ptr, int Size);
15 char **str_split(const char *__str, char __ch);
16 int strpos8(const char *str, Uint32 Search);
17 int ReadUTF8(Uint8 *str, Uint32 *Val);
18 int WriteUTF8(Uint8 *str, Uint32 Val);
19 int DivUp(int num, int dem);
20 Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year);
21 void format_date(tTime TS, int *year, int *month, int *day, int *hrs, int *mins, int *sec, int *ms);
23 int ModUtil_LookupString(char **Array, char *Needle);
24 int ModUtil_SetIdent(char *Dest, char *Value);
26 int Hex(char *Dest, size_t Size, const Uint8 *SourceData);
27 int UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString);
29 Uint16 SwapEndian16(Uint16 Val);
30 Uint32 SwapEndian32(Uint16 Val);
31 Uint64 SwapEndian64(Uint16 Val);
42 EXPORT(ModUtil_LookupString);
43 EXPORT(ModUtil_SetIdent);
52 * \fn Uint8 ByteSum(void *Ptr, int Size)
53 * \brief Adds the bytes in a memory region and returns the sum
55 Uint8 ByteSum(const void *Ptr, int Size)
58 const Uint8 *data = Ptr;
59 while(Size--) sum += *(data++);
64 * \brief Split a string using the passed character
65 * \return NULL terminated array of strings on the heap
66 * \param __str String to split
67 * \param __ch Character to split by
69 char **str_split(const char *__str, char __ch)
76 for( i = 0; __str[i]; i++ )
82 ret = malloc( sizeof(char*)*(len+1) + (i + 1) );
83 if( !ret ) return NULL;
86 start = (char *)&ret[len+1];
88 for( i = 0; __str[i]; i++ )
90 if(__str[i] == __ch) {
105 * \fn int DivUp(int num, int dem)
106 * \brief Divide two numbers, rounding up
107 * \param num Numerator
108 * \param dem Denominator
110 int DivUp(int num, int dem)
112 return (num+dem-1)/dem;
116 * \fn int strpos8(const char *str, Uint32 search)
117 * \brief Search a string for a UTF-8 character
119 int strpos8(const char *str, Uint32 Search)
123 for(pos=0;str[pos];pos++)
127 if(str[pos] == (char)Search) return pos;
130 if(*(Uint8*)(str+pos) < 128) continue;
132 pos += ReadUTF8( (Uint8*)&str[pos], &val );
133 if(val == Search) return pos;
139 * \fn int ReadUTF8(Uint8 *str, Uint32 *Val)
140 * \brief Read a UTF-8 character from a string
142 int ReadUTF8(const Uint8 *str, Uint32 *Val)
146 *Val = 0xFFFD; // Assume invalid character
149 if( !(*str & 0x80) ) {
154 // Middle of a sequence
155 if( (*str & 0xC0) == 0x80 ) {
160 if( (*str & 0xE0) == 0xC0 ) {
161 outval = (*str & 0x1F) << 6; // Upper 6 Bits
163 if( (*str & 0xC0) != 0x80) return 2; // Validity check
164 outval |= (*str & 0x3F); // Lower 6 Bits
170 if( (*str & 0xF0) == 0xE0 ) {
171 outval = (*str & 0x0F) << 12; // Upper 4 Bits
173 if( (*str & 0xC0) != 0x80) return 2; // Validity check
174 outval |= (*str & 0x3F) << 6; // Middle 6 Bits
176 if( (*str & 0xC0) != 0x80) return 3; // Validity check
177 outval |= (*str & 0x3F); // Lower 6 Bits
183 if( (*str & 0xF8) == 0xF0 ) {
184 outval = (*str & 0x07) << 18; // Upper 3 Bits
186 if( (*str & 0xC0) != 0x80) return 2; // Validity check
187 outval |= (*str & 0x3F) << 12; // Middle-upper 6 Bits
189 if( (*str & 0xC0) != 0x80) return 3; // Validity check
190 outval |= (*str & 0x3F) << 6; // Middle-lower 6 Bits
192 if( (*str & 0xC0) != 0x80) return 4; // Validity check
193 outval |= (*str & 0x3F); // Lower 6 Bits
198 // UTF-8 Doesn't support more than four bytes
203 * \fn int WriteUTF8(Uint8 *str, Uint32 Val)
204 * \brief Write a UTF-8 character sequence to a string
206 int WriteUTF8(Uint8 *str, Uint32 Val)
219 *str++ = 0xC0 | (Val >> 6);
220 *str++ = 0x80 | (Val & 0x3F);
226 if( Val < 0x10000 ) {
228 *str++ = 0xE0 | (Val >> 12);
229 *str++ = 0x80 | ((Val >> 6) & 0x3F);
230 *str++ = 0x80 | (Val & 0x3F);
236 if( Val < 0x110000 ) {
238 *str++ = 0xF0 | (Val >> 18);
239 *str++ = 0x80 | ((Val >> 12) & 0x3F);
240 *str++ = 0x80 | ((Val >> 6) & 0x3F);
241 *str++ = 0x80 | (Val & 0x3F);
246 // UTF-8 Doesn't support more than four bytes
251 * \fn Uint64 timestamp(int sec, int mins, int hrs, int day, int month, int year)
252 * \brief Converts a date into an Acess Timestamp
254 Sint64 timestamp(int sec, int min, int hrs, int day, int month, int year)
259 if( !(0 <= sec && sec < 60) ) return 0;
260 if( !(0 <= min && min < 60) ) return 0;
261 if( !(0 <= hrs && hrs < 24) ) return 0;
262 if( !(0 <= day && day < 31) ) return 0;
263 if( !(0 <= month && month < 12) ) return 0;
265 stamp = DAYS_BEFORE[month] + day;
270 is_leap = (year % 4 == 0) - (year % 100 == 0) + (year % 400 == 0);
271 ASSERT(is_leap == 0 || is_leap == 1);
273 if( is_leap && month > 1 ) // Leap year and after feb
276 // Get seconds before the first of specified year
277 year -= 2000; // Base off Y2K
278 // base year days + total leap year days
279 stamp += year*365 + (year/400) - (year/100) + (year/4);
290 static Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R);
292 static Sint64 DivMod64(Sint64 N, Sint64 D, Sint64 *R)
294 int sign = (N < 0) != (D < 0);
298 return -DivMod64U(N, D, (Uint64*)R);
300 return DivMod64U(N, D, (Uint64*)R);
303 void format_date(tTime TS, int *year, int *month, int *day, int *hrs, int *mins, int *sec, int *ms)
308 // TODO: Leap-seconds?
311 TS = DivMod64( TS, 1000, &rem );
313 TS = DivMod64( TS, 60, &rem );
315 TS = DivMod64( TS, 60, &rem );
317 TS = DivMod64( TS, 24, &rem );
322 TS -= UNIX_TO_2K/(3600*24);
324 // Year (400 yr blocks) - (400/4-3) leap years
325 *year = 400 * DivMod64( TS, 365*400 + (400/4-3), &TS );
326 if( TS < 366 ) // First year in 400 is a leap
330 // 100 yr blocks - 100/4-1 leap years
331 *year += 100 * DivMod64( TS, 365*100 + (100/4-1), &TS );
332 if( TS < 366 ) // First year in 100 isn't a leap
336 *year += 4 * DivMod64( TS, 365*4 + 1, &TS );
337 if( TS < 366 ) // First year in 4 is a leap
341 *year += DivMod64( TS, 356, &TS );
350 // Month (if after the first of march, which is 29 Feb in a leap year)
351 if( is_leap && TS > DAYS_BEFORE[2] ) {
352 TS -= 1; // Shifts 29 Feb to 28 Feb
355 // Get what month it is
356 for( i = 0; i < 12; i ++ ) {
357 if( TS < DAYS_BEFORE[i] )
362 TS -= DAYS_BEFORE[i-1];
363 *day += TS; // Plus offset from leap handling above
367 * \brief Search a string array for \a Needle
368 * \note Helper function for eTplDrv_IOCtl::DRV_IOCTL_LOOKUP
370 int ModUtil_LookupString(const char **Array, const char *Needle)
373 if( !CheckString(Needle) ) return -1;
374 for( i = 0; Array[i]; i++ )
376 if(strcmp(Array[i], Needle) == 0) return i;
381 int ModUtil_SetIdent(char *Dest, const char *Value)
383 if( !CheckMem(Dest, 32) ) return -1;
384 strncpy(Dest, Value, 32);
388 int Hex(char *Dest, size_t Size, const Uint8 *SourceData)
391 for( i = 0; i < Size; i ++ )
393 sprintf(Dest + i*2, "%02x", SourceData[i]);
399 * \brief Convert a string of hexadecimal digits into a byte stream
401 int UnHex(Uint8 *Dest, size_t DestSize, const char *SourceString)
404 for( i = 0; i < DestSize*2; i += 2 )
408 if(SourceString[i] == '\0') break;
410 if('0' <= SourceString[i] && SourceString[i] <= '9')
411 val |= (SourceString[i]-'0') << 4;
412 else if('A' <= SourceString[i] && SourceString[i] <= 'F')
413 val |= (SourceString[i]-'A'+10) << 4;
414 else if('a' <= SourceString[i] && SourceString[i] <= 'f')
415 val |= (SourceString[i]-'a'+10) << 4;
417 if(SourceString[i+1] == '\0') break;
419 if('0' <= SourceString[i+1] && SourceString[i+1] <= '9')
420 val |= (SourceString[i+1] - '0');
421 else if('A' <= SourceString[i+1] && SourceString[i+1] <= 'F')
422 val |= (SourceString[i+1] - 'A' + 10);
423 else if('a' <= SourceString[i+1] && SourceString[i+1] <= 'f')
424 val |= (SourceString[i+1] - 'a' + 10);
431 Uint16 SwapEndian16(Uint16 Val)
433 return ((Val&0xFF)<<8) | ((Val>>8)&0xFF);
435 Uint32 SwapEndian32(Uint32 Val)
437 return ((Val&0xFF)<<24) | ((Val&0xFF00)<<8) | ((Val>>8)&0xFF00) | ((Val>>24)&0xFF);
439 Uint64 SwapEndian64(Uint64 Val)
441 return SwapEndian32(Val >> 32) | ((Uint64)SwapEndian32(Val) << 32);