]> arthur.barton.de Git - netatalk.git/blob - libatalk/bstring/bstradd.c
Add vasprintf compatibility function
[netatalk.git] / libatalk / bstring / bstradd.c
1 /*
2   Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
3
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 2 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13 */
14
15 /*!
16  * @file
17  * Additional functions for bstrlib
18  */
19
20 #include <stdio.h>
21 #include <stddef.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26
27 #include <atalk/bstrlib.h>
28
29 /* Optionally include a mechanism for debugging memory */
30
31 #if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG)
32 #include "memdbg.h"
33 #endif
34
35 #ifndef bstr__alloc
36 #define bstr__alloc(x) malloc (x)
37 #endif
38
39 #ifndef bstr__free
40 #define bstr__free(p) free (p)
41 #endif
42
43 #ifndef bstr__realloc
44 #define bstr__realloc(p,x) realloc ((p), (x))
45 #endif
46
47 #ifndef bstr__memcpy
48 #define bstr__memcpy(d,s,l) memcpy ((d), (s), (l))
49 #endif
50
51 #ifndef bstr__memmove
52 #define bstr__memmove(d,s,l) memmove ((d), (s), (l))
53 #endif
54
55 #ifndef bstr__memset
56 #define bstr__memset(d,c,l) memset ((d), (c), (l))
57 #endif
58
59 #ifndef bstr__memcmp
60 #define bstr__memcmp(d,c,l) memcmp ((d), (c), (l))
61 #endif
62
63 #ifndef bstr__memchr
64 #define bstr__memchr(s,c,l) memchr ((s), (c), (l))
65 #endif
66
67 /*************************************************************************
68  * Stuff for making bstrings referencing c-strings
69  ************************************************************************/
70
71 /*!
72  * @brief Create a bstring referencing "str"
73  *
74  * This is usefull if a well know code path uses string, often doing strlen on string.
75  * By converting to bstring which carries the strlen, the repeated computation can be avoided.
76  */
77 bstring brefcstr (char *str) {
78     bstring b;
79     size_t j;
80
81         if (str == NULL)
82         return NULL;
83         j = strlen(str);
84
85         b = (bstring)bstr__alloc(sizeof(struct tagbstring));
86         if (NULL == b)
87         return NULL;
88
89         b->slen = (int) j;
90     b->mlen = -1;
91     b->data = (unsigned char *)str;
92
93         return b;
94 }
95
96 /*!
97  * @brief Free up the bstring, WITHOUT freeing the pointed to c-string!
98  */
99 int bunrefcstr (bstring b) {
100         if (b == NULL || b->slen < 0 || b->mlen > 0 || b->data == NULL)
101                 return BSTR_ERR;
102
103         /* In case there is any stale usage, there is one more chance to 
104            notice this error. */
105
106         b->slen = -1;
107         b->mlen = -__LINE__;
108         b->data = NULL;
109
110         bstr__free (b);
111         return BSTR_OK;
112 }
113
114 /*************************************************************************
115  * stuff for bstrList
116  ************************************************************************/
117
118 /*!
119  * @brief Create an empty list with preallocated storage for at least 'min' members
120  */
121 struct bstrList *bstrListCreateMin(int min)
122 {
123     struct bstrList *sl = NULL;
124
125     if ((sl = bstrListCreate()) == NULL)
126         return NULL;
127
128     if ((bstrListAlloc(sl, min)) != BSTR_OK) {
129         bstrListDestroy(sl);
130         return NULL;
131     }
132
133     return sl;
134 }
135
136 /*!
137  * @brief Push a bstring to the end of a list
138  */
139 int bstrListPush(struct bstrList *sl, bstring bs)
140 {
141     if (sl->qty == sl->mlen) {
142         if ((bstrListAlloc(sl, sl->qty + 1)) != BSTR_OK)
143             return BSTR_ERR;
144     }
145
146     sl->entry[sl->qty] = bs;
147     sl->qty++;
148     return BSTR_OK;
149 }
150
151 /*!
152  * @brief Pop a bstring from the end of a list
153  */
154 bstring bstrListPop(struct bstrList *sl)
155 {
156     return NULL;
157 }
158
159 /*!
160  * @brief Inverse bjoin
161  */
162 bstring bjoinInv(const struct bstrList * bl, const_bstring sep) {
163     bstring b;
164     int i, j, c, v;
165
166     if (bl == NULL || bl->qty < 0)
167         return NULL;
168     if (sep != NULL && (sep->slen < 0 || sep->data == NULL))
169         return NULL;
170
171     for (i = 0, c = 1; i < bl->qty; i++) {
172         v = bl->entry[i]->slen;
173         if (v < 0)
174             return NULL;/* Invalid input */
175         c += v;
176         if (c < 0)
177             return NULL;/* Wrap around ?? */
178     }
179
180     if (sep != NULL)
181         c += (bl->qty - 1) * sep->slen;
182
183     b = (bstring) bstr__alloc (sizeof (struct tagbstring));
184     if (NULL == b)
185         return NULL; /* Out of memory */
186     b->data = (unsigned char *) bstr__alloc (c);
187     if (b->data == NULL) {
188         bstr__free (b);
189         return NULL;
190     }
191
192     b->mlen = c;
193     b->slen = c-1;
194
195     for (i = bl->qty - 1, c = 0, j = 0; i >= 0; i--, j++) {
196         if (j > 0 && sep != NULL) {
197             bstr__memcpy (b->data + c, sep->data, sep->slen);
198             c += sep->slen;
199         }
200         v = bl->entry[i]->slen;
201         bstr__memcpy (b->data + c, bl->entry[i]->data, v);
202         c += v;
203     }
204     b->data[c] = (unsigned char) '\0';
205     return b;
206 }