1/*---------------------------------------------------------------------------*
2 |              PDFlib - A library for generating PDF on the fly             |
3 +---------------------------------------------------------------------------+
4 | Copyright (c) 1997-2004 Thomas Merz and PDFlib GmbH. All rights reserved. |
5 +---------------------------------------------------------------------------+
6 |                                                                           |
7 |    This software is subject to the PDFlib license. It is NOT in the       |
8 |    public domain. Extended versions and commercial licenses are           |
9 |    available, please check http://www.pdflib.com.                         |
10 |                                                                           |
11 *---------------------------------------------------------------------------*/
12
13/* $Id: pc_util.c 14574 2005-10-29 16:27:43Z bonefish $
14 *
15 * Various utility routines
16 *
17 */
18
19#include <errno.h>
20
21#include "pc_util.h"
22
23#ifdef AS400
24#include <qp0z1170.h>   /* for getenv() emulation */
25#endif
26
27/* -------------------------- Time functions ------------------------------ */
28
29#ifndef WINCE
30#include <time.h>
31#else
32#include <winbase.h>
33#endif
34
35void
36pdc_get_timestr(char *str)
37{
38#ifndef WINCE
39    time_t      timer, gtimer;
40    struct tm   ltime;
41    double      diffminutes;
42    int         utcoffset;
43#else
44    SYSTEMTIME  st;
45#endif
46
47#ifndef WINCE
48    time(&timer);
49
50    /* Calculate UTC offset with standard C functions. */
51    /* gmtime(), localtime and mktime() all use the same internal */
52    /* buffer. That is why it is done in multiple steps. */
53    ltime = *gmtime(&timer);
54    gtimer = mktime(&ltime);
55    ltime = *localtime(&timer);
56    ltime.tm_isdst = 0;
57    diffminutes = difftime(mktime(&ltime), gtimer) / 60;
58    if (diffminutes >= 0)
59        utcoffset = (int)(diffminutes + 0.5);
60    else
61        utcoffset = (int)(diffminutes - 0.5);
62
63    /* Get local time again, previous data is damaged by mktime(). */
64    ltime = *localtime(&timer);
65
66    if (utcoffset > 0)
67        sprintf(str, "D:%04d%02d%02d%02d%02d%02d+%02d'%02d'",
68            ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
69            ltime.tm_hour, ltime.tm_min, ltime.tm_sec,
70            utcoffset / 60, utcoffset % 60);
71    else if (utcoffset < 0)
72        sprintf(str, "D:%04d%02d%02d%02d%02d%02d-%02d'%02d'",
73            ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
74            ltime.tm_hour, ltime.tm_min, ltime.tm_sec,
75            abs(utcoffset) / 60, abs(utcoffset) % 60);
76    else
77        sprintf(str, "D:%04d%02d%02d%02d%02d%02dZ",
78            ltime.tm_year + 1900, ltime.tm_mon + 1, ltime.tm_mday,
79            ltime.tm_hour, ltime.tm_min, ltime.tm_sec);
80
81#else
82    GetLocalTime (&st);
83    sprintf(str, "D:%04d%02d%02d%02d%02d%02d",
84            st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
85#endif  /* !WINCE */
86}
87
88/* -------------------------- Environment ------------------------------ */
89
90char *
91pdc_getenv(const char *name)
92{
93#ifdef HAVE_ENVVARS
94    return getenv(name);
95#else
96    (void) name;
97
98    return (char *) 0;
99#endif
100}
101
102
103/* -------------------------- Bit arryas ------------------------------ */
104
105void
106pdc_setbit(char *bitarr, int bit)
107{
108    bitarr[bit/8] |= (char) (1<<(bit%8));
109}
110
111pdc_bool
112pdc_getbit(char *bitarr, int bit)
113{
114    return (pdc_bool) (bitarr[bit/8] & (1<<(bit%8)));
115}
116
117void
118pdc_setbit_text(char *bitarr, const pdc_byte *text, int len,
119                int nbits, int size)
120{
121    int i, bit;
122    pdc_ushort *ustext = (pdc_ushort *) text;
123
124    for (i = 0; i < len; i += size)
125    {
126        if (size == sizeof(pdc_byte))
127            bit = (int) text[i];
128        else
129            bit = ustext[i/size];
130        if (bit < nbits) pdc_setbit(bitarr, bit);
131    }
132}
133
134
135/* ---------- Get functions of integer binary data types --------------- */
136
137pdc_short
138pdc_get_le_short(pdc_byte *data)
139{
140    return (pdc_short) ((pdc_short) (data[1] << 8) | data[0]);
141}
142
143pdc_ushort
144pdc_get_le_ushort(pdc_byte *data)
145{
146    return (pdc_ushort) ((data[1] << 8) | data[0]);
147}
148
149pdc_ulong
150pdc_get_le_ulong3(pdc_byte *data)
151{
152    return (pdc_ulong) (((((data[2]) << 8) | data[1]) << 8) | data[0]);
153}
154
155pdc_long
156pdc_get_le_long(pdc_byte *data)
157{
158    return ((pdc_long)
159         (((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]);
160}
161
162pdc_ulong
163pdc_get_le_ulong(pdc_byte *data)
164{
165    return (pdc_ulong)
166         ((((((data[3] << 8) | data[2]) << 8) | data[1]) << 8) | data[0]);
167}
168
169pdc_short
170pdc_get_be_short(pdc_byte *data)
171{
172    return (pdc_short) ((pdc_short) (data[0] << 8) | data[1]);
173}
174
175pdc_ushort
176pdc_get_be_ushort(pdc_byte *data)
177{
178    return (pdc_ushort) ((data[0] << 8) | data[1]);
179}
180
181pdc_ulong
182pdc_get_be_ulong3(pdc_byte *data)
183{
184    return (pdc_ulong) (((((data[0]) << 8) | data[1]) << 8) | data[2]);
185}
186
187pdc_long
188pdc_get_be_long(pdc_byte *data)
189{
190    return ((pdc_long)
191         (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]);
192}
193
194pdc_ulong
195pdc_get_be_ulong(pdc_byte *data)
196{
197    return (pdc_ulong)
198        ((((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3]);
199}
200
201
202/* ----------------- String handling for Unicode too ------------------- */
203
204/* strlen() for unicode strings, which are terminated by two zero bytes.
205 * wstrlen() returns the number of bytes in the Unicode string,
206 * not including the two terminating null bytes.
207 */
208static size_t
209wstrlen(const char *s)
210{
211    size_t len;
212
213    for(len = 0;
214        (pdc_byte) (s[len++]) != 0 ||
215        (pdc_byte) (s[len++]) != 0; /* */ ) {
216	/* */
217    }
218
219    return len-2;
220}
221
222/*
223 * This function returns the length in bytes for C and Unicode strings.
224 * Note that unlike strlen() it returns the length _including_ the
225 * terminator, which may be one or two null bytes.
226 */
227size_t
228pdc_strlen(const char *text)
229{
230    if (pdc_is_unicode(text))
231	return wstrlen(text) + 2;
232    else
233	return strlen(text) + 1;
234}
235
236
237/* Allocate a local buffer and copy the string including
238 * the terminating sentinel. If the string starts with the Unicode BOM
239 * it is considered a Unicode string, and must be terminated by
240 * two null bytes. Otherwise it is considered a plain C string and
241 * must be terminated by a single null byte.
242 * The caller is responsible for freeing the buffer.
243 */
244char *
245pdc_strdup(pdc_core *pdc, const char *text)
246{
247    char *buf;
248    size_t len;
249    static const char fn[] = "pdc_strdup";
250
251    if (text == NULL)
252	pdc_error(pdc, PDC_E_INT_NULLARG, fn, 0, 0, 0);
253
254    len = pdc_strlen(text);
255    buf = (char *) pdc_malloc(pdc, len, fn);
256    memcpy(buf, text, len);
257
258    return buf;
259}
260
261/* Put out a 2 byte string for printing on the screen by replacing
262 * characters < 0x20 by space. The string will be limited to 40 byte.
263 */
264
265#define PDC_STRPRINTLEN 80
266const char *
267pdc_strprint(pdc_core *pdc, const char *str, int len)
268{
269    pdc_byte c, tmpstr[PDC_STRPRINTLEN + 4];
270    int i = 0, maxi;
271
272    if (str)
273    {
274        if (!len)
275            len = (int) strlen(str);
276        maxi = (len > PDC_STRPRINTLEN) ? PDC_STRPRINTLEN : len;
277        for (i = 0; i < maxi; i++)
278        {
279            c = (pdc_byte) str[i];
280            tmpstr[i] = (c < 0x20) ? (pdc_byte) ' ' : c;
281        }
282    }
283    tmpstr[i] = 0;
284    if (len > PDC_STRPRINTLEN)
285        strcat((char *) tmpstr, "...");
286
287    return pdc_errprintf(pdc, "%s", tmpstr);
288}
289
290/*
291 * Split a given text string into single strings which are separated by
292 * arbitrary characters. This characters must be specified in a string.
293 * If this string is NULL, " \f\n\r\t\v" (standard white spaces) is assumed.
294 *
295 * There is the convention that text inside braces {} will be taken verbatim.
296 * Inside brace expressions braces must exist only in pairs. Braces are
297 * masked by backslash.
298 *
299 * The caller is responsible for freeing the resultated string list
300 * by calling the function pdc_cleanup_stringlist.
301 *
302 * Not for unicode strings.
303 *
304 * Return value: Number of strings.
305 *               If braces aren't balanced the number is negative.
306 *
307 */
308
309int
310pdc_split_stringlist(pdc_core *pdc, const char *text, const char *i_separstr,
311                     char ***stringlist)
312{
313    static const char fn[] = "pdc_split_stringlist";
314    const char *separstr = " \f\n\r\t\v";
315    const char *oldtext;
316    char **strlist = NULL, *newtext;
317    int i, it, len, jt = 0, jtb = 0, maxk = 0, count = 0, inside = 0;
318
319    if (text == NULL)
320	pdc_error(pdc, PDC_E_INT_NULLARG, fn, 0, 0, 0);
321
322    if (stringlist)
323        *stringlist = NULL;
324    if (i_separstr)
325        separstr = i_separstr;
326
327    /* check for empty string */
328    i = (int) strspn(text, separstr);
329    oldtext = &text[i];
330    len = (int) strlen(oldtext);
331    if (!len) return 0;
332
333    newtext = (char *) pdc_malloc(pdc, (size_t) (len + 1), fn);
334    for (it = 0; it <= len; it++)
335    {
336        /* check for separators */
337        if (it == len)
338            i = 1;
339        else if (inside <= 0)
340            i = (int) strspn(&oldtext[it], separstr);
341        else
342            i = 0;
343
344        /* close text part */
345        if (i)
346        {
347            newtext[jt] = 0;
348            if (count == maxk)
349            {
350                maxk += 16;
351                strlist = (strlist == NULL) ?
352                    (char **) pdc_malloc(pdc, maxk * sizeof(char *), fn):
353                    (char **) pdc_realloc(pdc, strlist, maxk *
354                                          sizeof(char *), fn);
355            }
356            strlist[count] = &newtext[jtb];
357            count++;
358
359            /* Exit */
360            it += i;
361            if (it >= len ) break;
362
363            /* new text part */
364            jt++;
365            jtb = jt;
366        }
367
368        /* open and close brace */
369        if (oldtext[it] == '{')
370        {
371            inside++;
372            if (inside == 1)
373                continue;
374        }
375        else if (oldtext[it] == '}')
376        {
377            inside--;
378            if (inside == 0)
379                continue;
380        }
381
382        /* masked braces */
383        if (oldtext[it] == '\\' &&
384            (oldtext[it+1] == '{' || oldtext[it+1] == '}'))
385            it++;
386
387        /* save character */
388        newtext[jt] = oldtext[it];
389        jt++;
390    }
391
392    if (stringlist)
393        *stringlist = strlist;
394    return inside ? -count : count;
395}
396
397void
398pdc_cleanup_stringlist(pdc_core *pdc, char **stringlist)
399{
400    if(stringlist != NULL)
401    {
402	if(stringlist[0] != NULL)
403	    pdc_free(pdc, stringlist[0]);
404
405 	pdc_free(pdc, stringlist);
406    }
407}
408
409
410/*
411 * Compares its arguments and returns an integer less than,
412 * equal to, or greater than zero, depending on whether s1
413 * is lexicographically less than, equal to, or greater than s2.
414 * Null pointer values for s1 and s2 are treated the same as pointers
415 * to empty strings.
416 *
417 * Presupposition: basic character set
418 *
419 * Return value:  < 0  s1 <  s2;
420 *		  = 0  s1 == s2;
421 *		  > 0  s1 >  s2;
422 *
423 */
424int
425pdc_stricmp(const char *s1, const char *s2)
426{
427    char c1, c2;
428
429    if (s1 == s2) return (0);
430    if (s1 == NULL) return (-1);
431    if (s2 == NULL) return (1);
432
433    for (; *s1 != '\0' && *s2 != '\0';  s1++, s2++)
434    {
435	if ((c1 = *s1) == (c2 = *s2))
436	    continue;
437
438	if (islower((int)c1)) c1 = (char) toupper((int)c1);
439	if (islower((int)c2)) c2 = (char) toupper((int)c2);
440	if (c1 != c2)
441	    break;
442    }
443    return (*s1 - *s2);
444}
445
446
447/*
448 * Compares its arguments and returns an integer less than,
449 * equal to, or greater than zero, depending on whether s1
450 * is lexicographically less than, equal to, or greater than s2.
451 * But only up to n characters compared (n less than or equal
452 * to zero yields equality).Null pointer values for s1 and s2
453 * are treated the same as pointers to empty strings.
454 *
455 * Presupposition: basic character set
456 *
457 * Return value:  < 0  s1 <  s2;
458 *		  = 0  s1 == s2;
459 *		  > 0  s1 >  s2;
460 *
461 */
462int
463pdc_strincmp(const char *s1, const char *s2, int n)
464{
465    char c1, c2;
466    int  i;
467
468    if (s1 == s2)   return (0);
469    if (s1 == NULL) return (-1);
470    if (s2 == NULL) return (1);
471
472    for (i=0;  i < n && *s1 != '\0' && *s2 != '\0';  i++, s1++, s2++)
473    {
474	if ((c1 = *s1) == (c2 = *s2))
475	    continue;
476
477	if (islower((int)c1)) c1 = (char) toupper((int)c1);
478	if (islower((int)c2)) c2 = (char) toupper((int)c2);
479	if (c1 != c2)
480	    break;
481    }
482    return ((i < n) ?  (int)(*s1 - *s2) : 0);
483}
484
485/*
486 * pdc_strtrim removes trailing white space characters from an input string.
487 * pdc_str2trim removes leading and trailing white space characters from an
488 * input string..
489 */
490char *
491pdc_strtrim(char *str)
492{
493    int i;
494
495    for (i = (int) strlen(str) - 1; i >= 0; i--)
496        if (!isspace((unsigned char) str[i])) break;
497    str[i + 1] = '\0';
498
499    return str;
500}
501
502char *
503pdc_str2trim(char *str)
504{
505    int i;
506
507    for (i = (int) strlen(str) - 1; i >= 0; i--)
508        if (!isspace((unsigned char) str[i])) break;
509    str[i + 1] = '\0';
510
511    for (i = 0; ; i++)
512        if (!isspace((unsigned char) str[i])) break;
513    if (i > 0)
514        memmove(str, &str[i], strlen(&str[i]) + 1);
515
516    return str;
517}
518
519void
520pdc_swap_bytes(char *instring, int inlen, char *outstring)
521{
522    char c;
523    int i,j;
524
525    if (instring == NULL)
526        return;
527
528    if (outstring == NULL)
529        outstring = instring;
530
531    inlen = 2 * inlen / 2;
532    for (i = 0; i < inlen; i++)
533    {
534        j = i;
535        i++;
536        c = instring[j];
537        outstring[j] = instring[i];
538        outstring[i] = c;
539    }
540}
541
542/*
543 * Converts a null terminated and trimed string to a double number
544 */
545pdc_bool
546pdc_str2double(const char *string, double *o_dz)
547{
548    const char *s = string;
549    double dz = 0;
550    int is = 1, isd = 0;
551
552    *o_dz = 0;
553
554    /* sign */
555    if (*s == '-')
556    {
557        is = -1;
558        s++;
559    }
560    else if (*s == '+')
561        s++;
562
563    if (!*s)
564        return pdc_false;
565
566    /* places before decimal point */
567    isd = isdigit(*s);
568    if (isd)
569    {
570        do
571        {
572            dz = 10 * dz + *s - '0';
573            s++;
574        }
575        while (isdigit(*s));
576    }
577
578    /* decimal point */
579    if (*s == '.' || *s == ',')
580    {
581        const char *sa;
582        double adz = 0;
583
584        s++;
585        isd = isdigit(*s);
586        if (!isd)
587            return pdc_false;
588
589        /* places after decimal point */
590        sa = s;
591        do
592        {
593            adz = 10 * adz + *s - '0';
594            s++;
595        }
596        while (isdigit(*s));
597        dz += adz / pow(10.0, (double)(s - sa));
598    }
599
600    /* power sign */
601    if (*s == 'e' || *s == 'E')
602    {
603        s++;
604        if (!isd)
605            return pdc_false;
606
607        /* sign */
608        if (!*s)
609        {
610            dz *= 10;
611        }
612        else
613        {
614            int isp = 1;
615            double pdz = 0, pdl = log10(dz);
616
617            if (*s == '-')
618            {
619                isp = -1;
620                s++;
621            }
622            else if (*s == '+')
623                s++;
624
625            if (!isdigit(*s))
626                return pdc_false;
627            do
628            {
629                pdz = 10 * pdz + *s - '0';
630                s++;
631            }
632            while (isdigit(*s));
633
634
635            if (*s || fabs(pdl + pdz) > 300.0)
636                return pdc_false;
637
638            dz *= pow(10.0, isp * pdz);
639        }
640    }
641    else if(*s)
642    {
643        return pdc_false;
644    }
645
646    *o_dz = is * dz;
647    return pdc_true;
648}
649
650pdc_bool
651pdc_str2integer(const char *string, int *o_iz)
652{
653   double dz;
654
655   if (pdc_str2double(string, &dz) == pdc_true && fabs(dz) <= INT_MAX)
656   {
657       *o_iz = (int) dz;
658       if ((double) *o_iz == dz)
659           return pdc_true;
660   }
661
662   *o_iz = 0;
663   return pdc_false;
664}
665
666/* --------------------------- math  --------------------------- */
667
668float
669pdc_min(float a, float b)
670{
671    return (a < b ? a : b);
672}
673
674float
675pdc_max(float a, float b)
676{
677    return (a > b ? a : b);
678}
679