1 /*
2   memory and string operations and some more common stuff
3 
4   Copyright (C) 2000-2002 David Necas (Yeti) <yeti@physics.muni.cz>
5 
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of version 2 of the GNU General Public License as published
8   by the Free Software Foundation.
9 
10   This program is distributed in the hope that it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13   more details.
14 
15   You should have received a copy of the GNU General Public License along
16   with this program; if not, write to the Free Software Foundation, Inc.,
17   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
18 */
19 #ifdef HAVE_CONFIG_H
20 #  include "config.h"
21 #endif /* HAVE_CONFIG_H */
22 
23 #include <stdarg.h>
24 
25 #include "enca.h"
26 #include "internal.h"
27 
28 /**
29  * enca_malloc:
30  * @size: The number of bytes to allocate.
31  *
32  * Allocates memory, always successfully (when fails, aborts program).
33  *
34  * Returns: Pointer to the newly allocated memory.
35  **/
36 void*
enca_malloc(size_t size)37 enca_malloc(size_t size)
38 {
39   void *ptr;
40 
41   if (size == 0)
42     size = 1;
43   ptr = malloc(size);
44   assert(ptr != NULL);
45 
46   return ptr;
47 }
48 
49 /**
50  * enca_realloc:
51  * @ptr: Pointer to block of previously allocated memory.
52  * @size: The number of bytes to resize the block.
53  *
54  * Reallocates memory, always successfully (when fails, aborts program).
55  *
56  * Returns: Pointer to the newly allocated memory, #NULL when @size is zero.
57  **/
58 void*
enca_realloc(void * ptr,size_t size)59 enca_realloc(void *ptr, size_t size)
60 {
61   if (size == 0) {
62     free(ptr);
63     return NULL;
64   }
65 
66   ptr = realloc(ptr, size);
67   assert(ptr != NULL);
68 
69   return ptr;
70 }
71 
72 /**
73  * enca_strdup:
74  * @s: A string.
75  *
76  * Duplicates string.
77  *
78  * Will be defined as strdup() when system provides it.
79  *
80  * Returns: The newly allocated string copy.
81  **/
82 char*
enca_strdup(const char * s)83 enca_strdup(const char *s) {
84   if (s == NULL)
85     return NULL;
86   else
87     return strcpy(enca_malloc(strlen(s) + 1), s);
88 }
89 
90 #ifndef HAVE_STRSTR
91 /**
92  * enca_strstr:
93  * @haystack: A string where to search.
94  * @needle: A string to find.
95  *
96  * Finds occurence of a substring in a string.
97  *
98  * Will be defined as strstr() when system provides it.
99  *
100  * Returns: Pointer to the first occurence of @needle in @haystack; #NULL if
101  *          not found.
102  **/
103 const char*
enca_strstr(const char * haystack,const char * needle)104 enca_strstr(const char *haystack,
105             const char *needle)
106 {
107   char c;
108   size_t n;
109 
110   /* handle singularities */
111   if (needle == NULL)
112     return haystack;
113   if ((n = strlen(needle)) == 0)
114     return haystack;
115 
116   /* search */
117   c = needle[0];
118   while ((haystack = strchr(haystack, c)) != NULL) {
119     if (strncmp(haystack, needle, n) == 0)
120       return haystack;
121   }
122 
123   return NULL;
124 }
125 #endif
126 
127 #ifndef HAVE_STPCPY
128 /**
129  * enca_stpcpy:
130  * @dest: A string.
131  * @src: A string to append.
132  *
133  * Appends a string to the end of another strings, returning pointer to
134  * the terminating zero byte.
135  *
136  * Will be defined as stpcpy() when system provides it.
137  *
138  * Caller is responisble for providing @dest long enough to hold the result.
139  *
140  * Returns: Pointer to the terminating zero byte of resulting string.
141  **/
142 char*
enca_stpcpy(char * dest,const char * src)143 enca_stpcpy(char *dest,
144             const char *src)
145 {
146   const char *p = src;
147 
148   if (src == NULL)
149     return dest;
150 
151   while (*p != '\0')
152     *dest++ = *p++;
153 
154   *dest = '\0';
155   return dest;
156 }
157 #endif
158 
159 /**
160  * enca_strconcat:
161  * @str: A string.
162  * @...: A #NULL-terminated list of string to append.
163  *
164  * Concatenates arbitrary (but at least one) number of strings.
165  *
166  * Returns: All the strings concatenated together.
167  **/
168 char*
enca_strconcat(const char * str,...)169 enca_strconcat(const char *str,
170                ...)
171 {
172   va_list ap;
173   char *result = NULL;
174   size_t n;
175   const char *s;
176   char *r;
177 
178   /* compute size of resulting string */
179   n = 1;
180   va_start(ap, str);
181   for (s = str; s != NULL; s = va_arg(ap, const char*))
182     n += strlen(s);
183   va_end(ap);
184 
185   /* and construct it using the smart stpcpy() function */
186   r = result = (char*)enca_malloc(n);
187   va_start(ap, str);
188   for (s = str; s != NULL; s = va_arg(ap, const char*))
189     r = enca_stpcpy(r, s);
190   va_end(ap);
191 
192   return result;
193 }
194 
195 /**
196  * enca_strappend:
197  * @str: A string.
198  * @...: A #NULL-terminated list of string to append.
199  *
200  * Appends arbitrary number of strings to a string.
201  *
202  * The string @str is destroyed (reallocated), the others are kept.
203  *
204  * Returns: All the strings concatenated together.
205  **/
206 char*
enca_strappend(char * str,...)207 enca_strappend(char *str,
208                ...)
209 {
210   va_list ap;
211   size_t n, n1;
212   const char *s;
213   char *r;
214 
215   /* compute size of resulting string */
216   n1 = strlen(str);
217   n = 1 + n1;
218   va_start(ap, str);
219   for (s = va_arg(ap, const char*); s != NULL; s = va_arg(ap, const char*))
220     n += strlen(s);
221   va_end(ap);
222 
223   /* and construct it using the smart stpcpy() function */
224   str = (char*)enca_realloc(str, n);
225   r = str + n1;
226   va_start(ap, str);
227   for (s = va_arg(ap, const char*); s != NULL; s = va_arg(ap, const char*))
228     r = enca_stpcpy(r, s);
229   va_end(ap);
230 
231   return str;
232 }
233 
234 /* vim: ts=2
235  */
236