blob: 29108017ac0473885a4c48e17500c1c0b6fc0b68 [file] [log] [blame]
Daniel Veillard92ad2102001-03-27 12:47:33 +00001/*************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright (C) 1998 Bjorn Reese and Daniel Stenberg.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
12 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
13 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
14 * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
15 *
16 ************************************************************************/
17
18/* DV for libxml */
19#include "xmlversion.h"
20#ifdef WITH_TRIO
21
22/* FIXME
23 * StrToLongDouble
24 */
25
26static const char rcsid[] = "@(#)$Id$";
27
28#if defined(unix) || defined(__xlC__)
29# define PLATFORM_UNIX
30#elif defined(WIN32) || defined(_WIN32)
31# define PLATFORM_WIN32
32#elif defined(AMIGA) && defined(__GNUC__)
33# define PLATFORM_UNIX
34#endif
35
36#if defined(__STDC__) && (__STDC_VERSION__ >= 199901L)
37# define TRIO_C99
38#endif
39
40#include "strio.h"
41#include <string.h>
42#include <ctype.h>
43#include <stdarg.h>
44#include <time.h>
45#include <math.h>
46#ifndef DEBUG
47# define NDEBUG
48#endif
49#include <assert.h>
50
51#ifndef NULL
52# define NULL 0
53#endif
54#define NIL ((char)0)
55#ifndef FALSE
56# define FALSE (1 == 0)
57# define TRUE (! FALSE)
58#endif
59
60#define VALID(x) (NULL != (x))
61#define INVALID(x) (NULL == (x))
62
63#if defined(PLATFORM_UNIX)
64# define USE_STRCASECMP
65# define USE_STRNCASECMP
66# define USE_STRERROR
67#elif defined(PLATFORM_WIN32)
68# define USE_STRCMPI
69#endif
70
71/*************************************************************************
72 * StrAppendMax
73 */
74char *StrAppendMax(char *target, size_t max, const char *source)
75{
76 assert(VALID(target));
77 assert(VALID(source));
78 assert(max > 0);
79
80 max -= StrLength(target) + 1;
81 return (max > 0) ? strncat(target, source, max) : target;
82}
83
84/*************************************************************************
85 * StrCopyMax
86 */
87char *StrCopyMax(char *target, size_t max, const char *source)
88{
89 assert(VALID(target));
90 assert(VALID(source));
91 assert(max > 0); /* Includes != 0 */
92
93 target = strncpy(target, source, max - 1);
94 target[max - 1] = (char)0;
95 return target;
96}
97
98/*************************************************************************
99 * StrDuplicate
100 */
101char *StrDuplicate(const char *source)
102{
103 char *target;
104
105 assert(VALID(source));
106
107 target = (char *)malloc(StrLength(source) + 1);
108 if (target)
109 {
110 StrCopy(target, source);
111 }
112 return target;
113}
114
115/*************************************************************************
116 * StrDuplicateMax
117 */
118char *StrDuplicateMax(const char *source, size_t max)
119{
120 char *target;
121 size_t len;
122
123 assert(VALID(source));
124 assert(max > 0);
125
126 /* Make room for string plus a terminating zero */
127 len = StrLength(source) + 1;
128 if (len > max)
129 {
130 len = max;
131 }
132 target = (char *)malloc(len);
133 if (target)
134 {
135 StrCopyMax(target, len, source);
136 }
137 return target;
138}
139
140/*************************************************************************
141 * StrEqual
142 */
143int StrEqual(const char *first, const char *second)
144{
145 assert(VALID(first));
146 assert(VALID(second));
147
148 if (VALID(first) && VALID(second))
149 {
150#if defined(USE_STRCASECMP)
151 return (0 == strcasecmp(first, second));
152#elif defined(USE_STRCMPI)
153 return (0 == strcmpi(first, second));
154#else
155 while ((*first != NIL) && (*second != NIL))
156 {
157 if (toupper(*first) != toupper(*second))
158 {
159 break;
160 }
161 first++;
162 second++;
163 }
164 return ((*first == NIL) && (*second == NIL));
165#endif
166 }
167 return FALSE;
168}
169
170/*************************************************************************
171 * StrEqualCase
172 */
173int StrEqualCase(const char *first, const char *second)
174{
175 assert(VALID(first));
176 assert(VALID(second));
177
178 if (VALID(first) && VALID(second))
179 {
180 return (0 == strcmp(first, second));
181 }
182 return FALSE;
183}
184
185/*************************************************************************
186 * StrEqualCaseMax
187 */
188int StrEqualCaseMax(const char *first, size_t max, const char *second)
189{
190 assert(VALID(first));
191 assert(VALID(second));
192
193 if (VALID(first) && VALID(second))
194 {
195 return (0 == strncmp(first, second, max));
196 }
197 return FALSE;
198}
199
200/*************************************************************************
201 * StrEqualMax
202 */
203int StrEqualMax(const char *first, size_t max, const char *second)
204{
205 assert(VALID(first));
206 assert(VALID(second));
207
208 if (VALID(first) && VALID(second))
209 {
210#if defined(USE_STRNCASECMP)
211 return (0 == strncasecmp(first, second, max));
212#else
213 /* Not adequately tested yet */
214 size_t cnt = 0;
215 while ((*first != NIL) && (*second != NIL) && (cnt <= max))
216 {
217 if (toupper(*first) != toupper(*second))
218 {
219 break;
220 }
221 first++;
222 second++;
223 cnt++;
224 }
225 return ((cnt == max) || ((*first == NIL) && (*second == NIL)));
226#endif
227 }
228 return FALSE;
229}
230
231/*************************************************************************
232 * StrError
233 */
234const char *StrError(int errorNumber)
235{
236#if defined(USE_STRERROR)
237 return strerror(errorNumber);
238#else
239 return "unknown";
240#endif
241}
242
243/*************************************************************************
244 * StrFormatDate
245 */
246size_t StrFormatDateMax(char *target,
247 size_t max,
248 const char *format,
249 const struct tm *datetime)
250{
251 assert(VALID(target));
252 assert(VALID(format));
253 assert(VALID(datetime));
254 assert(max > 0);
255
256 return strftime(target, max, format, datetime);
257}
258
259/*************************************************************************
260 * StrHash
261 */
262unsigned long StrHash(const char *string, int type)
263{
264 unsigned long value = 0L;
265 char ch;
266
267 assert(VALID(string));
268
269 switch (type)
270 {
271 case STRIO_HASH_PLAIN:
272 while ( (ch = *string++) != NIL )
273 {
274 value *= 31;
275 value += (unsigned long)ch;
276 }
277 break;
278 default:
279 assert(FALSE);
280 break;
281 }
282 return value;
283}
284
285/*************************************************************************
286 * StrMatch
287 */
288int StrMatch(char *string, char *pattern)
289{
290 assert(VALID(string));
291 assert(VALID(pattern));
292
293 for (; ('*' != *pattern); ++pattern, ++string)
294 {
295 if (NIL == *string)
296 {
297 return (NIL == *pattern);
298 }
299 if ((toupper(*string) != toupper(*pattern))
300 && ('?' != *pattern))
301 {
302 return FALSE;
303 }
304 }
305 /* two-line patch to prevent *too* much recursiveness: */
306 while ('*' == pattern[1])
307 pattern++;
308
309 do
310 {
311 if ( StrMatch(string, &pattern[1]) )
312 {
313 return TRUE;
314 }
315 }
316 while (*string++);
317
318 return FALSE;
319}
320
321/*************************************************************************
322 * StrMatchCase
323 */
324int StrMatchCase(char *string, char *pattern)
325{
326 assert(VALID(string));
327 assert(VALID(pattern));
328
329 for (; ('*' != *pattern); ++pattern, ++string)
330 {
331 if (NIL == *string)
332 {
333 return (NIL == *pattern);
334 }
335 if ((*string != *pattern)
336 && ('?' != *pattern))
337 {
338 return FALSE;
339 }
340 }
341 /* two-line patch to prevent *too* much recursiveness: */
342 while ('*' == pattern[1])
343 pattern++;
344
345 do
346 {
347 if ( StrMatchCase(string, &pattern[1]) )
348 {
349 return TRUE;
350 }
351 }
352 while (*string++);
353
354 return FALSE;
355}
356
357/*************************************************************************
358 * StrSpanFunction
359 *
360 * Untested
361 */
362size_t StrSpanFunction(char *source, int (*Function)(int))
363{
364 size_t count = 0;
365
366 assert(VALID(source));
367 assert(VALID(Function));
368
369 while (*source != NIL)
370 {
371 if (Function(*source))
372 break; /* while */
373 source++;
374 count++;
375 }
376 return count;
377}
378
379/*************************************************************************
380 * StrSubstringMax
381 */
382char *StrSubstringMax(const char *string, size_t max, const char *find)
383{
384 size_t count;
385 size_t size;
386 char *result = NULL;
387
388 assert(VALID(string));
389 assert(VALID(find));
390
391 size = StrLength(find);
392 if (size >= max)
393 {
394 for (count = 0; count > max - size; count++)
395 {
396 if (StrEqualMax(find, size, &string[count]))
397 {
398 result = (char *)&string[count];
399 break;
400 }
401 }
402 }
403 return result;
404}
405
406/*************************************************************************
407 * StrToDouble
408 *
409 * double ::= [ <sign> ]
410 * ( <number> |
411 * <number> <decimal_point> <number> |
412 * <decimal_point> <number> )
413 * [ <exponential> [ <sign> ] <number> ]
414 * number ::= 1*( <digit> )
415 * digit ::= ( '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' )
416 * exponential ::= ( 'e' | 'E' )
417 * sign ::= ( '-' | '+' )
418 * decimal_point ::= '.'
419 */
420double StrToDouble(const char *source, const char **endp)
421{
422#if defined(TRIO_C99)
423 return strtod(source, endp);
424#else
425 /* Preliminary code */
426 int isNegative = FALSE;
427 int isExponentNegative = FALSE;
428 unsigned long integer = 0;
429 unsigned long fraction = 0;
430 unsigned long fracdiv = 1;
431 unsigned long exponent = 0;
432 double value = 0.0;
433
434 /* First try hex-floats */
435 if ((source[0] == '0') && ((source[1] == 'x') || (source[1] == 'X')))
436 {
437 source += 2;
438 while (isxdigit((int)*source))
439 {
440 integer *= 16;
441 integer += (isdigit((int)*source) ? (*source - '0') :
442 (isupper((int)*source) ? (*source - 'A') :
443 (*source - 'a')));
444 source++;
445 }
446 if (*source == '.')
447 {
448 source++;
449 while (isxdigit((int)*source))
450 {
451 fraction *= 16;
452 fraction += (isdigit((int)*source) ? (*source - '0') :
453 (isupper((int)*source) ? (*source - 'A') :
454 (*source - 'a')));
455 fracdiv *= 16;
456 source++;
457 }
458 if ((*source == 'p') || (*source == 'P'))
459 {
460 source++;
461 if ((*source == '+') || (*source == '-'))
462 {
463 isExponentNegative = (*source == '-');
464 source++;
465 }
466 while (isdigit((int)*source))
467 {
468 exponent *= 10;
469 exponent += (*source - '0');
470 source++;
471 }
472 }
473 }
474 }
475 else /* Then try normal decimal floats */
476 {
477 isNegative = (*source == '-');
478 /* Skip sign */
479 if ((*source == '+') || (*source == '-'))
480 source++;
481
482 /* Integer part */
483 while (isdigit((int)*source))
484 {
485 integer *= 10;
486 integer += (*source - '0');
487 source++;
488 }
489
490 if (*source == '.')
491 {
492 source++; /* skip decimal point */
493 while (isdigit((int)*source))
494 {
495 fraction *= 10;
496 fraction += (*source - '0');
497 fracdiv *= 10;
498 source++;
499 }
500 }
501 if ((*source == 'e') || (*source == 'E'))
502 {
503 source++; /* Skip exponential indicator */
504 isExponentNegative = (*source == '-');
505 if ((*source == '+') || (*source == '-'))
506 source++;
507 while (isdigit((int)*source))
508 {
509 exponent *= 10;
510 exponent += (*source - '0');
511 source++;
512 }
513 }
514 }
515
516 value = (double)integer;
517 if (fraction != 0)
518 {
519 value += (double)fraction / (double)fracdiv;
520 }
521 if (exponent != 0)
522 {
523 if (isExponentNegative)
524 value /= pow((double)10, (double)exponent);
525 else
526 value *= pow((double)10, (double)exponent);
527 }
528 if (isNegative)
529 value = -value;
530
531 if (endp)
532 *endp = source;
533 return value;
534#endif
535}
536
537/*************************************************************************
538 * StrToFloat
539 */
540float StrToFloat(const char *source, const char **endp)
541{
542#if defined(TRIO_C99)
543 return strtof(source, endp);
544#else
545 return (float)StrToDouble(source, endp);
546#endif
547}
548
549/*************************************************************************
550 * StrToUpper
551 */
552int StrToUpper(char *target)
553{
554 int i = 0;
555
556 assert(VALID(target));
557
558 while (NIL != *target)
559 {
560 *target = toupper(*target);
561 target++;
562 i++;
563 }
564 return i;
565}
566
567/* DV for libxml */
568#endif /* WITH_TRIO */