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(<ime); 55 ltime = *localtime(&timer); 56 ltime.tm_isdst = 0; 57 diffminutes = difftime(mktime(<ime), 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