BRL-CAD
str.c
Go to the documentation of this file.
1 /* S T R . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2007-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 #include <string.h>
24 #if defined(HAVE_WORKING_STRCASECMP_FUNCTION) || defined(HAVE_WORKING_STRNCASECMP_FUNCTION)
25 #include <strings.h>
26 #endif
27 #ifdef HAVE_SYS_TYPES_H
28 # include <sys/types.h>
29 #endif
30 #include <ctype.h>
31 #include <stdio.h> /* for fprintf */
32 
33 #include "bu/debug.h"
34 #include "bu/malloc.h"
35 #include "bu/parallel.h"
36 #include "bu/str.h"
37 
38 
39 size_t
40 bu_strlcatm(char *dst, const char *src, size_t size, const char *label)
41 {
42  size_t srcsize;
43  size_t dstsize;
44 
45  if (!dst && label) {
47  fprintf(stderr, "WARNING: NULL destination string, size %lu [%s]\n", (unsigned long)size, label);
49  }
50  if (UNLIKELY(!dst || !src || size <= 0)) {
51  return 0;
52  }
53  if (!label) {
54  label = "bu_strlcat";
55  }
56 
57  dstsize = strlen(dst);
58  srcsize = strlen(src);
59 
60  if (UNLIKELY(dstsize == size - 1)) {
62  fprintf(stderr, "WARNING: [%s] concatenation string is already full at %lu chars\n", label, (unsigned long)size-1);
64  } else if (UNLIKELY(dstsize > size - 1)) {
65  /* probably missing null-termination or is not an initialized buffer */
67  fprintf(stderr, "WARNING: [%s] concatenation string is already full, exceeds size (%lu > %lu)\n", label, (unsigned long)dstsize, (unsigned long)size-1);
69  } else if (UNLIKELY(srcsize > size - dstsize - 1)) {
70  if (UNLIKELY(bu_debug)) {
72  fprintf(stderr, "WARNING: [%s] string truncation, exceeding %lu char max concatenating %lu chars (started with %lu)\n", label, (unsigned long)size-1, (unsigned long)srcsize, (unsigned long)dstsize);
74  }
75  }
76 
77 #ifdef HAVE_STRLCAT
78  /* don't return to ensure consistent null-termination behavior in following */
79  (void)strlcat(dst, src, size);
80 #else
81  (void)strncat(dst, src, size - dstsize - 1);
82 #endif
83 
84  /* be sure to null-terminate, contrary to strncat behavior */
85  if (dstsize + srcsize < size - 1) {
86  dst[dstsize + srcsize] = '\0';
87  } else {
88  dst[size-1] = '\0'; /* sanity */
89  }
90 
91  return strlen(dst);
92 }
93 
94 
95 size_t
96 bu_strlcpym(char *dst, const char *src, size_t size, const char *label)
97 {
98  size_t srcsize;
99 
100 
101  if (UNLIKELY(!dst && label)) {
103  fprintf(stderr, "WARNING: NULL destination string, size %lu [%s]\n", (unsigned long)size, label);
105  }
106  if (UNLIKELY(!dst || !src || size <= 0)) {
107  return 0;
108  }
109  if (!label) {
110  label = "bu_strlcpy";
111  }
112 
113  srcsize = strlen(src);
114 
115  if (UNLIKELY(bu_debug)) {
116  if (srcsize > size - 1) {
118  fprintf(stderr, "WARNING: [%s] string truncation, exceeding %lu char max copying %lu chars\n", label, (unsigned long)size-1, (unsigned long)srcsize);
120  }
121  }
122 
123 #ifdef HAVE_STRLCPY
124  /* don't return to ensure consistent null-termination behavior in following */
125  (void)strlcpy(dst, src, size);
126 #else
127  (void)strncpy(dst, src, size - 1);
128 #endif
129 
130  /* be sure to always null-terminate, contrary to strncpy behavior */
131  if (srcsize < size - 1) {
132  dst[srcsize] = '\0';
133  } else {
134  dst[size-1] = '\0'; /* sanity */
135  }
136 
137  return strlen(dst);
138 }
139 
140 
141 char *
142 bu_strdupm(register const char *cp, const char *label)
143 {
144  char *base;
145  size_t len;
146 
147  if (UNLIKELY(!cp && label)) {
149  fprintf(stderr, "WARNING: [%s] NULL copy buffer\n", label);
151  }
152  if (!label) {
153  label = "bu_strdup";
154  }
155 
156  len = strlen(cp)+1;
157  base = (char *)bu_malloc(len, label);
158 
161  fprintf(stderr, "%p strdup%llu \"%s\"\n", (void *)base, (unsigned long long)len, cp);
163  }
164 
165  memcpy(base, cp, len);
166  return base;
167 }
168 
169 
170 int
171 bu_strcmp(const char *string1, const char *string2)
172 {
173  const char *s1 = "";
174  const char *s2 = "";
175 
176  /* "" and NULL are considered equivalent which helps prevent
177  * strcmp() from crashing.
178  */
179 
180  if (string1)
181  s1 = string1;
182 
183  if (string2)
184  s2 = string2;
185 
186  return strcmp(s1, s2);
187 }
188 
189 
190 int
191 bu_strncmp(const char *string1, const char *string2, size_t n)
192 {
193  const char *s1 = "";
194  const char *s2 = "";
195 
196  /* "" and NULL are considered equivalent which helps prevent
197  * strncmp() from crashing.
198  */
199 
200  if (string1)
201  s1 = string1;
202 
203  if (string2)
204  s2 = string2;
205 
206  return strncmp(s1, s2, n);
207 }
208 
209 
210 int
211 bu_strcasecmp(const char *string1, const char *string2)
212 {
213  const char *s1 = "";
214  const char *s2 = "";
215 
216  /* "" and NULL are considered equal */
217 
218  if (string1)
219  s1 = string1;
220 
221  if (string2)
222  s2 = string2;
223 
224 #if defined(HAVE_WORKING_STRCASECMP_FUNCTION)
225  return strcasecmp(s1, s2);
226 #else
227  while (tolower((unsigned char)*s1) == tolower((unsigned char)*s2)) {
228  if (*s1 == '\0')
229  return 0;
230  s1++;
231  s2++;
232  }
233  return tolower((unsigned char)*s1) - tolower((unsigned char)*s2);
234 #endif
235 }
236 
237 
238 int
239 bu_strncasecmp(const char *string1, const char *string2, size_t n)
240 {
241  const char *s1 = "";
242  const char *s2 = "";
243 
244  /* "" and NULL are considered equal */
245 
246  if (string1)
247  s1 = string1;
248 
249  if (string2)
250  s2 = string2;
251 
252  if (n == 0)
253  return 0;
254 
255 #if defined(HAVE_WORKING_STRNCASECMP_FUNCTION)
256  return strncasecmp(s1, s2, n);
257 #else
258  while (tolower((unsigned char)*s1) == tolower((unsigned char)*s2)) {
259  if (--n == 0 || *s1 == '\0')
260  return 0;
261  s1++;
262  s2++;
263  }
264  return tolower((unsigned char)*s1) - tolower((unsigned char)*s2);
265 #endif
266 }
267 
268 
269 /*
270  * Local Variables:
271  * mode: C
272  * tab-width: 8
273  * indent-tabs-mode: t
274  * c-file-style: "stroustrup"
275  * End:
276  * ex: shiftwidth=4 tabstop=8
277  */
void bu_semaphore_acquire(unsigned int i)
Definition: semaphore.c:180
Header file for the BRL-CAD common definitions.
void * bu_malloc(size_t siz, const char *str)
Definition: malloc.c:314
int bu_strncmp(const char *string1, const char *string2, size_t n)
Definition: str.c:191
int bu_strncasecmp(const char *string1, const char *string2, size_t n)
Definition: str.c:239
#define BU_DEBUG_MEM_LOG
Definition: debug.h:55
void bu_semaphore_release(unsigned int i)
Definition: semaphore.c:218
int bu_strcmp(const char *string1, const char *string2)
Definition: str.c:171
int bu_debug
Definition: globals.c:87
#define BU_SEM_SYSCALL
Definition: parallel.h:178
ustring label
size_t bu_strlcpym(char *dst, const char *src, size_t size, const char *label)
Definition: str.c:96
size_t bu_strlcatm(char *dst, const char *src, size_t size, const char *label)
Definition: str.c:40
char * bu_strdupm(register const char *cp, const char *label)
Definition: str.c:142
int bu_strcasecmp(const char *string1, const char *string2)
Definition: str.c:211
#define UNLIKELY(expression)
Definition: common.h:282