1 /*
2  *
3  *  Copyright (C) 2000-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  *  Module:  ofstd
19  *
20  *  Author:  Joerg Riesmeier, Marco Eichelberg
21  *
22  *  Purpose: Class for various helper functions
23  *
24  */
25 
26 
27 #ifndef __OFSTD_H
28 #define __OFSTD_H
29 
30 #include "osconfig.h"
31 #include "ofstring.h"   /* for class OFString */
32 
33 #define INCLUDE_CSTRING
34 #define INCLUDE_CSTDIO
35 #include "ofstdinc.h"
36 
37 BEGIN_EXTERN_C
38 #ifdef HAVE_SYS_TYPES_H
39 #include <sys/types.h>  /* for size_t */
40 #endif
41 END_EXTERN_C
42 
43 
44 /*---------------------*
45  *  class declaration  *
46  *---------------------*/
47 
48 /** A class for various helper functions.
49  *  This class is used to comprise a number of "global" helper functions.
50  */
51 class OFStandard
52 {
53  public:
54 
55     // --- string functions ---
56 
57     /** This function copies up to size - 1 characters from the NUL-
58      *  terminated string src to dst, NUL-terminating the result. It is
59      *  designed to be a safer, more consistent, and less error-prone
60      *  replacement for strncpy(3). strlcpy takes the full size of the
61      *  buffer (not just the length) and guarantees to NUL-terminate the
62      *  result (as long as size is larger than 0). Note that you should
63      *  include a byte for the NUL in size. Also note that strlcpy only
64      *  operates on true C strings, i. e. src must be NUL-terminated.
65      *  @param dst destination buffer of size siz, must not be NULL
66      *  @param src source string, must not be NULL
67      *  @param siz size of destination buffer
68      *  @return the total length of the string the function tried to
69      *    create, i.e. strlen(src).  While this may seem somewhat
70      *    confusing it was done to make truncation detection simple.
71      */
strlcpy(char * dst,const char * src,size_t siz)72     static inline size_t strlcpy(char *dst, const char *src, size_t siz)
73     {
74 #ifdef HAVE_STRLCPY
75       return ::strlcpy(dst, src, siz);
76 #else
77       return my_strlcpy(dst, src, siz);
78 #endif
79     }
80 
81     /** This function appends the NUL-terminated string src to the end of
82      *  dst. It will append at most size - strlen(dst) - 1 bytes, NUL-
83      *  terminating the result. It is designed to be a safer, more
84      *  consistent, and less error-prone replacement for strncat(3).
85      *  strlcat takes the full size of the buffer (not just the length) and
86      *  guarantees to NUL-terminate the result (as long as size is larger
87      *  than 0). Note that you should include a byte for the NUL in size.
88      *  Also note that strlcat only operates on true C strings, i. e. dst
89      *  and src must be NUL-terminated.
90      *  @param dst destination buffer of size siz, must not be NULL
91      *  @param src source string, must not be NULL
92      *  @param siz size of destination buffer
93      *  @return the total length of the string the function tried to
94      *    create, i.e. the initial length of dst plus the length of src.
95      *    While this may seem somewhat confusing it was done to make
96      *    truncation detection simple.
97      */
strlcat(char * dst,const char * src,size_t siz)98     static inline size_t strlcat(char *dst, const char *src, size_t siz)
99     {
100 #ifdef HAVE_STRLCAT
101       return ::strlcat(dst, src, siz);
102 #else
103       return my_strlcat(dst, src, siz);
104 #endif
105     }
106 
107     // --- file system functions ---
108 
109     /** check whether the given path exists.
110      *  This function does not distinguish files from directories (use 'fileExists()'
111      *  or 'directoryExists()' if required).
112      *  @param pathName name of the path to be checked
113      *  @return OFTrue if path exists, OFFalse otherwise
114      */
115     static OFBool pathExists(const OFString &pathName);
116 
117     /** check whether the given file exists.
118      *  This function also checks that the specified path points to file and not to
119      *  a directory (or the like).
120      *  @param fileName name of the file to be checked
121      *  @return OFTrue if file exists, OFFalse otherwise
122      */
123     static OFBool fileExists(const OFString &fileName);
124 
125     /** check whether the given directory exists.
126      *  This function also checks that the specified path points to directory and
127      *  not to a file (or the like).
128      *  @param dirName name of the directory to be checked
129      *  @return OFTrue if directory exists, OFFalse otherwise
130      */
131     static OFBool dirExists(const OFString &dirName);
132 
133     /** check whether the given path is readable.
134      *  This function works for both files and directories.
135      *  @param pathName name of the path to be checked
136      *  @return OFTrue if path is readable, OFFalse otherwise
137      */
138     static OFBool isReadable(const OFString &pathName);
139 
140     /** check whether the given path is writeable.
141      *  This function works for both files and directories.
142      *  @param pathName name of the path to be checked
143      *  @return OFTrue if path is writeable, OFFalse otherwise
144      */
145     static OFBool isWriteable(const OFString &pathName);
146 
147     /** normalize the given directory name.
148      *  Removes trailing path separators from the directory name. If the resulting
149      *  directory name is an empty string and the flag 'allowEmptyDirName' is OFFalse
150      *  the directory name is to "." (current directory).
151      *  @param result string variable in which the resulting directory name is stored
152      *  @param dirName directory name to be normalized
153      *  @param allowEmptyDirName flag indicating whether an empty directory name is allowed
154      *  @return reference to the resulting directory name (same as 'result')
155      */
156     static OFString &normalizeDirName(OFString &result,
157                                       const OFString &dirName,
158                                       const OFBool allowEmptyDirName = OFFalse);
159 
160     /** combine the given directory and file name.
161      *  Normalizes the directory name and appends the file name (with a path separator)
162      *  if not empty. If both 'dirName' and 'fileName' are empty strings and the flag
163      *  'allowEmptyDirName' is OFFalse the resulting path name is set "." (current
164      *  directory).
165      *  NB: This function neither checks whether the given 'dirName' exists nor whether
166      *      the resulting path name points to a valid or existing file name.
167      *  @param result string variable in which the resulting path name is stored
168      *  @param dirName directory name to be combined with the file name
169      *  @param fileName file name to be combined with the directory name
170      *  @param allowEmptyDirName flag indicating whether an empty directory name is allowed
171      *  @return reference to the resulting path name (same as 'result')
172      */
173     static OFString &combineDirAndFilename(OFString &result,
174                                            const OFString &dirName,
175                                            const OFString &fileName,
176                                            const OFBool allowEmptyDirName = OFFalse);
177 
178     // --- other functions ---
179 
180     /** convert character string to HTML/XML mnenonic string.
181      *  Characters with special meaning for HTML/XML (e.g. '<' and '&') are replace by the
182      *  corresponding mnenonics (e.g. "&lt;" and "&amp;").  If flag 'convertNonASCII' is OFTrue
183      *  all characters > #127 are also converted (useful if only HTML 3.2 is supported which does
184      *  not allow to specify the character set).
185      ** @param sourceString source string to be converted
186      *  @param markupString reference to character string where the result should be stored
187      *  @param convertNonASCII convert non-ASCII characters (> #127) to numeric value (&#nnn;)
188      *    if OFTrue
189      *  @param xmlMode convert to XML markup string if OFTrue, HTML string otherwise.
190      *    Newlines are always encoded as "&#182;" in XML mode, the flag 'newlineAllowed' has no
191      *    meaning in this case.
192      *  @param newlineAllowed optional flag indicating whether newlines are allowed or not.
193      *    If they are allowed the text "<br>" is used, "&para;" otherwise. The following
194      *    combinations are accepted: LF, CR, LF CR, CF LF.
195      ** @return reference to resulting 'markupString' (might be empty if 'sourceString' was empty)
196      */
197     static const OFString &convertToMarkupString(const OFString &sourceString,
198                                                  OFString &markupString,
199                                                  const OFBool convertNonASCII = OFFalse,
200                                                  const OFBool xmlMode = OFTrue,
201                                                  const OFBool newlineAllowed = OFFalse);
202 
203     /** encode binary data according to "Base64" as described in RFC 2045 (MIME).
204      *  Basic algorithm: groups of 3 bytes from the binary input are coded as groups of 4 bytes in
205      *  the textual output.  The input data is 'padded' with zeros to create a length that is an
206      *  even multiple of 3.  A special character ('=') is used to denote padding so that the output
207      *  can be decoded back to its exact size.
208      *  If the input data is NULL an empty string is returned.
209      ** @param data buffer with binary data to be encoded (big endian required!)
210      *  @param length length of the input data buffer (in bytes)
211      *  @param result reference to resulting string variable (Base64 encoded)
212      *  @param width maximum number of characters per line in the output string
213      *    (default: 0 = no line breaks, typical for MIME = 72)
214      ** @return reference to the resulting string
215      */
216     static const OFString &encodeBase64(const unsigned char *data,
217                                         const size_t length,
218                                         OFString &result,
219                                         const size_t width = 0);
220 
221     /** decode "Base64" encoded string.
222      *  Any character that does not belong to the Base64 alphabet (0..9, A..Z, a..z, + and /) is
223      *  ignored when decoding the input string.  This is especially true for line breaks which are
224      *  usually contained in MIME (RFC 2045) encoded streams (see above).  The first occurrence of
225      *  a '=' character is taken as evidence that the end of the data has been reached.
226      *  NB: The memory buffer in which the binary output is stored is allocated inside this function
227      *      and has to to be freed (using "delete[]") by the caller!  Do not pass a pointer to an
228      *      already allocated buffer to this function, the caller does not know the exact size anyway.
229      ** @param data Base64 encoded input data (possibly padded with '=' at the end)
230      *  @param result receives pointer to resulting buffer with binary data (big endian encoded)
231      ** @return length of the resulting binary data (0 if an error occurred, in this case the buffer
232      *    is deleted internally)
233      */
234     static size_t decodeBase64(const OFString &data,
235                                unsigned char *&result);
236 
237     /** converts a floating-point number from an ASCII
238      *  decimal representation to internal double-precision format.
239      *  Unlike the std::stod() function defined in Posix, this implementation
240      *  is not affected by a locale setting, the radix character is always
241      *  assumed to be '.'
242      *  This implementation does not set errno if the input cannot be parsed
243      *  and it does not implement special handling for overflow/underflow
244      *  or NaN values.  However, a return code indicates whether or not
245      *  a successful conversion could be performed.
246      *  The precision of this implementation is limited to approx. 9
247      *  decimal digits.
248      *  The use of this implementation can be disabled by defining
249      *  the macro DISABLE_OFSTD_ATOF at compile time; in this case,
250      *  the locale dependent Posix implementation of sscanf is used and
251      *  the application is responsible for making sure that the Posix locale
252      *  is activated at all times.
253      *
254      *  @param s
255      *    A decimal ASCII floating-point number, optionally preceded by white
256      *    space. Must have form "-I.FE-X", where I is the integer part of the
257      *    mantissa, F is the fractional part of the mantissa, and X is the
258      *    exponent.  Either of the signs may be "+", "-", or omitted.  Either I
259      *    or F may be omitted, or both.  The decimal point isn't necessary
260      *    unless F is present. The "E" may actually be an "e".  E and X may both
261      *    be omitted (but not just one).
262      *  @param success pointer to return status code, may be NULL.
263      *    if present, a status code is stored in the variable pointed to by this
264      *    parameter.  The status is OFTrue if a conversion could be performed
265      *    and OFFalse if the string does not have the expected format.
266      *  @return
267      *    floating-point equivalent of string.
268      *    If a terminating character is found before any floating-point
269      *    digits, then zero is returned.
270      */
271      static double atof(const char *s,
272                         OFBool *success = NULL);
273 
274      /** formats a floating-point number into an ASCII string.
275       *  This function works similar to sprintf(), except that this
276       *  implementation is not affected by a locale setting.
277       *  The radix character is always '.'.
278       *
279       *  This implementation guarantees that the given string size
280       *  is always respected by using strlcpy to copy the formatted
281       *  string into the target buffer.
282       *
283       *  The use of this implementation can be disabled by defining
284       *  the macro DISABLE_OFSTD_FTOA at compile time; in this case,
285       *  the locale dependent Posix implementation of sprintf is used and
286       *  the application is responsible for making sure that the Posix locale
287       *  is activated at all times.
288       *
289       *  @param target pointer to target string buffer
290       *  @param siz size of target string buffer
291       *  @param val double value to be formatted
292       *  @param flags processing flags. Any of the flags defined below
293       *    can be combined by bit-wise or.
294       *  @param width width from format (%8d), or 0
295       *  @param precision precision from format (%.3d), or -1
296       */
297      static void ftoa(char *target,
298                       size_t targetSize,
299                       double value,
300                       unsigned int flags = 0,
301                       int width = 0,
302                       int precision = -1);
303 
304      /** @name ftoa() processing flags.
305       *  These flags can be combined by bit-wise or.
306       */
307      //@{
308 
309      /// Use %e or %E conversion format instead of %g or %G
310      static const unsigned int ftoa_format_e;
311 
312      /// Use %f or %F conversion format instead of %g or %G
313      static const unsigned int ftoa_format_f;
314 
315      /// Use %E, %F or %G conversion format instead of %e, %f or %g
316      static const unsigned int ftoa_uppercase;
317 
318      /** convert value to alternate form. The result will always contain
319       *  a decimal point, even if no digits follow the point. For g and G
320       *  conversions, trailing zeroes will not be removed from the result.
321       */
322      static const unsigned int ftoa_alternate;
323 
324      /// left-justify number be within the field
325      static const unsigned int ftoa_leftadj;
326 
327      /// pad with zeroes instead of blanks
328      static const unsigned int ftoa_zeropad;
329 
330      //@}
331 
332     /** Checks if a given string consists only of characters which are specified in a
333      *  given charset. Note that in case one of the parameters equals NULL, OFTrue will
334      *  be returned.
335      *  @param str String which shall be checked.
336      *  @param charset Possible character set for s.
337      *  @return OFTrue if the given string consists only of characters which are specified
338      *    in the given charset; OFFalse otherwise.
339      */
340      static OFBool stringMatchesCharacterSet( const char *str, const char *charset );
341 
342  private:
343 
344     /** private implementation of strlcpy. Called when strlcpy
345      *  is not available in the standard library.
346      *  @param dst destination buffer of size siz, must not be NULL
347      *  @param src source string, must not be NULL
348      *  @param siz size of destination buffer
349      *  @return the total length of the string the function tried to
350      *    create, i.e. strlen(src).
351      */
352     static size_t my_strlcpy(char *dst, const char *src, size_t siz);
353 
354     /** private implementation of strlcat. Called when strlcat
355      *  is not available in the standard library.
356      *  @param dst destination buffer of size siz, must not be NULL
357      *  @param src source string, must not be NULL
358      *  @param siz size of destination buffer
359      *  @return the total length of the string the function tried to
360      *    create, i.e. the initial length of dst plus the length of src.
361      */
362     static size_t my_strlcat(char *dst, const char *src, size_t siz);
363 };
364 
365 
366 #endif
367