PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/v3p/dcmtk/ofstd/libsrc/ofstd.cxx

https://bitbucket.org/jtotz/vxl
C++ | 1373 lines | 1130 code | 62 blank | 181 comment | 141 complexity | 2e78f7f0fcb9f855a4d909128a9c5c54 MD5 | raw file
Possible License(s): BSD-2-Clause, LGPL-3.0, CC-BY-SA-3.0
  1. /*
  2. *
  3. * Copyright (C) 1997-2002, OFFIS
  4. *
  5. * This software and supporting documentation were developed by
  6. *
  7. * Kuratorium OFFIS e.V.
  8. * Healthcare Information and Communication Systems
  9. * Escherweg 2
  10. * D-26121 Oldenburg, Germany
  11. *
  12. * THIS SOFTWARE IS MADE AVAILABLE, AS IS, AND OFFIS MAKES NO WARRANTY
  13. * REGARDING THE SOFTWARE, ITS PERFORMANCE, ITS MERCHANTABILITY OR
  14. * FITNESS FOR ANY PARTICULAR USE, FREEDOM FROM ANY COMPUTER DISEASES OR
  15. * ITS CONFORMITY TO ANY SPECIFICATION. THE ENTIRE RISK AS TO QUALITY AND
  16. * PERFORMANCE OF THE SOFTWARE IS WITH THE USER.
  17. *
  18. *
  19. * As an exception of the above notice, the code for OFStandard::strlcpy
  20. * and OFStandard::strlcat in this file have been derived from the BSD
  21. * implementation which carries the following copyright notice:
  22. *
  23. * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
  24. * All rights reserved.
  25. *
  26. * Redistribution and use in source and binary forms, with or without
  27. * modification, are permitted provided that the following conditions
  28. * are met:
  29. * 1. Redistributions of source code must retain the above copyright
  30. * notice, this list of conditions and the following disclaimer.
  31. * 2. Redistributions in binary form must reproduce the above copyright
  32. * notice, this list of conditions and the following disclaimer in the
  33. * documentation and/or other materials provided with the distribution.
  34. * 3. The name of the author may not be used to endorse or promote products
  35. * derived from this software without specific prior written permission.
  36. *
  37. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  38. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  39. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  40. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  41. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  42. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  43. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  44. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  45. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  46. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  47. *
  48. *
  49. * The code for OFStandard::atof has been derived from an implementation
  50. * which carries the following copyright notice:
  51. *
  52. * Copyright 1988 Regents of the University of California
  53. * Permission to use, copy, modify, and distribute this software and
  54. * its documentation for any purpose and without fee is hereby granted,
  55. * provided that the above copyright notice appear in all copies. The
  56. * University of California makes no representations about the
  57. * suitability of this software for any purpose. It is provided "as
  58. * is" without express or implied warranty.
  59. *
  60. *
  61. * The code for OFStandard::ftoa has been derived from an implementation
  62. * which carries the following copyright notice:
  63. *
  64. * Copyright (c) 1988 Regents of the University of California.
  65. * All rights reserved.
  66. *
  67. * Redistribution and use in source and binary forms are permitted
  68. * provided that the above copyright notice and this paragraph are
  69. * duplicated in all such forms and that any documentation,
  70. * advertising materials, and other materials related to such
  71. * distribution and use acknowledge that the software was developed
  72. * by the University of California, Berkeley. The name of the
  73. * University may not be used to endorse or promote products derived
  74. * from this software without specific prior written permission.
  75. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  76. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  77. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  78. *
  79. *
  80. * The "Base64" encoder/decoder has been derived from an implementation
  81. * with the following copyright notice:
  82. *
  83. * Copyright (c) 1999, Bob Withers - bwit@pobox.com
  84. *
  85. * This code may be freely used for any purpose, either personal or
  86. * commercial, provided the authors copyright notice remains intact.
  87. *
  88. *
  89. * Module: ofstd
  90. *
  91. * Author: Joerg Riesmeier, Marco Eichelberg
  92. *
  93. * Purpose: Class for various helper functions
  94. *
  95. */
  96. #include "osconfig.h" /* make sure OS specific configuration is included first */
  97. #include "ofstd.h"
  98. #define INCLUDE_CMATH
  99. #define INCLUDE_CSTRING
  100. #define INCLUDE_CSTDIO
  101. #define INCLUDE_CCTYPE
  102. #include "ofstdinc.h"
  103. BEGIN_EXTERN_C
  104. #ifdef HAVE_SYS_STAT_H
  105. #include <sys/stat.h> /* for stat() */
  106. #endif
  107. #ifdef HAVE_UNISTD_H
  108. #include <unistd.h> /* for access() */
  109. #endif
  110. #ifdef HAVE_IO_H
  111. #include <io.h> /* for access() on Win32 */
  112. #endif
  113. #ifdef HAVE_SYS_TYPES_H
  114. #include <sys/types.h> /* for opendir() and closedir() */
  115. #endif
  116. #ifdef HAVE_DIRENT_H
  117. #include <dirent.h> /* for opendir() and closedir() */
  118. #else
  119. #define dirent direct
  120. #ifdef HAVE_SYS_NDIR_H
  121. #include <sys/ndir.h>
  122. #endif
  123. #ifdef HAVE_SYS_DIR_H
  124. #include <sys/dir.h>
  125. #endif
  126. #ifdef HAVE_NDIR_H
  127. #include <ndir.h>
  128. #endif
  129. #endif
  130. END_EXTERN_C
  131. #ifdef HAVE_WINDOWS_H
  132. #include <windows.h> /* for GetFileAttributes() */
  133. #ifndef R_OK /* windows defines access() but not the constants */
  134. #define W_OK 02 /* Write permission */
  135. #define R_OK 04 /* Read permission */
  136. #define F_OK 00 /* Existance only */
  137. #endif /* R_OK */
  138. #endif /* HAVE_WINDOWS_H */
  139. // --- ftoa() processing flags ---
  140. const unsigned int OFStandard::ftoa_format_e = 0x01;
  141. const unsigned int OFStandard::ftoa_format_f = 0x02;
  142. const unsigned int OFStandard::ftoa_uppercase = 0x04;
  143. const unsigned int OFStandard::ftoa_alternate = 0x08;
  144. const unsigned int OFStandard::ftoa_leftadj = 0x10;
  145. const unsigned int OFStandard::ftoa_zeropad = 0x20;
  146. // --- string functions ---
  147. #ifndef HAVE_STRLCPY
  148. /*
  149. * Copy src to string dst of size siz. At most siz-1 characters
  150. * will be copied. Always NUL terminates (unless siz == 0).
  151. * Returns strlen(src); if retval >= siz, truncation occurred.
  152. */
  153. size_t OFStandard::my_strlcpy(char *dst, const char *src, size_t siz)
  154. {
  155. register char *d = dst;
  156. register const char *s = src;
  157. register size_t n = siz;
  158. /* Copy as many bytes as will fit */
  159. if (n != 0 && --n != 0)
  160. {
  161. do
  162. {
  163. if ((*d++ = *s++) == 0)
  164. break;
  165. } while (--n != 0);
  166. }
  167. /* Not enough room in dst, add NUL and traverse rest of src */
  168. if (n == 0)
  169. {
  170. if (siz != 0)
  171. *d = '\0'; /* NUL-terminate dst */
  172. while (*s++) /* do_nothing */ ;
  173. }
  174. return(s - src - 1); /* count does not include NUL */
  175. }
  176. #endif /* HAVE_STRLCPY */
  177. #ifndef HAVE_STRLCAT
  178. /*
  179. * Appends src to string dst of size siz (unlike strncat, siz is the
  180. * full size of dst, not space left). At most siz-1 characters
  181. * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
  182. * Returns strlen(src) + MIN(siz, strlen(initial dst)).
  183. * If retval >= siz, truncation occurred.
  184. */
  185. size_t OFStandard::my_strlcat(char *dst, const char *src, size_t siz)
  186. {
  187. register char *d = dst;
  188. register const char *s = src;
  189. register size_t n = siz;
  190. size_t dlen;
  191. /* Find the end of dst and adjust bytes left but don't go past end */
  192. while (n-- != 0 && *d != '\0') d++;
  193. dlen = d - dst;
  194. n = siz - dlen;
  195. if (n == 0) return(dlen + strlen(s));
  196. while (*s != '\0')
  197. {
  198. if (n != 1)
  199. {
  200. *d++ = *s;
  201. n--;
  202. }
  203. s++;
  204. }
  205. *d = '\0';
  206. return(dlen + (s - src)); /* count does not include NUL */
  207. }
  208. #endif /* HAVE_STRLCAT */
  209. // --- file system functions ---
  210. OFBool OFStandard::pathExists(const OFString &pathName)
  211. {
  212. OFBool result = OFFalse;
  213. /* check for valid path name */
  214. if (pathName.length() > 0)
  215. {
  216. #if HAVE_ACCESS
  217. /* check whether path exists */
  218. result = (access(pathName.c_str(), F_OK) == 0);
  219. #else
  220. #ifdef HAVE_WINDOWS_H
  221. /* check whether path exists */
  222. result = (GetFileAttributes(pathName.c_str()) != 0xffffffff);
  223. #else
  224. #ifdef HAVE_SYS_STAT_H
  225. /* check existence with "stat()" */
  226. struct stat stat_buf;
  227. result = (stat(pathName.c_str(), &stat_buf) == 0);
  228. #else
  229. /* try to open the given "file" (or directory) in read-only mode */
  230. FILE* filePtr = fopen(pathName.c_str(), "r");
  231. result = (filePtr != NULL);
  232. fclose(filePtr);
  233. #endif /* HAVE_SYS_STAT_H */
  234. #endif /* HAVE_WINDOWS_H */
  235. #endif /* HAVE_ACCESS */
  236. }
  237. return result;
  238. }
  239. OFBool OFStandard::fileExists(const OFString &fileName)
  240. {
  241. OFBool result = OFFalse;
  242. /* check for valid file name */
  243. if (fileName.length() > 0)
  244. {
  245. #ifdef HAVE_WINDOWS_H
  246. /* get file attributes */
  247. DWORD fileAttr = GetFileAttributes(fileName.c_str());
  248. if (fileAttr != 0xffffffff)
  249. {
  250. /* check file type (not a directory?) */
  251. result = ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0);
  252. }
  253. #else
  254. /* check whether path exists (but does not point to a directory) */
  255. result = pathExists(fileName) && !dirExists(fileName);
  256. #endif /* HAVE_WINDOWS_H */
  257. }
  258. return result;
  259. }
  260. OFBool OFStandard::dirExists(const OFString &dirName)
  261. {
  262. OFBool result = OFFalse;
  263. /* check for valid directory name */
  264. if (dirName.length() > 0)
  265. {
  266. #ifdef HAVE_WINDOWS_H
  267. /* get file attributes of the directory */
  268. DWORD fileAttr = GetFileAttributes(dirName.c_str());
  269. if (fileAttr != 0xffffffff)
  270. {
  271. /* check file type (is a directory?) */
  272. result = ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) != 0);
  273. }
  274. #else
  275. /* try to open the given directory */
  276. DIR *dirPtr = opendir(dirName.c_str());
  277. if (dirPtr != NULL)
  278. {
  279. result = OFTrue;
  280. closedir(dirPtr);
  281. }
  282. #endif /* HAVE_WINDOWS_H */
  283. }
  284. return result;
  285. }
  286. OFBool OFStandard::isReadable(const OFString &pathName)
  287. {
  288. #if HAVE_ACCESS
  289. return (access(pathName.c_str(), R_OK) == 0);
  290. #else
  291. OFBool result = OFFalse;
  292. /* try to open the given "file" (or directory) in read-only mode */
  293. FILE* filePtr = fopen(pathName.c_str(), "r");
  294. result = (filePtr != NULL);
  295. fclose(filePtr);
  296. return result;
  297. #endif /* HAVE_ACCESS */
  298. }
  299. OFBool OFStandard::isWriteable(const OFString &pathName)
  300. {
  301. #if HAVE_ACCESS
  302. return (access(pathName.c_str(), W_OK) == 0);
  303. #else
  304. OFBool result = OFFalse;
  305. /* try to open the given "file" (or directory) in write mode */
  306. FILE* filePtr = fopen(pathName.c_str(), "w");
  307. result = (filePtr != NULL);
  308. fclose(filePtr);
  309. return result;
  310. #endif /* HAVE_ACCESS */
  311. }
  312. OFString &OFStandard::normalizeDirName(OFString &result,
  313. const OFString &dirName,
  314. const OFBool allowEmptyDirName)
  315. {
  316. result = dirName;
  317. /* remove trailing path separators (keep it if at the beginning of the string) */
  318. while ((result.length() > 1) && (result[result.length() - 1] == PATH_SEPARATOR))
  319. result.erase(result.length() - 1, 1);
  320. /* avoid empty directory name (use "." instead) */
  321. if ((result.length() == 0) && !allowEmptyDirName)
  322. result = ".";
  323. return result;
  324. }
  325. OFString &OFStandard::combineDirAndFilename(OFString &result,
  326. const OFString &dirName,
  327. const OFString &fileName,
  328. const OFBool allowEmptyDirName)
  329. {
  330. /* normalize the directory name */
  331. normalizeDirName(result, dirName, allowEmptyDirName);
  332. /* check file name */
  333. if (fileName.length() > 0)
  334. {
  335. /* add path separator (if required) ... */
  336. if ((result.length() > 0) && (result[result.length() - 1] != PATH_SEPARATOR))
  337. result += PATH_SEPARATOR;
  338. /* ...and file name */
  339. result += fileName;
  340. }
  341. return result;
  342. }
  343. const OFString &OFStandard::convertToMarkupString(const OFString &sourceString,
  344. OFString &markupString,
  345. const OFBool convertNonASCII,
  346. const OFBool xmlMode,
  347. const OFBool newlineAllowed)
  348. {
  349. /* char ptr allows fastest access to the string */
  350. const char *str = sourceString.c_str();
  351. /* start with empty string */
  352. markupString.clear();
  353. /* avoid to resize the string too often */
  354. markupString.resize(strlen(str));
  355. while (*str != 0)
  356. {
  357. /* less than */
  358. if (*str == '<')
  359. markupString += "&lt;";
  360. /* greater than */
  361. else if (*str == '>')
  362. markupString += "&gt;";
  363. /* ampers and */
  364. else if (*str == '&')
  365. markupString += "&amp;";
  366. /* quotation mark */
  367. else if (*str == '"')
  368. markupString += "&quot;";
  369. /* newline: LF, CR, LF CR, CR LF */
  370. else if ((*str == '\012') || (*str == '\015'))
  371. {
  372. /* skip next character if it belongs to the newline sequence */
  373. if (((*str == '\012') && (*(str + 1) == '\015')) || ((*str == '\015') && (*(str + 1) == '\012')))
  374. str++;
  375. if (xmlMode)
  376. {
  377. /* "<br>" and "&para;" not defined in XML - requires DTD definition */
  378. markupString += "&#182;";
  379. } else {
  380. if (newlineAllowed)
  381. markupString += "<br>\n";
  382. else
  383. markupString += "&para;";
  384. }
  385. }
  386. else {
  387. /* other character: ... */
  388. const size_t charValue = (size_t)(*(const unsigned char *)str);
  389. if (convertNonASCII && (charValue > 127))
  390. {
  391. char buffer[16];
  392. sprintf(buffer, "%lu", (unsigned long)charValue);
  393. /* convert > #127 to Unicode (ISO Latin-1), what is about < #32 ? */
  394. markupString += "&#";
  395. markupString += buffer;
  396. markupString += ";";
  397. } else {
  398. /* just append */
  399. markupString += *str;
  400. }
  401. }
  402. str++;
  403. }
  404. return markupString;
  405. }
  406. // Base64 translation table as described in RFC 2045 (MIME)
  407. static const char enc_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  408. const OFString &OFStandard::encodeBase64(const unsigned char *data,
  409. const size_t length,
  410. OFString &result,
  411. const size_t width)
  412. {
  413. result.clear();
  414. /* check data buffer to be encoded */
  415. if (data != NULL)
  416. {
  417. unsigned char c;
  418. size_t j = 0;
  419. size_t w = 0;
  420. /* reserve expected output size: +33%, even multiple of 4 */
  421. result.reserve(((length + 2) / 3) * 4);
  422. /* iterate over all data elements */
  423. for (size_t i = 0; i < length; i++)
  424. {
  425. /* encode first 6 bits */
  426. result[j++] = enc_base64[(data[i] >> 2) & 0x3f];
  427. /* insert line break (if width > 0) */
  428. if (++w == width)
  429. {
  430. result[j++] = '\n';
  431. w = 0;
  432. }
  433. /* encode remaining 2 bits of the first byte and 4 bits of the second byte */
  434. c = (data[i] << 4) & 0x3f;
  435. if (++i < length)
  436. c |= (data[i] >> 4) & 0x0f;
  437. result[j++] = enc_base64[c];
  438. /* insert line break (if width > 0) */
  439. if (++w == width)
  440. {
  441. result[j++] = '\n';
  442. w = 0;
  443. }
  444. /* encode remaining 4 bits of the second byte and 2 bits of the third byte */
  445. if (i < length)
  446. {
  447. c = (data[i] << 2) & 0x3f;
  448. if (++i < length)
  449. c |= (data[i] >> 6) & 0x03;
  450. result[j++] = enc_base64[c];
  451. } else {
  452. i++;
  453. /* append fill char */
  454. result[j++] = '=';
  455. }
  456. /* insert line break (if width > 0) */
  457. if (++w == width)
  458. {
  459. result[j++] = '\n';
  460. w = 0;
  461. }
  462. /* encode remaining 6 bits of the third byte */
  463. if (i < length)
  464. result[j++] = enc_base64[data[i] & 0x3f];
  465. else /* append fill char */
  466. result[j++] = '=';
  467. /* insert line break (if width > 0) */
  468. if (++w == width)
  469. {
  470. result[j++] = '\n';
  471. w = 0;
  472. }
  473. }
  474. /* append trailing 0 byte */
  475. result[j] = '\0';
  476. }
  477. return result;
  478. }
  479. // Base64 decoding table: maps #43..#122 to #0..#63 (255 means invalid)
  480. static const unsigned char dec_base64[] =
  481. { 62, 255, 255, 255, 63, // '+' .. '/'
  482. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0' .. '9'
  483. 255, 255, 255, 255, 255, 255, 255, // ':' .. '@'
  484. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A' .. 'Z'
  485. 255, 255, 255, 255, 255, 255, // '[' .. '`'
  486. 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 // 'a' .. 'z'
  487. };
  488. size_t OFStandard::decodeBase64(const OFString &data,
  489. unsigned char *&result)
  490. {
  491. size_t count = 0;
  492. /* search for fill char to determine the real length of the input string */
  493. const size_t fillPos = data.find('=');
  494. const size_t length = (fillPos != OFString_npos) ? fillPos : data.length();
  495. /* check data buffer to be decoded */
  496. if (length > 0)
  497. {
  498. /* allocate sufficient memory for the decoded data */
  499. result = new unsigned char[((length + 3) / 4) * 3];
  500. if (result != NULL)
  501. {
  502. unsigned char c1 = 0;
  503. unsigned char c2 = 0;
  504. /* iterate over all data elements */
  505. for (size_t i = 0; i < length; i++)
  506. {
  507. /* skip invalid characters and assign first decoded char */
  508. while ((i < length) && ((data[i] < '+') || (data[i] > 'z') || ((c1 = dec_base64[data[i] - '+']) > 63)))
  509. i++;
  510. if (++i < length)
  511. {
  512. /* skip invalid characters and assign second decoded char */
  513. while ((i < length) && ((data[i] < '+') || (data[i] > 'z') || ((c2 = dec_base64[data[i] - '+']) > 63)))
  514. i++;
  515. if (i < length)
  516. {
  517. /* decode first byte */
  518. result[count++] = (c1 << 2) | ((c2 >> 4) & 0x3);
  519. if (++i < length)
  520. {
  521. /* skip invalid characters and assign third decoded char */
  522. while ((i < length) && ((data[i] < '+') || (data[i] > 'z') || ((c1 = dec_base64[data[i] - '+']) > 63)))
  523. i++;
  524. if (i < length)
  525. {
  526. /* decode second byte */
  527. result[count++] = ((c2 << 4) & 0xf0) | ((c1 >> 2) & 0xf);
  528. if (++i < length)
  529. {
  530. /* skip invalid characters and assign fourth decoded char */
  531. while ((i < length) && ((data[i] < '+') || (data[i] > 'z') || ((c2 = dec_base64[data[i] - '+']) > 63)))
  532. i++;
  533. /* decode third byte */
  534. if (i < length)
  535. result[count++] = ((c1 << 6) & 0xc0) | c2;
  536. }
  537. }
  538. }
  539. }
  540. }
  541. }
  542. /* delete buffer if no data has been written to the output */
  543. if (count == 0)
  544. delete[] result;
  545. }
  546. } else
  547. result = NULL;
  548. return count;
  549. }
  550. #ifdef DISABLE_OFSTD_ATOF
  551. // we use sscanf instead of atof because atof doesn't return a status flag
  552. double OFStandard::atof(const char *s, OFBool *success)
  553. {
  554. double result;
  555. if (success)
  556. {
  557. *success = (1 == sscanf(s,"%lf",&result));
  558. }
  559. else
  560. {
  561. (void) sscanf(s,"%lf",&result);
  562. }
  563. return result;
  564. }
  565. #else
  566. // --- definitions and constants for atof() ---
  567. /* Largest possible base 10 exponent. Any exponent larger than this will
  568. * already produce underflow or overflow, so there's no need to worry
  569. * about additional digits.
  570. */
  571. #define ATOF_MAXEXPONENT 511
  572. /* Table giving binary powers of 10. Entry is 10^2^i.
  573. * Used to convert decimal exponents into floating-point numbers.
  574. */
  575. static const double atof_powersOf10[] =
  576. {
  577. 10.,
  578. 100.,
  579. 1.0e4,
  580. 1.0e8,
  581. 1.0e16,
  582. 1.0e32,
  583. 1.0e64,
  584. 1.0e128,
  585. 1.0e256
  586. };
  587. double OFStandard::atof(const char *s, OFBool *success)
  588. {
  589. if (success) *success = OFFalse;
  590. register const char *p = s;
  591. register char c;
  592. int sign = 0;
  593. int expSign = 0;
  594. double fraction;
  595. int exponent = 0; // Exponent read from "EX" field.
  596. const char *pExp; // Temporarily holds location of exponent in string.
  597. /* Exponent that derives from the fractional part. Under normal
  598. * circumstatnces, it is the negative of the number of digits in F.
  599. * However, if I is very long, the last digits of I get dropped
  600. * (otherwise a long I with a large negative exponent could cause an
  601. * unnecessary overflow on I alone). In this case, fracExp is
  602. * incremented one for each dropped digit.
  603. */
  604. int fracExp = 0;
  605. // Strip off leading blanks and check for a sign.
  606. while (isspace((int)(*p))) ++p;
  607. if (*p == '-')
  608. {
  609. sign = 1;
  610. ++p;
  611. }
  612. else
  613. {
  614. if (*p == '+') ++p;
  615. }
  616. // Count the number of digits in the mantissa (including the decimal
  617. // point), and also locate the decimal point.
  618. int decPt = -1; // Number of mantissa digits BEFORE decimal point.
  619. int mantSize; // Number of digits in mantissa.
  620. for (mantSize = 0; ; ++mantSize)
  621. {
  622. c = *p;
  623. if (!isdigit((int)c))
  624. {
  625. if ((c != '.') || (decPt >= 0)) break;
  626. decPt = mantSize;
  627. }
  628. ++p;
  629. }
  630. /*
  631. * Now suck up the digits in the mantissa. Use two integers to
  632. * collect 9 digits each (this is faster than using floating-point).
  633. * If the mantissa has more than 18 digits, ignore the extras, since
  634. * they can't affect the value anyway.
  635. */
  636. pExp = p;
  637. p -= mantSize;
  638. if (decPt < 0)
  639. decPt = mantSize;
  640. else mantSize -= 1; // One of the digits was the point
  641. if (mantSize > 18)
  642. {
  643. fracExp = decPt - 18;
  644. mantSize = 18;
  645. }
  646. else
  647. {
  648. fracExp = decPt - mantSize;
  649. }
  650. if (mantSize == 0)
  651. {
  652. // subject sequence does not have expected form.
  653. // return 0 and leave success flag set to false
  654. return 0.0;
  655. }
  656. else
  657. {
  658. int frac1 = 0;
  659. for ( ; mantSize > 9; mantSize -= 1)
  660. {
  661. c = *p;
  662. ++p;
  663. if (c == '.')
  664. {
  665. c = *p;
  666. ++p;
  667. }
  668. frac1 = 10*frac1 + (c - '0');
  669. }
  670. int frac2 = 0;
  671. for (; mantSize > 0; mantSize -= 1)
  672. {
  673. c = *p;
  674. ++p;
  675. if (c == '.')
  676. {
  677. c = *p;
  678. ++p;
  679. }
  680. frac2 = 10*frac2 + (c - '0');
  681. }
  682. fraction = (1.0e9 * frac1) + frac2;
  683. }
  684. // Skim off the exponent.
  685. p = pExp;
  686. if ((*p == 'E') || (*p == 'e'))
  687. {
  688. ++p;
  689. if (*p == '-')
  690. {
  691. expSign = 1;
  692. ++p;
  693. }
  694. else
  695. {
  696. if (*p == '+') ++p;
  697. expSign = 0;
  698. }
  699. while (isdigit((int)(*p)))
  700. {
  701. exponent = exponent * 10 + (*p - '0');
  702. ++p;
  703. }
  704. }
  705. if (expSign)
  706. exponent = fracExp - exponent;
  707. else exponent = fracExp + exponent;
  708. /*
  709. * Generate a floating-point number that represents the exponent.
  710. * Do this by processing the exponent one bit at a time to combine
  711. * many powers of 2 of 10. Then combine the exponent with the
  712. * fraction.
  713. */
  714. if (exponent < 0)
  715. {
  716. expSign = 1;
  717. exponent = -exponent;
  718. }
  719. else expSign = 0;
  720. if (exponent > ATOF_MAXEXPONENT) exponent = ATOF_MAXEXPONENT;
  721. double dblExp = 1.0;
  722. for (const double *d = atof_powersOf10; exponent != 0; exponent >>= 1, ++d)
  723. {
  724. if (exponent & 01) dblExp *= *d;
  725. }
  726. if (expSign)
  727. fraction /= dblExp;
  728. else fraction *= dblExp;
  729. if (success) *success = OFTrue;
  730. if (sign) return -fraction;
  731. return fraction;
  732. }
  733. #endif /* DISABLE_OFSTD_ATOF */
  734. /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
  735. #define FTOA_MAXEXP 308
  736. /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
  737. #define FTOA_MAXFRACT 39
  738. /* default precision */
  739. #define FTOA_DEFPREC 6
  740. /* internal buffer size for ftoa code */
  741. #define FTOA_BUFSIZE (FTOA_MAXEXP+FTOA_MAXFRACT+1)
  742. #define FTOA_TODIGIT(c) ((c) - '0')
  743. #define FTOA_TOCHAR(n) ((n) + '0')
  744. #define FTOA_FORMAT_MASK 0x03 /* and mask for format flags */
  745. #define FTOA_FORMAT_E OFStandard::ftoa_format_e
  746. #define FTOA_FORMAT_F OFStandard::ftoa_format_f
  747. #define FTOA_FORMAT_UPPERCASE OFStandard::ftoa_uppercase
  748. #define FTOA_ALTERNATE_FORM OFStandard::ftoa_alternate
  749. #define FTOA_LEFT_ADJUSTMENT OFStandard::ftoa_leftadj
  750. #define FTOA_ZEROPAD OFStandard::ftoa_zeropad
  751. #ifdef DISABLE_OFSTD_FTOA
  752. void OFStandard::ftoa(
  753. char *dst,
  754. size_t siz,
  755. double val,
  756. unsigned int flags,
  757. int width,
  758. int prec)
  759. {
  760. // this version of the function uses sprintf to format the output string.
  761. // Since we have to assemble the sprintf format string, this version might
  762. // even be slower than the alternative implementation.
  763. char buf[FTOA_BUFSIZE];
  764. OFString s("%"); // this will become the format string
  765. unsigned char fmtch = 'G';
  766. // determine format character
  767. if (flags & FTOA_FORMAT_UPPERCASE)
  768. {
  769. if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_E) fmtch = 'E';
  770. else if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_F) fmtch = 'f'; // there is no uppercase for 'f'
  771. else fmtch = 'G';
  772. }
  773. else
  774. {
  775. if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_E) fmtch = 'e';
  776. else if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_F) fmtch = 'f';
  777. else fmtch = 'g';
  778. }
  779. if (flags & FTOA_ALTERNATE_FORM) s += "#";
  780. if (flags & FTOA_LEFT_ADJUSTMENT) s += "-";
  781. if (flags & FTOA_ZEROPAD) s += "0";
  782. if (width > 0)
  783. {
  784. sprintf(buf, "%d", width);
  785. s += buf;
  786. }
  787. if (prec >= 0)
  788. {
  789. sprintf(buf, ".%d", prec);
  790. s += buf;
  791. }
  792. s += fmtch;
  793. sprintf(buf, s.c_str(), val);
  794. OFStandard::strlcpy(dst, buf, siz);
  795. }
  796. #else
  797. /** internal helper class that maintains a string buffer
  798. * to which characters can be written. If the string buffer
  799. * gets full, additional characters are discarded.
  800. * The string buffer does not guarantee zero termination.
  801. */
  802. class FTOAStringBuffer
  803. {
  804. public:
  805. /** constructor
  806. * @param theSize desired size of string buffer, in bytes
  807. */
  808. FTOAStringBuffer(unsigned long theSize)
  809. : buf_(NULL)
  810. , offset_(0)
  811. , size_(theSize)
  812. {
  813. if (size_ > 0) buf_ = new char[size_];
  814. }
  815. /// destructor
  816. ~FTOAStringBuffer()
  817. {
  818. delete[] buf_;
  819. }
  820. /** add one character to string buffer. Never overwrites
  821. * buffer boundary.
  822. * @param c character to add
  823. */
  824. inline void put(unsigned char c)
  825. {
  826. if (buf_ && (offset_ < size_)) buf_[offset_++] = c;
  827. }
  828. // return pointer to string buffer
  829. const char *getBuffer() const
  830. {
  831. return buf_;
  832. }
  833. private:
  834. /// pointer to string buffer
  835. char *buf_;
  836. /// current offset within buffer
  837. unsigned long offset_;
  838. /// size of buffer
  839. unsigned long size_;
  840. /// private undefined copy constructor
  841. FTOAStringBuffer(const FTOAStringBuffer &old);
  842. /// private undefined assignment operator
  843. FTOAStringBuffer &operator=(const FTOAStringBuffer &obj);
  844. };
  845. /** writes the given format character and exponent to output string p.
  846. * @param p pointer to target string
  847. * @param exponent exponent to print
  848. * @param fmtch format character
  849. * @return pointer to next unused character in output string
  850. */
  851. static char *ftoa_exponent(char *p, int exponent, char fmtch)
  852. {
  853. char expbuf[FTOA_MAXEXP];
  854. *p++ = fmtch;
  855. if (exponent < 0)
  856. {
  857. exponent = -exponent;
  858. *p++ = '-';
  859. }
  860. else *p++ = '+';
  861. register char *t = expbuf + FTOA_MAXEXP;
  862. if (exponent > 9)
  863. {
  864. do
  865. {
  866. *--t = FTOA_TOCHAR(exponent % 10);
  867. }
  868. while ((exponent /= 10) > 9);
  869. *--t = FTOA_TOCHAR(exponent);
  870. for (; t < expbuf + FTOA_MAXEXP; *p++ = *t++) /* nothing */;
  871. }
  872. else
  873. {
  874. *p++ = '0';
  875. *p++ = FTOA_TOCHAR(exponent);
  876. }
  877. return p;
  878. }
  879. /** round given fraction and adjust text string if round up.
  880. * @param fract fraction to round
  881. * @param expon pointer to exponent, may be NULL
  882. * @param start pointer to start of string to round
  883. * @param end pointer to one char after end of string
  884. * @param ch if fract is zero, this character is interpreted as fraction*10 instead
  885. * @param signp pointer to sign character, '-' or 0.
  886. * @return adjusted pointer to start of rounded string, may be start or start-1.
  887. */
  888. static char *ftoa_round(double fract, int *expon, char *start, char *end, char ch, char *signp)
  889. {
  890. double tmp;
  891. if (fract) (void) modf(fract * 10, &tmp);
  892. else tmp = FTOA_TODIGIT(ch);
  893. if (tmp > 4)
  894. {
  895. for (;; --end)
  896. {
  897. if (*end == '.') --end;
  898. if (++*end <= '9') break;
  899. *end = '0';
  900. if (end == start)
  901. {
  902. if (expon) /* e/E; increment exponent */
  903. {
  904. *end = '1';
  905. ++*expon;
  906. }
  907. else /* f; add extra digit */
  908. {
  909. *--end = '1';
  910. --start;
  911. }
  912. break;
  913. }
  914. }
  915. }
  916. /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
  917. else if (*signp == '-')
  918. {
  919. for (;; --end)
  920. {
  921. if (*end == '.') --end;
  922. if (*end != '0') break;
  923. if (end == start) *signp = 0; // suppress negative 0
  924. }
  925. }
  926. return start;
  927. }
  928. /** convert double value to string, without padding
  929. * @param val double value to be formatted
  930. * @param prec precision, adjusted for FTOA_MAXFRACT
  931. * @param flags formatting flags
  932. * @param signp pointer to sign character, '-' or 0.
  933. * @param fmtch format character
  934. * @param startp pointer to start of target buffer
  935. * @param endp pointer to one char after end of target buffer
  936. * @return
  937. */
  938. static int ftoa_convert(double val, int prec, int flags, char *signp, char fmtch, char *startp, char *endp)
  939. {
  940. register char *p;
  941. register double fract;
  942. int dotrim = 0;
  943. int expcnt = 0;
  944. int gformat = 0;
  945. double integer, tmp;
  946. fract = modf(val, &integer);
  947. /* get an extra slot for rounding. */
  948. register char *t = ++startp;
  949. /*
  950. * get integer portion of val; put into the end of the buffer; the
  951. * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
  952. */
  953. for (p = endp - 1; integer; ++expcnt)
  954. {
  955. tmp = modf(integer / 10, &integer);
  956. *p-- = FTOA_TOCHAR((int)((tmp + .01) * 10));
  957. }
  958. switch (fmtch)
  959. {
  960. case 'f':
  961. /* reverse integer into beginning of buffer */
  962. if (expcnt)
  963. {
  964. for (; ++p < endp; *t++ = *p);
  965. }
  966. else *t++ = '0';
  967. /*
  968. * if precision required or alternate flag set, add in a
  969. * decimal point.
  970. */
  971. if (prec || flags & FTOA_ALTERNATE_FORM) *t++ = '.';
  972. /* if requires more precision and some fraction left */
  973. if (fract)
  974. {
  975. if (prec) do
  976. {
  977. fract = modf(fract * 10, &tmp);
  978. *t++ = FTOA_TOCHAR((int)tmp);
  979. } while (--prec && fract);
  980. if (fract)
  981. {
  982. startp = ftoa_round(fract, (int *)NULL, startp, t - 1, (char)0, signp);
  983. }
  984. }
  985. for (; prec--; *t++ = '0');
  986. break;
  987. case 'e':
  988. case 'E':
  989. eformat:
  990. if (expcnt)
  991. {
  992. *t++ = *++p;
  993. if (prec || flags&FTOA_ALTERNATE_FORM)
  994. *t++ = '.';
  995. /* if requires more precision and some integer left */
  996. for (; prec && ++p < endp; --prec)
  997. *t++ = *p;
  998. /*
  999. * if done precision and more of the integer component,
  1000. * round using it; adjust fract so we don't re-round
  1001. * later.
  1002. */
  1003. if (!prec && ++p < endp)
  1004. {
  1005. fract = 0;
  1006. startp = ftoa_round((double)0, &expcnt, startp, t - 1, *p, signp);
  1007. }
  1008. /* adjust expcnt for digit in front of decimal */
  1009. --expcnt;
  1010. }
  1011. /* until first fractional digit, decrement exponent */
  1012. else if (fract)
  1013. {
  1014. /* adjust expcnt for digit in front of decimal */
  1015. for (expcnt = -1;; --expcnt) {
  1016. fract = modf(fract * 10, &tmp);
  1017. if (tmp)
  1018. break;
  1019. }
  1020. *t++ = FTOA_TOCHAR((int)tmp);
  1021. if (prec || flags&FTOA_ALTERNATE_FORM) *t++ = '.';
  1022. }
  1023. else
  1024. {
  1025. *t++ = '0';
  1026. if (prec || flags&FTOA_ALTERNATE_FORM) *t++ = '.';
  1027. }
  1028. /* if requires more precision and some fraction left */
  1029. if (fract)
  1030. {
  1031. if (prec) do
  1032. {
  1033. fract = modf(fract * 10, &tmp);
  1034. *t++ = FTOA_TOCHAR((int)tmp);
  1035. } while (--prec && fract);
  1036. if (fract)
  1037. {
  1038. startp = ftoa_round(fract, &expcnt, startp, t - 1, (char)0, signp);
  1039. }
  1040. }
  1041. /* if requires more precision */
  1042. for (; prec--; *t++ = '0');
  1043. /* unless alternate flag, trim any g/G format trailing 0's */
  1044. if (gformat && !(flags&FTOA_ALTERNATE_FORM))
  1045. {
  1046. while (t > startp && *--t == '0') /* nothing */;
  1047. if (*t == '.') --t;
  1048. ++t;
  1049. }
  1050. t = ftoa_exponent(t, expcnt, fmtch);
  1051. break;
  1052. case 'g':
  1053. case 'G':
  1054. /* a precision of 0 is treated as a precision of 1. */
  1055. if (!prec) ++prec;
  1056. /*
  1057. * ``The style used depends on the value converted; style e
  1058. * will be used only if the exponent resulting from the
  1059. * conversion is less than -4 or greater than the precision.''
  1060. * -- ANSI X3J11
  1061. */
  1062. if (expcnt > prec || (!expcnt && fract && fract < .0001))
  1063. {
  1064. /*
  1065. * g/G format counts "significant digits, not digits of
  1066. * precision; for the e/E format, this just causes an
  1067. * off-by-one problem, i.e. g/G considers the digit
  1068. * before the decimal point significant and e/E doesn't
  1069. * count it as precision.
  1070. */
  1071. --prec;
  1072. fmtch -= 2; /* G->E, g->e */
  1073. gformat = 1;
  1074. goto eformat;
  1075. }
  1076. /*
  1077. * reverse integer into beginning of buffer,
  1078. * note, decrement precision
  1079. */
  1080. if (expcnt)
  1081. {
  1082. for (; ++p < endp; *t++ = *p, --prec);
  1083. }
  1084. else *t++ = '0';
  1085. /*
  1086. * if precision required or alternate flag set, add in a
  1087. * decimal point. If no digits yet, add in leading 0.
  1088. */
  1089. if (prec || flags&FTOA_ALTERNATE_FORM)
  1090. {
  1091. dotrim = 1;
  1092. *t++ = '.';
  1093. }
  1094. else dotrim = 0;
  1095. /* if requires more precision and some fraction left */
  1096. if (fract)
  1097. {
  1098. if (prec)
  1099. {
  1100. do
  1101. {
  1102. fract = modf(fract * 10, &tmp);
  1103. *t++ = FTOA_TOCHAR((int)tmp);
  1104. } while (!tmp);
  1105. while (--prec && fract)
  1106. {
  1107. fract = modf(fract * 10, &tmp);
  1108. *t++ = FTOA_TOCHAR((int)tmp);
  1109. }
  1110. }
  1111. if (fract)
  1112. {
  1113. startp = ftoa_round(fract, (int *)NULL, startp, t - 1, (char)0, signp);
  1114. }
  1115. }
  1116. /* alternate format, adds 0's for precision, else trim 0's */
  1117. if (flags&FTOA_ALTERNATE_FORM) for (; prec--; *t++ = '0') /* nothing */;
  1118. else if (dotrim)
  1119. {
  1120. while (t > startp && *--t == '0') /* nothing */;
  1121. if (*t != '.') ++t;
  1122. }
  1123. } /* end switch */
  1124. return (t - startp);
  1125. }
  1126. void OFStandard::ftoa(
  1127. char *dst,
  1128. size_t siz,
  1129. double val,
  1130. unsigned int flags,
  1131. int width,
  1132. int prec)
  1133. {
  1134. // if target string is NULL or zero bytes long, bail out.
  1135. if (!dst || !siz) return;
  1136. int fpprec = 0; /* `extra' floating precision in [eEfgG] */
  1137. char softsign = 0; /* temporary negative sign for floats */
  1138. char buf[FTOA_BUFSIZE]; /* space for %c, %[diouxX], %[eEfgG] */
  1139. char sign = '\0'; /* sign prefix (' ', '+', '-', or \0) */
  1140. register int n;
  1141. unsigned char fmtch = 'G';
  1142. FTOAStringBuffer sb(FTOA_BUFSIZE+1);
  1143. // determine format character
  1144. if (flags & FTOA_FORMAT_UPPERCASE)
  1145. {
  1146. if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_E) fmtch = 'E';
  1147. else if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_F) fmtch = 'f'; // there is no uppercase for 'f'
  1148. else fmtch = 'G';
  1149. }
  1150. else
  1151. {
  1152. if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_E) fmtch = 'e';
  1153. else if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_F) fmtch = 'f';
  1154. else fmtch = 'g';
  1155. }
  1156. // don't do unrealistic precision; just pad it with zeroes later,
  1157. // so buffer size stays rational.
  1158. if (prec > FTOA_MAXFRACT)
  1159. {
  1160. if ((fmtch != 'g' && fmtch != 'G') || (flags&FTOA_ALTERNATE_FORM)) fpprec = prec - FTOA_MAXFRACT;
  1161. prec = FTOA_MAXFRACT;
  1162. }
  1163. else if (prec == -1) prec = FTOA_DEFPREC;
  1164. /*
  1165. * softsign avoids negative 0 if val is < 0 and
  1166. * no significant digits will be shown
  1167. */
  1168. if (val < 0)
  1169. {
  1170. softsign = '-';
  1171. val = -val;
  1172. }
  1173. else softsign = 0;
  1174. /*
  1175. * ftoa_convert may have to round up past the "start" of the
  1176. * buffer, i.e. ``intf("%.2f", (double)9.999);'';
  1177. * if the first char isn't \0, it did.
  1178. */
  1179. *buf = 0;
  1180. int size = ftoa_convert(val, prec, flags, &softsign, fmtch, buf, buf + sizeof(buf));
  1181. if (softsign) sign = '-';
  1182. register char *t = *buf ? buf : buf + 1;
  1183. /* At this point, `t' points to a string which (if not flags&FTOA_LEFT_ADJUSTMENT)
  1184. * should be padded out to `width' places. If flags&FTOA_ZEROPAD, it should
  1185. * first be prefixed by any sign or other prefix; otherwise, it should be
  1186. * blank padded before the prefix is emitted. After any left-hand
  1187. * padding, print the string proper, then emit zeroes required by any
  1188. * leftover floating precision; finally, if FTOA_LEFT_ADJUSTMENT, pad with blanks.
  1189. *
  1190. * compute actual size, so we know how much to pad
  1191. */
  1192. int fieldsz = size + fpprec;
  1193. if (sign) fieldsz++;
  1194. /* right-adjusting blank padding */
  1195. if ((flags & (FTOA_LEFT_ADJUSTMENT|FTOA_ZEROPAD)) == 0 && width)
  1196. {
  1197. for (n = fieldsz; n < width; n++) sb.put(' ');
  1198. }
  1199. /* prefix */
  1200. if (sign) sb.put(sign);
  1201. /* right-adjusting zero padding */
  1202. if ((flags & (FTOA_LEFT_ADJUSTMENT|FTOA_ZEROPAD)) == FTOA_ZEROPAD)
  1203. for (n = fieldsz; n < width; n++)
  1204. sb.put('0');
  1205. /* the string or number proper */
  1206. n = size;
  1207. while (--n >= 0) sb.put(*t++);
  1208. /* trailing f.p. zeroes */
  1209. while (--fpprec >= 0) sb.put('0');
  1210. /* left-adjusting padding (always blank) */
  1211. if (flags & FTOA_LEFT_ADJUSTMENT)
  1212. for (n = fieldsz; n < width; n++)
  1213. sb.put(' ');
  1214. /* zero-terminate string */
  1215. sb.put(0);
  1216. /* copy result from char buffer to output array */
  1217. const char *c = sb.getBuffer();
  1218. if (c) OFStandard::strlcpy(dst, c, siz); else *dst = 0;
  1219. }
  1220. #endif /* DISABLE_OFSTD_FTOA */
  1221. OFBool OFStandard::stringMatchesCharacterSet( const char *str, const char *charset )
  1222. {
  1223. if ( charset == NULL || str == NULL )
  1224. return OFTrue;
  1225. OFBool result = OFTrue;
  1226. unsigned int lenStr = strlen( str );
  1227. unsigned int lenCharset = strlen( charset );
  1228. for ( unsigned int i=0 ; i<lenStr && result ; i++ )
  1229. {
  1230. OFBool charFound = OFFalse;
  1231. for ( unsigned int j=0 ; j<lenCharset && !charFound ; j++ )
  1232. {
  1233. if ( str[i] == charset[j] )
  1234. charFound = OFTrue;
  1235. }
  1236. if ( !charFound )
  1237. result = OFFalse;
  1238. }
  1239. return( result );
  1240. }