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 */ 77bstring 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 */ 99int 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 */ 121struct 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 */ 139int 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 */ 154bstring bstrListPop(struct bstrList *sl) 155{ 156 return NULL; 157} 158 159/*! 160 * @brief Inverse bjoin 161 */ 162bstring 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} 207