PageRenderTime 52ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/ofstd/libsrc/ofstd.cc

https://github.com/hmeyer/dcmtk
C++ | 1748 lines | 1323 code | 81 blank | 344 comment | 191 complexity | 8bfa3c77c8c01f353a3b79d4d1206797 MD5 | raw file
Possible License(s): CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. *
  3. * Copyright (C) 2001-2005, 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. * Last Update: $Author: meichel $
  96. * Update Date: $Date: 2005/12/08 15:49:00 $
  97. * CVS/RCS Revision: $Revision: 1.34 $
  98. * Status: $State: Exp $
  99. *
  100. * CVS/RCS Log at end of file
  101. *
  102. */
  103. #include "dcmtk/config/osconfig.h" /* make sure OS specific configuration is included first */
  104. #include "dcmtk/ofstd/ofstd.h"
  105. #define INCLUDE_CMATH
  106. #define INCLUDE_CFLOAT
  107. #define INCLUDE_CSTRING
  108. #define INCLUDE_CSTDIO
  109. #define INCLUDE_CCTYPE
  110. #define INCLUDE_UNISTD
  111. #include "dcmtk/ofstd/ofstdinc.h"
  112. BEGIN_EXTERN_C
  113. #ifdef HAVE_SYS_STAT_H
  114. #include <sys/stat.h> /* for stat() */
  115. #endif
  116. #ifdef HAVE_IO_H
  117. #include <io.h> /* for access() on Win32 */
  118. #endif
  119. #ifdef HAVE_SYS_TYPES_H
  120. #include <sys/types.h> /* for opendir() and closedir() */
  121. #endif
  122. #ifdef HAVE_DIRENT_H
  123. #include <dirent.h> /* for opendir() and closedir() */
  124. #else
  125. #define dirent direct
  126. #ifdef HAVE_SYS_NDIR_H
  127. #include <sys/ndir.h>
  128. #endif
  129. #ifdef HAVE_SYS_DIR_H
  130. #include <sys/dir.h>
  131. #endif
  132. #ifdef HAVE_NDIR_H
  133. #include <ndir.h>
  134. #endif
  135. #endif
  136. #ifdef HAVE_FNMATCH_H
  137. #include <fnmatch.h> /* for fnmatch() */
  138. #endif
  139. #ifdef HAVE_IEEEFP_H
  140. #include <ieeefp.h> /* for finite() on Solaris 2.5.1 */
  141. #endif
  142. END_EXTERN_C
  143. #ifdef HAVE_WINDOWS_H
  144. #include <windows.h> /* for GetFileAttributes() */
  145. #ifndef R_OK /* windows defines access() but not the constants */
  146. #define W_OK 02 /* Write permission */
  147. #define R_OK 04 /* Read permission */
  148. #define F_OK 00 /* Existance only */
  149. #endif /* R_OK */
  150. #endif /* HAVE_WINDOWS_H */
  151. // --- ftoa() processing flags ---
  152. const unsigned int OFStandard::ftoa_format_e = 0x01;
  153. const unsigned int OFStandard::ftoa_format_f = 0x02;
  154. const unsigned int OFStandard::ftoa_uppercase = 0x04;
  155. const unsigned int OFStandard::ftoa_alternate = 0x08;
  156. const unsigned int OFStandard::ftoa_leftadj = 0x10;
  157. const unsigned int OFStandard::ftoa_zeropad = 0x20;
  158. /* Some MacOS X versions define isinf() and isnan() in <math.h> but not in <cmath> */
  159. #if defined(__APPLE__) && defined(__MACH__)
  160. #undef HAVE_PROTOTYPE_ISINF
  161. #undef HAVE_PROTOTYPE_ISNAN
  162. #endif
  163. // some systems don't properly define isnan()
  164. #ifdef HAVE_ISNAN
  165. #ifndef HAVE_PROTOTYPE_ISNAN
  166. extern "C"
  167. {
  168. int isnan(double value);
  169. }
  170. #endif
  171. #endif
  172. // some systems don't properly define finite()
  173. #ifdef HAVE_FINITE
  174. #ifndef HAVE_PROTOTYPE_FINITE
  175. extern "C"
  176. {
  177. int finite(double value);
  178. }
  179. #endif
  180. #endif
  181. // some systems don't properly define isinf()
  182. #ifdef HAVE_ISINF
  183. #ifndef HAVE_PROTOTYPE_ISINF
  184. extern "C"
  185. {
  186. int isinf(double value);
  187. }
  188. #endif
  189. #else /* HAVE_ISINF */
  190. static int my_isinf(double x)
  191. {
  192. #ifdef HAVE_WINDOWS_H
  193. return (! _finite(x)) && (! _isnan(x));
  194. #else
  195. // Solaris 2.5.1 has finite() and isnan() but not isinf().
  196. return (! finite(x)) && (! isnan(x));
  197. #endif
  198. }
  199. #endif /* HAVE_ISINF */
  200. // --- string functions ---
  201. #ifndef HAVE_STRLCPY
  202. /*
  203. * Copy src to string dst of size siz. At most siz-1 characters
  204. * will be copied. Always NUL terminates (unless siz == 0).
  205. * Returns strlen(src); if retval >= siz, truncation occurred.
  206. */
  207. size_t OFStandard::my_strlcpy(char *dst, const char *src, size_t siz)
  208. {
  209. register char *d = dst;
  210. register const char *s = src;
  211. register size_t n = siz;
  212. /* Copy as many bytes as will fit */
  213. if (n != 0 && --n != 0)
  214. {
  215. do
  216. {
  217. if ((*d++ = *s++) == 0)
  218. break;
  219. } while (--n != 0);
  220. }
  221. /* Not enough room in dst, add NUL and traverse rest of src */
  222. if (n == 0)
  223. {
  224. if (siz != 0)
  225. *d = '\0'; /* NUL-terminate dst */
  226. while (*s++) /* do_nothing */ ;
  227. }
  228. return(s - src - 1); /* count does not include NUL */
  229. }
  230. #endif /* HAVE_STRLCPY */
  231. #ifndef HAVE_STRLCAT
  232. /*
  233. * Appends src to string dst of size siz (unlike strncat, siz is the
  234. * full size of dst, not space left). At most siz-1 characters
  235. * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
  236. * Returns strlen(src) + MIN(siz, strlen(initial dst)).
  237. * If retval >= siz, truncation occurred.
  238. */
  239. size_t OFStandard::my_strlcat(char *dst, const char *src, size_t siz)
  240. {
  241. register char *d = dst;
  242. register const char *s = src;
  243. register size_t n = siz;
  244. size_t dlen;
  245. /* Find the end of dst and adjust bytes left but don't go past end */
  246. while (n-- != 0 && *d != '\0') d++;
  247. dlen = d - dst;
  248. n = siz - dlen;
  249. if (n == 0) return(dlen + strlen(s));
  250. while (*s != '\0')
  251. {
  252. if (n != 1)
  253. {
  254. *d++ = *s;
  255. n--;
  256. }
  257. s++;
  258. }
  259. *d = '\0';
  260. return(dlen + (s - src)); /* count does not include NUL */
  261. }
  262. #endif /* HAVE_STRLCAT */
  263. // --- file system functions ---
  264. OFBool OFStandard::pathExists(const OFString &pathName)
  265. {
  266. OFBool result = OFFalse;
  267. /* check for valid path name */
  268. if (!pathName.empty())
  269. {
  270. #if HAVE_ACCESS
  271. /* check whether path exists */
  272. result = (access(pathName.c_str(), F_OK) == 0);
  273. #else
  274. #ifdef HAVE_WINDOWS_H
  275. /* check whether path exists */
  276. result = (GetFileAttributes(pathName.c_str()) != 0xffffffff);
  277. #else
  278. #ifdef HAVE_SYS_STAT_H
  279. /* check existence with "stat()" */
  280. struct stat stat_buf;
  281. result = (stat(pathName.c_str(), &stat_buf) == 0);
  282. #else
  283. /* try to open the given "file" (or directory) in read-only mode */
  284. FILE* filePtr = fopen(pathName.c_str(), "r");
  285. result = (filePtr != NULL);
  286. fclose(filePtr);
  287. #endif /* HAVE_SYS_STAT_H */
  288. #endif /* HAVE_WINDOWS_H */
  289. #endif /* HAVE_ACCESS */
  290. }
  291. return result;
  292. }
  293. OFBool OFStandard::fileExists(const OFString &fileName)
  294. {
  295. OFBool result = OFFalse;
  296. /* check for valid file name */
  297. if (!fileName.empty())
  298. {
  299. #ifdef HAVE_WINDOWS_H
  300. /* get file attributes */
  301. DWORD fileAttr = GetFileAttributes(fileName.c_str());
  302. if (fileAttr != 0xffffffff)
  303. {
  304. /* check file type (not a directory?) */
  305. result = ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) == 0);
  306. }
  307. #else
  308. /* check whether path exists (but does not point to a directory) */
  309. result = pathExists(fileName) && !dirExists(fileName);
  310. #endif /* HAVE_WINDOWS_H */
  311. }
  312. return result;
  313. }
  314. OFBool OFStandard::dirExists(const OFString &dirName)
  315. {
  316. OFBool result = OFFalse;
  317. /* check for valid directory name */
  318. if (!dirName.empty())
  319. {
  320. #ifdef HAVE_WINDOWS_H
  321. /* get file attributes of the directory */
  322. DWORD fileAttr = GetFileAttributes(dirName.c_str());
  323. if (fileAttr != 0xffffffff)
  324. {
  325. /* check file type (is a directory?) */
  326. result = ((fileAttr & FILE_ATTRIBUTE_DIRECTORY) != 0);
  327. }
  328. #else
  329. /* try to open the given directory */
  330. DIR *dirPtr = opendir(dirName.c_str());
  331. if (dirPtr != NULL)
  332. {
  333. result = OFTrue;
  334. closedir(dirPtr);
  335. }
  336. #endif /* HAVE_WINDOWS_H */
  337. }
  338. return result;
  339. }
  340. OFBool OFStandard::isReadable(const OFString &pathName)
  341. {
  342. #if HAVE_ACCESS
  343. return (access(pathName.c_str(), R_OK) == 0);
  344. #else
  345. OFBool result = OFFalse;
  346. /* try to open the given "file" (or directory) in read-only mode */
  347. FILE* filePtr = fopen(pathName.c_str(), "r");
  348. result = (filePtr != NULL);
  349. fclose(filePtr);
  350. return result;
  351. #endif /* HAVE_ACCESS */
  352. }
  353. OFBool OFStandard::isWriteable(const OFString &pathName)
  354. {
  355. #if HAVE_ACCESS
  356. return (access(pathName.c_str(), W_OK) == 0);
  357. #else
  358. OFBool result = OFFalse;
  359. /* try to open the given "file" (or directory) in write mode */
  360. FILE* filePtr = fopen(pathName.c_str(), "w");
  361. result = (filePtr != NULL);
  362. fclose(filePtr);
  363. return result;
  364. #endif /* HAVE_ACCESS */
  365. }
  366. OFString &OFStandard::normalizeDirName(OFString &result,
  367. const OFString &dirName,
  368. const OFBool allowEmptyDirName)
  369. {
  370. result = dirName;
  371. /* remove trailing path separators (keep it if appearing at the beginning of the string) */
  372. while ((result.length() > 1) && (result.at(result.length() - 1) == PATH_SEPARATOR))
  373. result.erase(result.length() - 1, 1);
  374. if (allowEmptyDirName)
  375. {
  376. /* avoid "." as a directory name, use empty string instead */
  377. if (result == ".")
  378. result.clear();
  379. } else {
  380. /* avoid empty directory name (use "." instead) */
  381. if (result.empty())
  382. result = ".";
  383. }
  384. return result;
  385. }
  386. OFString &OFStandard::combineDirAndFilename(OFString &result,
  387. const OFString &dirName,
  388. const OFString &fileName,
  389. const OFBool allowEmptyDirName)
  390. {
  391. // ## might use system function realpath() in the future to resolve paths including ".."?
  392. /* check whether 'fileName' contains absolute path */
  393. if (!fileName.empty() && (fileName.at(0) == PATH_SEPARATOR))
  394. result = fileName;
  395. else {
  396. /* normalize the directory name */
  397. normalizeDirName(result, dirName, allowEmptyDirName);
  398. /* check file name */
  399. if (!fileName.empty() && (fileName != "."))
  400. {
  401. /* add path separator (if required) ... */
  402. if (!result.empty() && (result.at(result.length() - 1) != PATH_SEPARATOR))
  403. result += PATH_SEPARATOR;
  404. /* ...and file name */
  405. result += fileName;
  406. }
  407. }
  408. return result;
  409. }
  410. size_t OFStandard::searchDirectoryRecursively(const OFString &directory,
  411. OFList<OFString> &fileList,
  412. const OFString &pattern,
  413. const OFString &dirPrefix)
  414. {
  415. const size_t initialSize = fileList.size();
  416. OFString dirname, pathname, tmpString;
  417. combineDirAndFilename(dirname, dirPrefix, directory, OFTrue /*allowEmptyDirName*/);
  418. #ifdef HAVE_WINDOWS_H
  419. /* check whether given directory exists */
  420. if (dirExists(dirname))
  421. {
  422. HANDLE handle;
  423. WIN32_FIND_DATA data;
  424. /* check whether file pattern is given */
  425. if (!pattern.empty())
  426. {
  427. /* first, search for matching files on this directory level */
  428. handle = FindFirstFile(combineDirAndFilename(tmpString, dirname, pattern, OFTrue /*allowEmptyDirName*/).c_str(), &data);
  429. if (handle != INVALID_HANDLE_VALUE)
  430. {
  431. do {
  432. /* avoid leading "." */
  433. if (dirname == ".")
  434. pathname = data.cFileName;
  435. else
  436. combineDirAndFilename(pathname, directory, data.cFileName, OFTrue /*allowEmptyDirName*/);
  437. /* ignore directories and the like */
  438. if (fileExists(combineDirAndFilename(tmpString, dirPrefix, pathname, OFTrue /*allowEmptyDirName*/)))
  439. fileList.push_back(pathname);
  440. } while (FindNextFile(handle, &data));
  441. FindClose(handle);
  442. }
  443. }
  444. /* then search for _any_ file/directory entry */
  445. handle = FindFirstFile(combineDirAndFilename(tmpString, dirname, "*.*", OFTrue /*allowEmptyDirName*/).c_str(), &data);
  446. if (handle != INVALID_HANDLE_VALUE)
  447. {
  448. do {
  449. /* filter out current and parent directory */
  450. if ((strcmp(data.cFileName, ".") != 0) && (strcmp(data.cFileName, "..") != 0))
  451. {
  452. /* avoid leading "." */
  453. if (dirname == ".")
  454. pathname = data.cFileName;
  455. else
  456. combineDirAndFilename(pathname, directory, data.cFileName, OFTrue /*allowEmptyDirName*/);
  457. /* recursively search sub directories */
  458. if (dirExists(combineDirAndFilename(tmpString, dirPrefix, pathname, OFTrue /*allowEmptyDirName*/)))
  459. searchDirectoryRecursively(pathname, fileList, pattern, dirPrefix);
  460. /* add filename to the list (if no pattern is given) */
  461. else if (pattern.empty())
  462. fileList.push_back(pathname);
  463. }
  464. } while (FindNextFile(handle, &data));
  465. FindClose(handle);
  466. }
  467. }
  468. #else
  469. /* try to open the directory */
  470. DIR *dirPtr = opendir(dirname.c_str());
  471. if (dirPtr != NULL)
  472. {
  473. struct dirent *entry = NULL;
  474. while ((entry = readdir(dirPtr)) != NULL)
  475. {
  476. /* filter out current and parent directory */
  477. if ((strcmp(entry->d_name, ".") != 0) && (strcmp(entry->d_name, "..") != 0))
  478. {
  479. /* avoid leading "." */
  480. if (dirname == ".")
  481. pathname = entry->d_name;
  482. else
  483. combineDirAndFilename(pathname, directory, entry->d_name, OFTrue /*allowEmptyDirName*/);
  484. /* recursively search sub directories */
  485. if (dirExists(combineDirAndFilename(tmpString, dirPrefix, pathname, OFTrue /*allowEmptyDirName*/)))
  486. searchDirectoryRecursively(pathname, fileList, pattern, dirPrefix);
  487. /* check whether filename matches pattern */
  488. else
  489. #ifdef HAVE_FNMATCH_H
  490. if ((pattern.empty()) || (fnmatch(pattern.c_str(), entry->d_name, FNM_PATHNAME) == 0))
  491. #else
  492. /* no pattern matching, sorry :-/ */
  493. #endif
  494. fileList.push_back(pathname);
  495. }
  496. }
  497. closedir(dirPtr);
  498. }
  499. #endif
  500. /* return number of added files */
  501. return fileList.size() - initialSize;
  502. }
  503. const OFString &OFStandard::convertToMarkupString(const OFString &sourceString,
  504. OFString &markupString,
  505. const OFBool convertNonASCII,
  506. const OFBool xmlMode,
  507. const OFBool newlineAllowed)
  508. {
  509. /* char ptr allows fastest access to the string */
  510. const char *str = sourceString.c_str();
  511. /* start with empty string */
  512. markupString.clear();
  513. /* avoid to resize the string too often */
  514. markupString.reserve(strlen(str));
  515. /* replace HTML/XML reserved characters */
  516. while (*str != 0)
  517. {
  518. /* less than */
  519. if (*str == '<')
  520. markupString += "&lt;";
  521. /* greater than */
  522. else if (*str == '>')
  523. markupString += "&gt;";
  524. /* ampers and */
  525. else if (*str == '&')
  526. markupString += "&amp;";
  527. /* quotation mark */
  528. else if (*str == '"')
  529. markupString += "&quot;";
  530. /* apostrophe */
  531. else if (*str == '\'')
  532. markupString += "&apos;";
  533. /* newline: LF, CR, LF CR, CR LF */
  534. else if ((*str == '\012') || (*str == '\015'))
  535. {
  536. if (xmlMode)
  537. {
  538. /* encode CR and LF exactly as specified */
  539. if (*str == '\012')
  540. markupString += "&#10;"; // '\n'
  541. else
  542. markupString += "&#13;"; // '\r'
  543. } else { /* HTML mode */
  544. /* skip next character if it belongs to the newline sequence */
  545. if (((*str == '\012') && (*(str + 1) == '\015')) || ((*str == '\015') && (*(str + 1) == '\012')))
  546. str++;
  547. if (newlineAllowed)
  548. markupString += "<br>\n";
  549. else
  550. markupString += "&para;";
  551. }
  552. } else {
  553. /* other character: ... */
  554. const size_t charValue = OFstatic_cast(unsigned char, *str);
  555. if (convertNonASCII && (charValue > 127))
  556. {
  557. char buffer[16];
  558. sprintf(buffer, "%lu", OFstatic_cast(unsigned long, charValue));
  559. /* convert > #127 to Unicode (ISO Latin-1), what is about < #32 ? */
  560. markupString += "&#";
  561. markupString += buffer;
  562. markupString += ";";
  563. } else {
  564. /* just append */
  565. markupString += *str;
  566. }
  567. }
  568. str++;
  569. }
  570. return markupString;
  571. }
  572. // Base64 translation table as described in RFC 2045 (MIME)
  573. static const char enc_base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  574. const OFString &OFStandard::encodeBase64(const unsigned char *data,
  575. const size_t length,
  576. OFString &result,
  577. const size_t width)
  578. {
  579. result.clear();
  580. /* check data buffer to be encoded */
  581. if (data != NULL)
  582. {
  583. unsigned char c;
  584. size_t w = 0;
  585. /* reserve expected output size: +33%, even multiple of 4 */
  586. result.reserve(((length + 2) / 3) * 4);
  587. char *bufPtr = OFconst_cast(char *, result.c_str());
  588. /* iterate over all data elements */
  589. for (size_t i = 0; i < length; i++)
  590. {
  591. /* encode first 6 bits */
  592. *(bufPtr++) = enc_base64[(data[i] >> 2) & 0x3f];
  593. /* insert line break (if width > 0) */
  594. if (++w == width)
  595. {
  596. *(bufPtr++) = OFstatic_cast(unsigned char, '\n');
  597. w = 0;
  598. }
  599. /* encode remaining 2 bits of the first byte and 4 bits of the second byte */
  600. c = (data[i] << 4) & 0x3f;
  601. if (++i < length)
  602. c |= (data[i] >> 4) & 0x0f;
  603. *(bufPtr++) = enc_base64[c];
  604. /* insert line break (if width > 0) */
  605. if (++w == width)
  606. {
  607. *(bufPtr++) = OFstatic_cast(unsigned char, '\n');
  608. w = 0;
  609. }
  610. /* encode remaining 4 bits of the second byte and 2 bits of the third byte */
  611. if (i < length)
  612. {
  613. c = (data[i] << 2) & 0x3f;
  614. if (++i < length)
  615. c |= (data[i] >> 6) & 0x03;
  616. *(bufPtr++) = enc_base64[c];
  617. } else {
  618. i++;
  619. /* append fill char */
  620. *(bufPtr++) = '=';
  621. }
  622. /* insert line break (if width > 0) */
  623. if (++w == width)
  624. {
  625. *(bufPtr++) = '\n';
  626. w = 0;
  627. }
  628. /* encode remaining 6 bits of the third byte */
  629. if (i < length)
  630. *(bufPtr++) = enc_base64[data[i] & 0x3f];
  631. else /* append fill char */
  632. *(bufPtr++) = '=';
  633. /* insert line break (if width > 0) */
  634. if (++w == width)
  635. {
  636. *(bufPtr++) = '\n';
  637. w = 0;
  638. }
  639. }
  640. /* append trailing 0 byte (probably not required) */
  641. *bufPtr = '\0';
  642. }
  643. return result;
  644. }
  645. // Base64 decoding table: maps #43..#122 to #0..#63 (255 means invalid)
  646. static const unsigned char dec_base64[] =
  647. { 62, 255, 255, 255, 63, // '+' .. '/'
  648. 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0' .. '9'
  649. 255, 255, 255, 255, 255, 255, 255, // ':' .. '@'
  650. 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'
  651. 255, 255, 255, 255, 255, 255, // '[' .. '`'
  652. 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'
  653. };
  654. size_t OFStandard::decodeBase64(const OFString &data,
  655. unsigned char *&result)
  656. {
  657. size_t count = 0;
  658. /* search for fill char to determine the real length of the input string */
  659. const size_t fillPos = data.find('=');
  660. const size_t length = (fillPos != OFString_npos) ? fillPos : data.length();
  661. /* check data buffer to be decoded */
  662. if (length > 0)
  663. {
  664. /* allocate sufficient memory for the decoded data */
  665. result = new unsigned char[((length + 3) / 4) * 3];
  666. if (result != NULL)
  667. {
  668. unsigned char c1 = 0;
  669. unsigned char c2 = 0;
  670. /* iterate over all data elements */
  671. for (size_t i = 0; i < length; i++)
  672. {
  673. /* skip invalid characters and assign first decoded char */
  674. while ((i < length) && ((data.at(i) < '+') || (data.at(i) > 'z') || ((c1 = dec_base64[data.at(i) - '+']) > 63)))
  675. i++;
  676. if (++i < length)
  677. {
  678. /* skip invalid characters and assign second decoded char */
  679. while ((i < length) && ((data.at(i) < '+') || (data.at(i) > 'z') || ((c2 = dec_base64[data.at(i) - '+']) > 63)))
  680. i++;
  681. if (i < length)
  682. {
  683. /* decode first byte */
  684. result[count++] = OFstatic_cast(unsigned char, (c1 << 2) | ((c2 >> 4) & 0x3));
  685. if (++i < length)
  686. {
  687. /* skip invalid characters and assign third decoded char */
  688. while ((i < length) && ((data.at(i) < '+') || (data.at(i) > 'z') || ((c1 = dec_base64[data.at(i) - '+']) > 63)))
  689. i++;
  690. if (i < length)
  691. {
  692. /* decode second byte */
  693. result[count++] = OFstatic_cast(unsigned char, ((c2 << 4) & 0xf0) | ((c1 >> 2) & 0xf));
  694. if (++i < length)
  695. {
  696. /* skip invalid characters and assign fourth decoded char */
  697. while ((i < length) && ((data.at(i) < '+') || (data.at(i) > 'z') || ((c2 = dec_base64[data.at(i) - '+']) > 63)))
  698. i++;
  699. /* decode third byte */
  700. if (i < length)
  701. result[count++] = OFstatic_cast(unsigned char, ((c1 << 6) & 0xc0) | c2);
  702. }
  703. }
  704. }
  705. }
  706. }
  707. }
  708. /* delete buffer if no data has been written to the output */
  709. if (count == 0)
  710. delete[] result;
  711. }
  712. } else
  713. result = NULL;
  714. return count;
  715. }
  716. #ifdef DISABLE_OFSTD_ATOF
  717. // we use sscanf instead of atof because atof doesn't return a status flag
  718. double OFStandard::atof(const char *s, OFBool *success)
  719. {
  720. double result;
  721. if (success)
  722. {
  723. *success = (1 == sscanf(s,"%lf",&result));
  724. }
  725. else
  726. {
  727. (void) sscanf(s,"%lf",&result);
  728. }
  729. return result;
  730. }
  731. #else
  732. // --- definitions and constants for atof() ---
  733. /* Largest possible base 10 exponent. Any exponent larger than this will
  734. * already produce underflow or overflow, so there's no need to worry
  735. * about additional digits.
  736. */
  737. #define ATOF_MAXEXPONENT 511
  738. /* Table giving binary powers of 10. Entry is 10^2^i.
  739. * Used to convert decimal exponents into floating-point numbers.
  740. */
  741. static const double atof_powersOf10[] =
  742. {
  743. 10.,
  744. 100.,
  745. 1.0e4,
  746. 1.0e8,
  747. 1.0e16,
  748. 1.0e32,
  749. 1.0e64,
  750. 1.0e128,
  751. 1.0e256
  752. };
  753. double OFStandard::atof(const char *s, OFBool *success)
  754. {
  755. if (success) *success = OFFalse;
  756. register const char *p = s;
  757. register char c;
  758. int sign = 0;
  759. int expSign = 0;
  760. double fraction;
  761. int exponent = 0; // Exponent read from "EX" field.
  762. const char *pExp; // Temporarily holds location of exponent in string.
  763. /* Exponent that derives from the fractional part. Under normal
  764. * circumstatnces, it is the negative of the number of digits in F.
  765. * However, if I is very long, the last digits of I get dropped
  766. * (otherwise a long I with a large negative exponent could cause an
  767. * unnecessary overflow on I alone). In this case, fracExp is
  768. * incremented one for each dropped digit.
  769. */
  770. int fracExp = 0;
  771. // Strip off leading blanks and check for a sign.
  772. while (isspace(OFstatic_cast(int, *p))) ++p;
  773. if (*p == '-')
  774. {
  775. sign = 1;
  776. ++p;
  777. }
  778. else
  779. {
  780. if (*p == '+') ++p;
  781. }
  782. // Count the number of digits in the mantissa (including the decimal
  783. // point), and also locate the decimal point.
  784. int decPt = -1; // Number of mantissa digits BEFORE decimal point.
  785. int mantSize; // Number of digits in mantissa.
  786. for (mantSize = 0; ; ++mantSize)
  787. {
  788. c = *p;
  789. if (!isdigit(OFstatic_cast(int, c)))
  790. {
  791. if ((c != '.') || (decPt >= 0)) break;
  792. decPt = mantSize;
  793. }
  794. ++p;
  795. }
  796. /*
  797. * Now suck up the digits in the mantissa. Use two integers to
  798. * collect 9 digits each (this is faster than using floating-point).
  799. * If the mantissa has more than 18 digits, ignore the extras, since
  800. * they can't affect the value anyway.
  801. */
  802. pExp = p;
  803. p -= mantSize;
  804. if (decPt < 0)
  805. decPt = mantSize;
  806. else mantSize -= 1; // One of the digits was the point
  807. if (mantSize > 18)
  808. {
  809. fracExp = decPt - 18;
  810. mantSize = 18;
  811. }
  812. else
  813. {
  814. fracExp = decPt - mantSize;
  815. }
  816. if (mantSize == 0)
  817. {
  818. // subject sequence does not have expected form.
  819. // return 0 and leave success flag set to false
  820. return 0.0;
  821. }
  822. else
  823. {
  824. int frac1 = 0;
  825. for ( ; mantSize > 9; mantSize -= 1)
  826. {
  827. c = *p;
  828. ++p;
  829. if (c == '.')
  830. {
  831. c = *p;
  832. ++p;
  833. }
  834. frac1 = 10*frac1 + (c - '0');
  835. }
  836. int frac2 = 0;
  837. for (; mantSize > 0; mantSize -= 1)
  838. {
  839. c = *p;
  840. ++p;
  841. if (c == '.')
  842. {
  843. c = *p;
  844. ++p;
  845. }
  846. frac2 = 10*frac2 + (c - '0');
  847. }
  848. fraction = (1.0e9 * frac1) + frac2;
  849. }
  850. // Skim off the exponent.
  851. p = pExp;
  852. if ((*p == 'E') || (*p == 'e'))
  853. {
  854. ++p;
  855. if (*p == '-')
  856. {
  857. expSign = 1;
  858. ++p;
  859. }
  860. else
  861. {
  862. if (*p == '+') ++p;
  863. expSign = 0;
  864. }
  865. while (isdigit(OFstatic_cast(int, *p)))
  866. {
  867. exponent = exponent * 10 + (*p - '0');
  868. ++p;
  869. }
  870. }
  871. if (expSign)
  872. exponent = fracExp - exponent;
  873. else exponent = fracExp + exponent;
  874. /*
  875. * Generate a floating-point number that represents the exponent.
  876. * Do this by processing the exponent one bit at a time to combine
  877. * many powers of 2 of 10. Then combine the exponent with the
  878. * fraction.
  879. */
  880. if (exponent < 0)
  881. {
  882. expSign = 1;
  883. exponent = -exponent;
  884. }
  885. else expSign = 0;
  886. if (exponent > ATOF_MAXEXPONENT) exponent = ATOF_MAXEXPONENT;
  887. double dblExp = 1.0;
  888. for (const double *d = atof_powersOf10; exponent != 0; exponent >>= 1, ++d)
  889. {
  890. if (exponent & 01) dblExp *= *d;
  891. }
  892. if (expSign)
  893. fraction /= dblExp;
  894. else fraction *= dblExp;
  895. if (success) *success = OFTrue;
  896. if (sign) return -fraction;
  897. return fraction;
  898. }
  899. #endif /* DISABLE_OFSTD_ATOF */
  900. /* 11-bit exponent (VAX G floating point) is 308 decimal digits */
  901. #define FTOA_MAXEXP 308
  902. /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */
  903. #define FTOA_MAXFRACT 39
  904. /* default precision */
  905. #define FTOA_DEFPREC 6
  906. /* internal buffer size for ftoa code */
  907. #define FTOA_BUFSIZE (FTOA_MAXEXP+FTOA_MAXFRACT+1)
  908. #define FTOA_TODIGIT(c) ((c) - '0')
  909. #define FTOA_TOCHAR(n) ((n) + '0')
  910. #define FTOA_FORMAT_MASK 0x03 /* and mask for format flags */
  911. #define FTOA_FORMAT_E OFStandard::ftoa_format_e
  912. #define FTOA_FORMAT_F OFStandard::ftoa_format_f
  913. #define FTOA_FORMAT_UPPERCASE OFStandard::ftoa_uppercase
  914. #define FTOA_ALTERNATE_FORM OFStandard::ftoa_alternate
  915. #define FTOA_LEFT_ADJUSTMENT OFStandard::ftoa_leftadj
  916. #define FTOA_ZEROPAD OFStandard::ftoa_zeropad
  917. #ifdef DISABLE_OFSTD_FTOA
  918. void OFStandard::ftoa(
  919. char *dst,
  920. size_t siz,
  921. double val,
  922. unsigned int flags,
  923. int width,
  924. int prec)
  925. {
  926. // this version of the function uses sprintf to format the output string.
  927. // Since we have to assemble the sprintf format string, this version might
  928. // even be slower than the alternative implementation.
  929. char buf[FTOA_BUFSIZE];
  930. OFString s("%"); // this will become the format string
  931. unsigned char fmtch = 'G';
  932. // check if val is NAN
  933. #ifdef HAVE_WINDOWS_H
  934. if (_isnan(val))
  935. #else
  936. if (isnan(val))
  937. #endif
  938. {
  939. OFStandard::strlcpy(dst, "nan", siz);
  940. return;
  941. }
  942. // check if val is infinity
  943. #ifdef HAVE_ISINF
  944. if (isinf(val))
  945. #else
  946. if (my_isinf(val))
  947. #endif
  948. {
  949. if (val < 0)
  950. OFStandard::strlcpy(dst, "-inf", siz);
  951. else OFStandard::strlcpy(dst, "inf", siz);
  952. return;
  953. }
  954. // determine format character
  955. if (flags & FTOA_FORMAT_UPPERCASE)
  956. {
  957. if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_E) fmtch = 'E';
  958. else if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_F) fmtch = 'f'; // there is no uppercase for 'f'
  959. else fmtch = 'G';
  960. }
  961. else
  962. {
  963. if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_E) fmtch = 'e';
  964. else if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_F) fmtch = 'f';
  965. else fmtch = 'g';
  966. }
  967. if (flags & FTOA_ALTERNATE_FORM) s += "#";
  968. if (flags & FTOA_LEFT_ADJUSTMENT) s += "-";
  969. if (flags & FTOA_ZEROPAD) s += "0";
  970. if (width > 0)
  971. {
  972. sprintf(buf, "%d", width);
  973. s += buf;
  974. }
  975. if (prec >= 0)
  976. {
  977. sprintf(buf, ".%d", prec);
  978. s += buf;
  979. }
  980. s += fmtch;
  981. sprintf(buf, s.c_str(), val);
  982. OFStandard::strlcpy(dst, buf, siz);
  983. }
  984. #else
  985. /** internal helper class that maintains a string buffer
  986. * to which characters can be written. If the string buffer
  987. * gets full, additional characters are discarded.
  988. * The string buffer does not guarantee zero termination.
  989. */
  990. class FTOAStringBuffer
  991. {
  992. public:
  993. /** constructor
  994. * @param theSize desired size of string buffer, in bytes
  995. */
  996. FTOAStringBuffer(unsigned long theSize)
  997. : buf_(NULL)
  998. , offset_(0)
  999. , size_(theSize)
  1000. {
  1001. if (size_ > 0) buf_ = new char[size_];
  1002. }
  1003. /// destructor
  1004. ~FTOAStringBuffer()
  1005. {
  1006. delete[] buf_;
  1007. }
  1008. /** add one character to string buffer. Never overwrites
  1009. * buffer boundary.
  1010. * @param c character to add
  1011. */
  1012. inline void put(unsigned char c)
  1013. {
  1014. if (buf_ && (offset_ < size_)) buf_[offset_++] = c;
  1015. }
  1016. // return pointer to string buffer
  1017. const char *getBuffer() const
  1018. {
  1019. return buf_;
  1020. }
  1021. private:
  1022. /// pointer to string buffer
  1023. char *buf_;
  1024. /// current offset within buffer
  1025. unsigned long offset_;
  1026. /// size of buffer
  1027. unsigned long size_;
  1028. /// private undefined copy constructor
  1029. FTOAStringBuffer(const FTOAStringBuffer &old);
  1030. /// private undefined assignment operator
  1031. FTOAStringBuffer &operator=(const FTOAStringBuffer &obj);
  1032. };
  1033. /** writes the given format character and exponent to output string p.
  1034. * @param p pointer to target string
  1035. * @param exponent exponent to print
  1036. * @param fmtch format character
  1037. * @return pointer to next unused character in output string
  1038. */
  1039. static char *ftoa_exponent(char *p, int exponent, char fmtch)
  1040. {
  1041. char expbuf[FTOA_MAXEXP];
  1042. *p++ = fmtch;
  1043. if (exponent < 0)
  1044. {
  1045. exponent = -exponent;
  1046. *p++ = '-';
  1047. }
  1048. else *p++ = '+';
  1049. register char *t = expbuf + FTOA_MAXEXP;
  1050. if (exponent > 9)
  1051. {
  1052. do
  1053. {
  1054. *--t = OFstatic_cast(char, FTOA_TOCHAR(exponent % 10));
  1055. }
  1056. while ((exponent /= 10) > 9);
  1057. *--t = OFstatic_cast(char, FTOA_TOCHAR(exponent));
  1058. for (; t < expbuf + FTOA_MAXEXP; *p++ = *t++) /* nothing */;
  1059. }
  1060. else
  1061. {
  1062. *p++ = '0';
  1063. *p++ = OFstatic_cast(char, FTOA_TOCHAR(exponent));
  1064. }
  1065. return p;
  1066. }
  1067. /** round given fraction and adjust text string if round up.
  1068. * @param fract fraction to round
  1069. * @param expon pointer to exponent, may be NULL
  1070. * @param start pointer to start of string to round
  1071. * @param end pointer to one char after end of string
  1072. * @param ch if fract is zero, this character is interpreted as fraction*10 instead
  1073. * @param signp pointer to sign character, '-' or 0.
  1074. * @return adjusted pointer to start of rounded string, may be start or start-1.
  1075. */
  1076. static char *ftoa_round(double fract, int *expon, char *start, char *end, char ch, char *signp)
  1077. {
  1078. double tmp;
  1079. if (fract) (void) modf(fract * 10, &tmp);
  1080. else tmp = FTOA_TODIGIT(ch);
  1081. if (tmp > 4)
  1082. {
  1083. for (;; --end)
  1084. {
  1085. if (*end == '.') --end;
  1086. if (++*end <= '9') break;
  1087. *end = '0';
  1088. if (end == start)
  1089. {
  1090. if (expon) /* e/E; increment exponent */
  1091. {
  1092. *end = '1';
  1093. ++*expon;
  1094. }
  1095. else /* f; add extra digit */
  1096. {
  1097. *--end = '1';
  1098. --start;
  1099. }
  1100. break;
  1101. }
  1102. }
  1103. }
  1104. /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
  1105. else if (*signp == '-')
  1106. {
  1107. for (;; --end)
  1108. {
  1109. if (*end == '.') --end;
  1110. if (*end != '0') break;
  1111. if (end == start) *signp = 0; // suppress negative 0
  1112. }
  1113. }
  1114. return start;
  1115. }
  1116. /** convert double value to string, without padding
  1117. * @param val double value to be formatted
  1118. * @param prec precision, adjusted for FTOA_MAXFRACT
  1119. * @param flags formatting flags
  1120. * @param signp pointer to sign character, '-' or 0.
  1121. * @param fmtch format character
  1122. * @param startp pointer to start of target buffer
  1123. * @param endp pointer to one char after end of target buffer
  1124. * @return
  1125. */
  1126. static int ftoa_convert(double val, int prec, int flags, char *signp, char fmtch, char *startp, char *endp)
  1127. {
  1128. register char *p;
  1129. register double fract;
  1130. int dotrim = 0;
  1131. int expcnt = 0;
  1132. int gformat = 0;
  1133. double integer, tmp;
  1134. fract = modf(val, &integer);
  1135. /* get an extra slot for rounding. */
  1136. register char *t = ++startp;
  1137. /*
  1138. * get integer portion of val; put into the end of the buffer; the
  1139. * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
  1140. */
  1141. for (p = endp - 1; integer; ++expcnt)
  1142. {
  1143. tmp = modf(integer / 10, &integer);
  1144. *p-- = OFstatic_cast(char, FTOA_TOCHAR(OFstatic_cast(int, (tmp + .01) * 10)));
  1145. }
  1146. switch(fmtch)
  1147. {
  1148. case 'f':
  1149. /* reverse integer into beginning of buffer */
  1150. if (expcnt)
  1151. {
  1152. for (; ++p < endp; *t++ = *p);
  1153. }
  1154. else *t++ = '0';
  1155. /*
  1156. * if precision required or alternate flag set, add in a
  1157. * decimal point.
  1158. */
  1159. if (prec || flags & FTOA_ALTERNATE_FORM) *t++ = '.';
  1160. /* if requires more precision and some fraction left */
  1161. if (fract)
  1162. {
  1163. if (prec) do
  1164. {
  1165. fract = modf(fract * 10, &tmp);
  1166. *t++ = OFstatic_cast(char, FTOA_TOCHAR(OFstatic_cast(int, tmp)));
  1167. } while (--prec && fract);
  1168. if (fract)
  1169. {
  1170. startp = ftoa_round(fract, OFstatic_cast(int *, NULL), startp, t - 1, OFstatic_cast(char, 0), signp);
  1171. }
  1172. }
  1173. for (; prec--; *t++ = '0');
  1174. break;
  1175. case 'e':
  1176. case 'E':
  1177. eformat:
  1178. if (expcnt)
  1179. {
  1180. *t++ = *++p;
  1181. if (prec || flags&FTOA_ALTERNATE_FORM)
  1182. *t++ = '.';
  1183. /* if requires more precision and some integer left */
  1184. for (; prec && ++p < endp; --prec)
  1185. *t++ = *p;
  1186. /*
  1187. * if done precision and more of the integer component,
  1188. * round using it; adjust fract so we don't re-round
  1189. * later.
  1190. */
  1191. if (!prec && ++p < endp)
  1192. {
  1193. fract = 0;
  1194. startp = ftoa_round(OFstatic_cast(double, 0), &expcnt, startp, t - 1, *p, signp);
  1195. }
  1196. /* adjust expcnt for digit in front of decimal */
  1197. --expcnt;
  1198. }
  1199. /* until first fractional digit, decrement exponent */
  1200. else if (fract)
  1201. {
  1202. /* adjust expcnt for digit in front of decimal */
  1203. for (expcnt = -1;; --expcnt) {
  1204. fract = modf(fract * 10, &tmp);
  1205. if (tmp)
  1206. break;
  1207. }
  1208. *t++ = OFstatic_cast(char, FTOA_TOCHAR(OFstatic_cast(int, tmp)));
  1209. if (prec || flags&FTOA_ALTERNATE_FORM) *t++ = '.';
  1210. }
  1211. else
  1212. {
  1213. *t++ = '0';
  1214. if (prec || flags&FTOA_ALTERNATE_FORM) *t++ = '.';
  1215. }
  1216. /* if requires more precision and some fraction left */
  1217. if (fract)
  1218. {
  1219. if (prec) do
  1220. {
  1221. fract = modf(fract * 10, &tmp);
  1222. *t++ = OFstatic_cast(char, FTOA_TOCHAR(OFstatic_cast(int, tmp)));
  1223. } while (--prec && fract);
  1224. if (fract)
  1225. {
  1226. startp = ftoa_round(fract, &expcnt, startp, t - 1, OFstatic_cast(char, 0), signp);
  1227. }
  1228. }
  1229. /* if requires more precision */
  1230. for (; prec--; *t++ = '0');
  1231. /* unless alternate flag, trim any g/G format trailing 0's */
  1232. if (gformat && !(flags&FTOA_ALTERNATE_FORM))
  1233. {
  1234. while (t > startp && *--t == '0') /* nothing */;
  1235. if (*t == '.') --t;
  1236. ++t;
  1237. }
  1238. t = ftoa_exponent(t, expcnt, fmtch);
  1239. break;
  1240. case 'g':
  1241. case 'G':
  1242. /* a precision of 0 is treated as a precision of 1. */
  1243. if (!prec) ++prec;
  1244. /*
  1245. * ``The style used depends on the value converted; style e
  1246. * will be used only if the exponent resulting from the
  1247. * conversion is less than -4 or greater than the precision.''
  1248. * -- ANSI X3J11
  1249. */
  1250. if (expcnt > prec || !expcnt && fract && fract < .0001)
  1251. {
  1252. /*
  1253. * g/G format counts "significant digits, not digits of
  1254. * precision; for the e/E format, this just causes an
  1255. * off-by-one problem, i.e. g/G considers the digit
  1256. * before the decimal point significant and e/E doesn't
  1257. * count it as precision.
  1258. */
  1259. --prec;
  1260. fmtch -= 2; /* G->E, g->e */
  1261. gformat = 1;
  1262. goto eformat;
  1263. }
  1264. /*
  1265. * reverse integer into beginning of buffer,
  1266. * note, decrement precision
  1267. */
  1268. if (expcnt)
  1269. {
  1270. for (; ++p < endp; *t++ = *p, --prec);
  1271. }
  1272. else *t++ = '0';
  1273. /*
  1274. * if precision required or alternate flag set, add in a
  1275. * decimal point. If no digits yet, add in leading 0.
  1276. */
  1277. if (prec || flags&FTOA_ALTERNATE_FORM)
  1278. {
  1279. dotrim = 1;
  1280. *t++ = '.';
  1281. }
  1282. else dotrim = 0;
  1283. /* if requires more precision and some fraction left */
  1284. if (fract)
  1285. {
  1286. if (prec)
  1287. {
  1288. do
  1289. {
  1290. fract = modf(fract * 10, &tmp);
  1291. *t++ = OFstatic_cast(char, FTOA_TOCHAR(OFstatic_cast(int, tmp)));
  1292. } while(!tmp);
  1293. while (--prec && fract)
  1294. {
  1295. fract = modf(fract * 10, &tmp);
  1296. *t++ = OFstatic_cast(char, FTOA_TOCHAR(OFstatic_cast(int, tmp)));
  1297. }
  1298. }
  1299. if (fract)
  1300. {
  1301. startp = ftoa_round(fract, OFstatic_cast(int *, NULL), startp, t - 1, OFstatic_cast(char, 0), signp);
  1302. }
  1303. }
  1304. /* alternate format, adds 0's for precision, else trim 0's */
  1305. if (flags&FTOA_ALTERNATE_FORM) for (; prec--; *t++ = '0') /* nothing */;
  1306. else if (dotrim)
  1307. {
  1308. while (t > startp && *--t == '0') /* nothing */;
  1309. if (*t != '.') ++t;
  1310. }
  1311. } /* end switch */
  1312. return (t - startp);
  1313. }
  1314. void OFStandard::ftoa(
  1315. char *dst,
  1316. size_t siz,
  1317. double val,
  1318. unsigned int flags,
  1319. int width,
  1320. int prec)
  1321. {
  1322. // if target string is NULL or zero bytes long, bail out.
  1323. if (!dst || !siz) return;
  1324. // check if val is NAN
  1325. #ifdef HAVE_WINDOWS_H
  1326. if (_isnan(val))
  1327. #else
  1328. if (isnan(val))
  1329. #endif
  1330. {
  1331. OFStandard::strlcpy(dst, "nan", siz);
  1332. return;
  1333. }
  1334. // check if val is infinity
  1335. #ifdef HAVE_ISINF
  1336. if (isinf(val))
  1337. #else
  1338. if (my_isinf(val))
  1339. #endif
  1340. {
  1341. if (val < 0)
  1342. OFStandard::strlcpy(dst, "-inf", siz);
  1343. else OFStandard::strlcpy(dst, "inf", siz);
  1344. return;
  1345. }
  1346. int fpprec = 0; /* `extra' floating precision in [eEfgG] */
  1347. char softsign = 0; /* temporary negative sign for floats */
  1348. char buf[FTOA_BUFSIZE]; /* space for %c, %[diouxX], %[eEfgG] */
  1349. char sign = '\0'; /* sign prefix (' ', '+', '-', or \0) */
  1350. register int n;
  1351. unsigned char fmtch = 'G';
  1352. FTOAStringBuffer sb(FTOA_BUFSIZE+1);
  1353. // determine format character
  1354. if (flags & FTOA_FORMAT_UPPERCASE)
  1355. {
  1356. if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_E) fmtch = 'E';
  1357. else if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_F) fmtch = 'f'; // there is no uppercase for 'f'
  1358. else fmtch = 'G';
  1359. }
  1360. else
  1361. {
  1362. if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_E) fmtch = 'e';
  1363. else if ((flags & FTOA_FORMAT_MASK) == FTOA_FORMAT_F) fmtch = 'f';
  1364. else fmtch = 'g';
  1365. }
  1366. // don't do unrealistic precision; just pad it with zeroes later,
  1367. // so buffer size stays rational.
  1368. if (prec > FTOA_MAXFRACT)
  1369. {
  1370. if (fmtch != 'g' && fmtch != 'G' || (flags&FTOA_ALTERNATE_FORM)) fpprec = prec - FTOA_MAXFRACT;
  1371. prec = FTOA_MAXFRACT;
  1372. }
  1373. else if (prec == -1) prec = FTOA_DEFPREC;
  1374. /*
  1375. * softsign avoids negative 0 if val is < 0 and
  1376. * no significant digits will be shown
  1377. */
  1378. if (val < 0)
  1379. {
  1380. softsign = '-';
  1381. val = -val;
  1382. }
  1383. else softsign = 0;
  1384. /*
  1385. * ftoa_convert may have to round up past the "start" of the
  1386. * buffer, i.e. ``intf("%.2f", (double)9.999);'';
  1387. * if the first char isn't \0, it did.
  1388. */
  1389. *buf = 0;
  1390. int size = ftoa_convert(val, prec, flags, &softsign, fmtch, buf, buf + sizeof(buf));
  1391. if (softsign) sign = '-';
  1392. register char *t = *buf ? buf : buf + 1;
  1393. /* At this point, `t' points to a string which (if not flags&FTOA_LEFT_ADJUSTMENT)
  1394. * should be padded out to `width' places. If flags&FTOA_ZEROPAD, it should
  1395. * first be prefixed by any sign or other prefix; otherwise, it should be
  1396. * blank padded before the prefix is emitted. After any left-hand
  1397. * padding, print the string proper, then emit zeroes required by any
  1398. * leftover floating precision; finally, if FTOA_LEFT_ADJUSTMENT, pad with blanks.
  1399. *
  1400. * compute actual size, so we know how much to pad
  1401. */
  1402. int fieldsz = size + fpprec;
  1403. if (sign) fieldsz++;
  1404. /* right-adjusting blank padding */
  1405. if ((flags & (FTOA_LEFT_ADJUSTMENT|FTOA_ZEROPAD)) == 0 && width)
  1406. {
  1407. for (n = fieldsz; n < width; n++) sb.put(' ');
  1408. }
  1409. /* prefix */
  1410. if (sign) sb.put(sign);
  1411. /* right-adjusting zero padding */
  1412. if ((flags & (FTOA_LEFT_ADJUSTMENT|FTOA_ZEROPAD)) == FTOA_ZEROPAD)
  1413. for (n = fieldsz; n < width; n++)
  1414. sb.put('0');
  1415. /* the string or number proper */
  1416. n = size;
  1417. while (--n >= 0) sb.put(*t++);
  1418. /* trailing f.p. zeroes */
  1419. while (--fpprec >= 0) sb.put('0');
  1420. /* left-adjusting padding (always blank) */
  1421. if (flags & FTOA_LEFT_ADJUSTMENT)
  1422. for (n = fieldsz; n < width; n++)
  1423. sb.put(' ');
  1424. /* zero-terminate string */
  1425. sb.put(0);
  1426. /* copy result from char buffer to output array */
  1427. const char *c = sb.getBuffer();
  1428. if (c) OFStandard::strlcpy(dst, c, siz); else *dst = 0;
  1429. }
  1430. #endif /* DISABLE_OFSTD_FTOA */
  1431. OFBool OFStandard::stringMatchesCharacterSet( const char *str, const char *charset )
  1432. {
  1433. if( charset == NULL || str == NULL )
  1434. return OFTrue;
  1435. OFBool result = OFTrue;
  1436. unsigned int lenStr = strlen( str );
  1437. unsigned int lenCharset = strlen( charset );
  1438. for( unsigned int i=0 ; i<lenStr && result ; i++ )
  1439. {
  1440. OFBool charFound = OFFalse;
  1441. for( unsigned int j=0 ; j<lenCharset && !charFound ; j++ )
  1442. {
  1443. if( str[i] == charset[j] )
  1444. charFound = OFTrue;
  1445. }
  1446. if( !charFound )
  1447. result = OFFalse;
  1448. }
  1449. return( result );
  1450. }
  1451. unsigned int OFStandard::my_sleep(unsigned int seconds)
  1452. {
  1453. #ifdef HAVE_WINDOWS_H
  1454. // on Win32 we use the Sleep() system call which expects milliseconds
  1455. Sleep(1000*seconds);
  1456. return 0;
  1457. #elif defined(HAVE_SLEEP)
  1458. // just use the original sleep() system call
  1459. return sleep(seconds);
  1460. #elif defined(HAVE_USLEEP)
  1461. // usleep() expects microseconds
  1462. (void) usleep(((unsigned long)seconds)*1000000UL);
  1463. return 0;
  1464. #else
  1465. // don't know how to sleep
  1466. return 0;
  1467. #endif
  1468. }
  1469. /*
  1470. * $Log: ofstd.cc,v $
  1471. * Revision 1.34 2005/12/08 15:49:00 meichel
  1472. * Changed include path schema for all DCMTK header files
  1473. *
  1474. * Revision 1.33 2004/08/04 12:11:52 joergr
  1475. * Replaced non-Unix newline characters.
  1476. *
  1477. * Revision 1.32 2004/08/03 11:45:48 meichel
  1478. * Headers libc.h and unistd.h are now included via ofstdinc.h
  1479. *
  1480. * Revision 1.31 2004/05/26 10:14:47 meichel
  1481. * Completed isinf() workaround for MacOS X
  1482. *
  1483. * Revision 1.30 2004/05/07 11:25:38 meichel
  1484. * Added workaround for MacOS X where isinf() and isnan() are defined in <math.h>
  1485. * but not in <cmath>.
  1486. *
  1487. * Revision 1.29 2004/05/03 17:19:50 meichel
  1488. * my_isinf() now also works on systems where finite() or isinf()
  1489. * are defined but not properly declared in <math.h> or <cmath>.
  1490. *
  1491. * Revision 1.28 2004/04/30 15:52:33 meichel
  1492. * my_isinf() now also works on systems where finite() or isinf()
  1493. * are defined but not properly declared in <math.h> or <cmath>.
  1494. *
  1495. * Revision 1.27 2004/04/16 12:47:53 joergr
  1496. * Renamed local function "…

Large files files are truncated, but you can click here to view the full file