1 #ifndef _NSTRING_H
2 #define _NSTRING_H
3
4 #include <stdarg.h>
5 #include <string.h>
6 #include <strings.h> /* For strncasecmp */
7 #include <ctype.h>
8
9 #include "pm_c_util.h"
10 #include "pm.h" /* For PM_GNU_PRINTF_ATTR, __inline__ */
11
12 #ifdef __cplusplus
13 extern "C" {
14 #endif
15 #if 0
16 } /* to fake out automatic code indenters */
17 #endif
18
19 /* Here are string functions that respect the size of the array
20 into which you are copying -- E.g. STRSCPY truncates the source string as
21 required so that it fits, with the terminating null, in the destination
22 array.
23 */
24 #define STRSCPY(A,B) \
25 (strncpy((A), (B), sizeof(A)), *((A)+sizeof(A)-1) = '\0')
26 #define STRSCMP(A,B) \
27 (strncmp((A), (B), sizeof(A)))
28 #define STRSCAT(A,B) \
29 (strncpy(A+strlen(A), B, sizeof(A)-strlen(A)), *((A)+sizeof(A)-1) = '\0')
30 #define STRSEQ(A, B) \
31 (strneq((A), (B), sizeof(A)))
32
33 #define MEMEQ(a,b,c) (memcmp(a, b, c) == 0)
34
35 #define MEMSEQ(a,b) (memeq(a, b, sizeof(*(a))) == 0)
36
37 #define MEMSSET(a,b) (memset(a, b, sizeof(*(a))))
38
39 #define MEMSCPY(a,b) (memcpy(a, b, sizeof(*(a))))
40
41 #define MEMSZERO(a) (MEMSSET(a, 0))
42
43
44 static __inline__ int
streq(const char * const comparand,const char * const comparator)45 streq(const char * const comparand,
46 const char * const comparator) {
47
48 return strcmp(comparand, comparator) == 0;
49 }
50
51 static __inline__ int
strneq(const char * const comparand,const char * const comparator,size_t const size)52 strneq(const char * const comparand,
53 const char * const comparator,
54 size_t const size) {
55
56 return strncmp(comparand, comparator, size) == 0;
57 }
58
59 static __inline__ int
memeq(const void * const comparand,const void * const comparator,size_t const size)60 memeq(const void * const comparand,
61 const void * const comparator,
62 size_t const size) {
63
64 return memcmp(comparand, comparator, size) == 0;
65 }
66
67 /* The Standard C Library may not declare strcasecmp() if the including source
68 file doesn't request BSD functions, with _BSD_SOURCE or SUSv2 function,
69 with _XOPEN_SOURCE >= 500. So we don't define functions that use
70 strcasecmp() in that case.
71
72 (Actually, _XOPEN_SOURCE 500 is stronger than you need for strcasecmp -
73 _XOPEN_SOURCE_EXTENDED, which asks for XPG 4, would do, whereas
74 _XOPEN_SOURCE 500 asks for XPG 5, but for simplicity, we don't use
75 _XOPEN_SOURCE_EXTENDED in Netpbm.
76 */
77 #if defined(_BSD_SOURCE) || (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE - 0) >= 500)
78 static __inline__ int
strcaseeq(const char * const comparand,const char * const comparator)79 strcaseeq(const char * const comparand,
80 const char * const comparator) {
81
82 return strcasecmp(comparand, comparator) == 0;
83 }
84
85 static __inline__ int
strncaseeq(const char * const comparand,const char * const comparator,size_t const size)86 strncaseeq(const char * const comparand,
87 const char * const comparator,
88 size_t const size) {
89
90 return strncasecmp(comparand, comparator, size) == 0;
91 }
92 #endif
93
94
95 /* The standard C library routines isdigit(), for some weird
96 historical reason, does not take a character (type 'char') as its
97 argument. Instead it takes an integer. When the integer is a whole
98 number, it represents a character in the obvious way using the local
99 character set encoding. When the integer is negative, the results
100 are undefined.
101
102 Passing a character to isdigit(), which expects an integer, results in
103 isdigit() sometimes getting a negative number.
104
105 On some systems, when the integer is negative, it represents exactly
106 the character you want it to anyway (e.g. -1 is the character that is
107 encoded 0xFF). But on others, it does not.
108
109 (The same is true of other routines like isdigit()).
110
111 Therefore, we have the substitutes for isdigit() etc. that take an
112 actual character (type 'char') as an argument.
113 */
114
115 #define ISALNUM(C) (isalnum((unsigned char)(C)))
116 #define ISALPHA(C) (isalpha((unsigned char)(C)))
117 #define ISCNTRL(C) (iscntrl((unsigned char)(C)))
118 #define ISDIGIT(C) (isdigit((unsigned char)(C)))
119 #define ISGRAPH(C) (isgraph((unsigned char)(C)))
120 #define ISLOWER(C) (islower((unsigned char)(C)))
121 #define ISPRINT(C) (isprint((unsigned char)(C)))
122 #define ISPUNCT(C) (ispunct((unsigned char)(C)))
123 #define ISSPACE(C) (isspace((unsigned char)(C)))
124 #define ISUPPER(C) (isupper((unsigned char)(C)))
125 #define ISXDIGIT(C) (isxdigit((unsigned char)(C)))
126 #define TOUPPER(C) ((char)toupper((unsigned char)(C)))
127
128
129 /* These are all private versions of commonly available standard C
130 library subroutines whose names are the same except with the N at
131 the end. Because not all standard C libraries have them all,
132 Netpbm must include them in its own libraries, and because some
133 standard C libraries have some of them, Netpbm must use different
134 names for them.
135
136 The GNU C library has all of them. All but the oldest standard C libraries
137 have snprintf().
138
139 There are slight differences between the asprintf() family and that
140 found in other libraries:
141
142 - There is no return value.
143
144 - The returned string is a const char * instead of a char *. The
145 const is more correct.
146
147 - If the function can't get the memory, it returns 'pm_strsol',
148 which is a string that is in static memory that contains text
149 indicating an out of memory failure has occurred, instead of
150 NULL. This makes it much easier for programs to ignore this
151 possibility.
152
153 strfree() is strictly a Netpbm invention, to allow proper type checking
154 when freeing storage allocated by the Netpbm pm_asprintf().
155 */
156
157 extern const char * const pm_strsol;
158
159 size_t
160 pm_strnlen(const char * const s,
161 size_t const maxlen);
162
163 int
164 pm_snprintf(char * const dest,
165 size_t const str_m,
166 const char * const fmt,
167 ...) PM_GNU_PRINTF_ATTR(3,4);
168
169 void
170 pm_vsnprintf(char * const str,
171 size_t const str_m,
172 const char * const fmt,
173 va_list ap,
174 size_t * const sizeP);
175
176 const char *
177 pm_strdup(const char * const arg);
178
179 void
180 pm_asprintf(const char ** const resultP,
181 const char * const fmt,
182 ...) PM_GNU_PRINTF_ATTR(2,3);
183
184 void
185 pm_vasprintf(const char ** const resultP,
186 const char * const format,
187 va_list args);
188
189 bool
190 pm_vasprintf_knows_float(void);
191
192 void
193 pm_strfree(const char * const string);
194
195 const char *
196 pm_strsep(char ** const stringP, const char * const delim);
197
198 int
199 pm_stripeq(const char * const comparand,
200 const char * const comparator);
201
202 const void *
203 pm_memmem(const void * const haystackArg,
204 size_t const haystacklen,
205 const void * const needleArg,
206 size_t const needlelen);
207
208 bool
209 pm_strishex(const char * const subject);
210
211 void
212 pm_string_to_long(const char * const string,
213 long * const longP,
214 const char ** const errorP);
215
216 void
217 pm_string_to_int(const char * const string,
218 int * const intP,
219 const char ** const errorP);
220
221 void
222 pm_string_to_uint(const char * const string,
223 unsigned int * const uintP,
224 const char ** const errorP);
225
226 #ifdef __cplusplus
227 }
228 #endif
229
230 #endif
231