This is Unofficial EPICS BASE Doxygen Site
epicsString.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie.
3 * Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne
4 * National Laboratory.
5 * Copyright (c) 2002 The Regents of the University of California, as
6 * Operator of Los Alamos National Laboratory.
7 * EPICS BASE is distributed subject to a Software License Agreement found
8 * in file LICENSE that is included with this distribution.
9 \*************************************************************************/
10 
11 /* Authors: Jun-ichi Odagiri, Marty Kraimer, Eric Norum,
12  * Mark Rivers, Andrew Johnson, Ralph Lange
13  *
14  * Routines in this file should have corresponding test code in
15  * libCom/test/epicsStringTest.c
16  */
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <errno.h>
23 #include <ctype.h>
24 
25 #include "epicsStdio.h"
26 #include "cantProceed.h"
27 #include "epicsString.h"
28 
29 /* Deprecated, use epicsStrnRawFromEscaped() instead */
30 int dbTranslateEscape(char *dst, const char *src)
31 {
32  size_t big_enough = strlen(src) + 1;
33 
34  return epicsStrnRawFromEscaped(dst, big_enough, src, big_enough);
35 }
36 
37 int epicsStrnRawFromEscaped(char *dst, size_t dstlen, const char *src,
38  size_t srclen)
39 {
40  int rem = dstlen;
41  int ndst = 0;
42 
43  while (srclen--) {
44  int c = *src++;
45  #define OUT(chr) if (--rem > 0) ndst++, *dst++ = chr
46 
47  if (!c) break;
48 
49  input:
50  if (c != '\\') {
51  OUT(c);
52  continue;
53  }
54 
55  if (!srclen-- || !(c = *src++)) break;
56 
57  switch (c) {
58  case 'a': OUT('\a'); break;
59  case 'b': OUT('\b'); break;
60  case 'f': OUT('\f'); break;
61  case 'n': OUT('\n'); break;
62  case 'r': OUT('\r'); break;
63  case 't': OUT('\t'); break;
64  case 'v': OUT('\v'); break;
65  case '\\': OUT('\\'); break;
66  case '\'': OUT('\''); break;
67  case '\"': OUT('\"'); break;
68 
69  case '0' :case '1' :case '2' :case '3' :
70  case '4' :case '5' :case '6' :case '7' :
71  { /* \ooo */
72  unsigned int u = c - '0';
73 
74  if (!srclen-- || !(c = *src++)) {
75  OUT(u); goto done;
76  }
77  if (c < '0' || c > '7') {
78  OUT(u); goto input;
79  }
80  u = u << 3 | (c - '0');
81 
82  if (!srclen-- || !(c = *src++)) {
83  OUT(u); goto done;
84  }
85  if (c < '0' || c > '7') {
86  OUT(u); goto input;
87  }
88  u = u << 3 | (c - '0');
89 
90  if (u > 0377) {
91  /* Undefined behaviour! */
92  }
93  OUT(u);
94  }
95  break;
96 
97  case 'x' :
98  { /* \xXXX... */
99  unsigned int u = 0;
100 
101  if (!srclen-- || !(c = *src++ & 0xff))
102  goto done;
103 
104  while (isxdigit(c)) {
105  u = u << 4 | ((c > '9') ? toupper(c) - 'A' + 10 : c - '0');
106  if (u > 0xff) {
107  /* Undefined behaviour! */
108  }
109  if (!srclen-- || !(c = *src++ & 0xff)) {
110  OUT(u);
111  goto done;
112  }
113  }
114  OUT(u);
115  goto input;
116  }
117 
118  default:
119  OUT(c);
120  }
121  #undef OUT
122  }
123 done:
124  if (dstlen)
125  *dst = '\0';
126  return ndst;
127 }
128 
129 int epicsStrnEscapedFromRaw(char *dst, size_t dstlen, const char *src,
130  size_t srclen)
131 {
132  int rem = dstlen;
133  int ndst = 0;
134 
135  if (dst == src)
136  return -1;
137 
138  while (srclen--) {
139  int c = *src++;
140  #define OUT(chr) ndst++; if (--rem > 0) *dst++ = chr
141 
142  switch (c) {
143  case '\a': OUT('\\'); OUT('a'); break;
144  case '\b': OUT('\\'); OUT('b'); break;
145  case '\f': OUT('\\'); OUT('f'); break;
146  case '\n': OUT('\\'); OUT('n'); break;
147  case '\r': OUT('\\'); OUT('r'); break;
148  case '\t': OUT('\\'); OUT('t'); break;
149  case '\v': OUT('\\'); OUT('v'); break;
150  case '\\': OUT('\\'); OUT('\\'); break;
151  case '\'': OUT('\\'); OUT('\''); break;
152  case '\"': OUT('\\'); OUT('\"'); break;
153  default:
154  if (isprint(c & 0xff)) {
155  OUT(c);
156  break;
157  }
158  OUT('\\');
159  OUT('0' + ((c & 0300) >> 6));
160  OUT('0' + ((c & 0070) >> 3));
161  OUT('0' + (c & 0007));
162  }
163  #undef OUT
164  }
165  if (dstlen)
166  *dst = '\0';
167  return ndst;
168 }
169 
170 size_t epicsStrnEscapedFromRawSize(const char *src, size_t srclen)
171 {
172  size_t ndst = srclen;
173 
174  while (srclen--) {
175  int c = *src++;
176 
177  switch (c) {
178  case '\a': case '\b': case '\f': case '\n':
179  case '\r': case '\t': case '\v': case '\\':
180  case '\'': case '\"':
181  ndst++;
182  break;
183  default:
184  if (!isprint(c & 0xff))
185  ndst += 3;
186  }
187  }
188  return ndst;
189 }
190 
191 int epicsStrCaseCmp(const char *s1, const char *s2)
192 {
193  while (1) {
194  int ch1 = toupper((int) *s1);
195  int ch2 = toupper((int) *s2);
196 
197  if (ch2 == 0) return (ch1 != 0);
198  if (ch1 == 0) return -1;
199  if (ch1 < ch2) return -1;
200  if (ch1 > ch2) return 1;
201  s1++;
202  s2++;
203  }
204 }
205 
206 int epicsStrnCaseCmp(const char *s1, const char *s2, size_t len)
207 {
208  size_t i = 0;
209 
210  while (i++ < len) {
211  int ch1 = toupper((int) *s1);
212  int ch2 = toupper((int) *s2);
213 
214  if (ch2 == 0) return (ch1 != 0);
215  if (ch1 == 0) return -1;
216  if (ch1 < ch2) return -1;
217  if (ch1 > ch2) return 1;
218  s1++;
219  s2++;
220  }
221  return 0;
222 }
223 
224 char * epicsStrnDup(const char *s, size_t len)
225 {
226  char *buf = mallocMustSucceed(len + 1, "epicsStrnDup");
227 
228  strncpy(buf, s, len);
229  buf[len] = '\0';
230  return buf;
231 }
232 
233 char * epicsStrDup(const char *s)
234 {
235  return strcpy(mallocMustSucceed(strlen(s)+1, "epicsStrDup"), s);
236 }
237 
238 int epicsStrPrintEscaped(FILE *fp, const char *s, size_t len)
239 {
240  int nout = 0;
241 
242  while (len--) {
243  char c = *s++;
244 
245  switch (c) {
246  case '\a': nout += fprintf(fp, "\\a"); break;
247  case '\b': nout += fprintf(fp, "\\b"); break;
248  case '\f': nout += fprintf(fp, "\\f"); break;
249  case '\n': nout += fprintf(fp, "\\n"); break;
250  case '\r': nout += fprintf(fp, "\\r"); break;
251  case '\t': nout += fprintf(fp, "\\t"); break;
252  case '\v': nout += fprintf(fp, "\\v"); break;
253  case '\\': nout += fprintf(fp, "\\\\"); break;
254  case '\'': nout += fprintf(fp, "\\'"); break;
255  case '\"': nout += fprintf(fp, "\\\""); break;
256  default:
257  if (isprint(0xff & (int)c))
258  nout += fprintf(fp, "%c", c);
259  else
260  nout += fprintf(fp, "\\%03o", (unsigned char)c);
261  break;
262  }
263  }
264  return nout;
265 }
266 
267 /* Until Base requires POSIX 2008 we must provide our own implementation */
268 size_t epicsStrnLen(const char *s, size_t maxlen)
269 {
270  size_t i;
271 
272  for (i=0; i<maxlen; i++) {
273  if(s[i]=='\0')
274  return i;
275  }
276  return i;
277 }
278 
279 int epicsStrGlobMatch(const char *str, const char *pattern)
280 {
281  const char *cp = NULL, *mp = NULL;
282 
283  while ((*str) && (*pattern != '*')) {
284  if ((*pattern != *str) && (*pattern != '?'))
285  return 0;
286  pattern++;
287  str++;
288  }
289  while (*str) {
290  if (*pattern == '*') {
291  if (!*++pattern)
292  return 1;
293  mp = pattern;
294  cp = str+1;
295  }
296  else if ((*pattern == *str) || (*pattern == '?')) {
297  pattern++;
298  str++;
299  }
300  else {
301  pattern = mp;
302  str = cp++;
303  }
304  }
305  while (*pattern == '*')
306  pattern++;
307  return !*pattern;
308 }
309 
310 char * epicsStrtok_r(char *s, const char *delim, char **lasts)
311 {
312  const char *spanp;
313  int c, sc;
314  char *tok;
315 
316  if (s == NULL && (s = *lasts) == NULL)
317  return NULL;
318 
319  /*
320  * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
321  */
322 cont:
323  c = *s++;
324  for (spanp = delim; (sc = *spanp++) != 0;) {
325  if (c == sc)
326  goto cont;
327  }
328 
329  if (c == 0) { /* no non-delimiter characters */
330  *lasts = NULL;
331  return NULL;
332  }
333  tok = s - 1;
334 
335  /*
336  * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
337  * Note that delim must have one NUL; we stop if we see that, too.
338  */
339  for (;;) {
340  c = *s++;
341  spanp = delim;
342  do {
343  if ((sc = *spanp++) == c) {
344  if (c == 0)
345  s = NULL;
346  else
347  s[-1] = 0;
348  *lasts = s;
349  return tok;
350  }
351  } while (sc != 0);
352  }
353 }
354 
355 
356 unsigned int epicsStrHash(const char *str, unsigned int seed)
357 {
358  unsigned int hash = seed;
359  char c;
360 
361  while ((c = *str++)) {
362  hash ^= ~((hash << 11) ^ c ^ (hash >> 5));
363  if (!(c = *str++)) break;
364  hash ^= (hash << 7) ^ c ^ (hash >> 3);
365  }
366  return hash;
367 }
368 
369 unsigned int epicsMemHash(const char *str, size_t length, unsigned int seed)
370 {
371  unsigned int hash = seed;
372 
373  while (length--) {
374  hash ^= ~((hash << 11) ^ *str++ ^ (hash >> 5));
375  if (!length--) break;
376  hash ^= (hash << 7) ^ *str++ ^ (hash >> 3);
377  }
378  return hash;
379 }
unsigned int epicsStrHash(const char *str, unsigned int seed)
Definition: epicsString.c:356
size_t epicsStrnEscapedFromRawSize(const char *src, size_t srclen)
Definition: epicsString.c:170
int i
Definition: scan.c:967
int epicsStrGlobMatch(const char *str, const char *pattern)
Definition: epicsString.c:279
#define NULL
Definition: catime.c:38
#define str(v)
int epicsStrCaseCmp(const char *s1, const char *s2)
Definition: epicsString.c:191
int dbTranslateEscape(char *dst, const char *src)
Definition: epicsString.c:30
char * epicsStrtok_r(char *s, const char *delim, char **lasts)
Definition: epicsString.c:310
int epicsStrPrintEscaped(FILE *fp, const char *s, size_t len)
Definition: epicsString.c:238
char * epicsStrnDup(const char *s, size_t len)
Definition: epicsString.c:224
char * epicsStrDup(const char *s)
Definition: epicsString.c:233
size_t epicsStrnLen(const char *s, size_t maxlen)
Definition: epicsString.c:268
LIBCOM_API void * mallocMustSucceed(size_t size, const char *msg)
A malloc() that never returns NULL.
Definition: cantProceed.c:38
int epicsStrnCaseCmp(const char *s1, const char *s2, size_t len)
Definition: epicsString.c:206
void done(int k)
Definition: antelope.c:77
unsigned int epicsMemHash(const char *str, size_t length, unsigned int seed)
Definition: epicsString.c:369
Routines for code that can&#39;t continue or return after an error.
int epicsStrnEscapedFromRaw(char *dst, size_t dstlen, const char *src, size_t srclen)
Definition: epicsString.c:129
int epicsStrnRawFromEscaped(char *dst, size_t dstlen, const char *src, size_t srclen)
Definition: epicsString.c:37
#define OUT(chr)