Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2004-2015 Frediano Ziglio
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Library General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2 of the License, or (at your option) any later version.
8 : *
9 : * This library 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 GNU
12 : * Library General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Library General Public
15 : * License along with this library; if not, write to the
16 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 : * Boston, MA 02111-1307, USA.
18 : */
19 :
20 : #include <config.h>
21 :
22 : #include <stdarg.h>
23 : #include <stdio.h>
24 : #include <assert.h>
25 :
26 : #if HAVE_STDLIB_H
27 : #include <stdlib.h>
28 : #endif /* HAVE_STDLIB_H */
29 :
30 : #if HAVE_STRING_H
31 : #include <string.h>
32 : #endif /* HAVE_STRING_H */
33 :
34 : #include <freetds/utils/string.h>
35 :
36 :
37 : /**
38 : * \ingroup libtds
39 : * \defgroup dstring Dynamic string functions
40 : * Handle dynamic string. In this string are always valid
41 : * (you don't have NULL pointer, only empty strings)
42 : */
43 :
44 : /* This is in a separate module because we use the pointer to discriminate allocated and not allocated */
45 : const struct tds_dstr tds_str_empty = { 0, "" };
46 : #define EMPTY ((struct tds_dstr*) &tds_str_empty)
47 :
48 : /**
49 : * \addtogroup dstring
50 : * @{
51 : */
52 :
53 : /** clear all string filling with zeroes (mainly for security reason) */
54 : void
55 16288 : tds_dstr_zero(DSTR * s)
56 : {
57 16288 : memset((*s)->dstr_s, 0, (*s)->dstr_size);
58 16288 : }
59 :
60 : /** free string */
61 : void
62 649980 : tds_dstr_free(DSTR * s)
63 : {
64 649980 : if (*s != EMPTY)
65 179986 : free(*s);
66 649980 : *s = EMPTY;
67 649980 : }
68 :
69 : /**
70 : * Set string to a given buffer of characters
71 : * @param s dynamic string
72 : * @param src source buffer
73 : * @param length length of source buffer
74 : * @return string copied or NULL on memory error
75 : */
76 : DSTR*
77 112443 : tds_dstr_copyn(DSTR * s, const char *src, size_t length)
78 : {
79 112443 : if (!length) {
80 14870 : if (*s != EMPTY) {
81 1454 : free(*s);
82 1454 : *s = EMPTY;
83 : }
84 : } else {
85 97573 : struct tds_dstr *p = (struct tds_dstr *) malloc(length + TDS_OFFSET(struct tds_dstr, dstr_s) + 1);
86 97573 : if (TDS_UNLIKELY(!p))
87 : return NULL;
88 97573 : memcpy(p->dstr_s, src, length);
89 97573 : p->dstr_s[length] = 0;
90 97573 : p->dstr_size = length;
91 97573 : if (*s != EMPTY)
92 17085 : free(*s);
93 97573 : *s = p;
94 : }
95 : return s;
96 : }
97 :
98 : /**
99 : * set a string from another buffer.
100 : * The string will use the supplied buffer (it not copy the string),
101 : * so it should be a pointer returned by malloc.
102 : * @param s dynamic string
103 : * @param src source buffer
104 : * @return string copied or NULL on memory error
105 : */
106 : DSTR*
107 13249 : tds_dstr_set(DSTR * s, char *src)
108 : {
109 13249 : DSTR *res = tds_dstr_copy(s, src);
110 13249 : if (TDS_LIKELY(res != NULL))
111 13249 : free(src);
112 13249 : return res;
113 : }
114 :
115 : /**
116 : * copy a string from another
117 : * @param s dynamic string
118 : * @param src source buffer
119 : * @return string copied or NULL on memory error
120 : */
121 : DSTR*
122 38507 : tds_dstr_copy(DSTR * s, const char *src)
123 : {
124 51756 : return tds_dstr_copyn(s, src, strlen(src));
125 : }
126 :
127 : /**
128 : * Duplicate a string from another dynamic string
129 : * @param s output string
130 : * @param src source string to copy
131 : * @return string copied or NULL on memory error
132 : */
133 : DSTR*
134 59260 : tds_dstr_dup(DSTR * s, const DSTR * src)
135 : {
136 59260 : return tds_dstr_copyn(s, (*src)->dstr_s, (*src)->dstr_size);
137 : }
138 :
139 : /**
140 : * limit length of string, MUST be <= current length
141 : * @param s dynamic string
142 : * @param length new length
143 : */
144 : DSTR*
145 138599 : tds_dstr_setlen(DSTR *s, size_t length)
146 : {
147 : #if ENABLE_EXTRA_CHECKS
148 138599 : assert((*s)->dstr_size >= length);
149 : #endif
150 : /* test required for empty strings */
151 138599 : if ((*s)->dstr_size >= length && *s != EMPTY) {
152 138599 : (*s)->dstr_size = length;
153 138599 : (*s)->dstr_s[length] = 0;
154 : }
155 138599 : return s;
156 : }
157 :
158 : /**
159 : * allocate space for length char
160 : * @param s dynamic string
161 : * @param length new length
162 : * @return string allocated or NULL on memory error
163 : */
164 : DSTR*
165 114021 : tds_dstr_alloc(DSTR *s, size_t length)
166 : {
167 114021 : struct tds_dstr *p = (struct tds_dstr *) malloc(length + TDS_OFFSET(struct tds_dstr, dstr_s) + 1);
168 114021 : if (TDS_UNLIKELY(!p))
169 : return NULL;
170 :
171 114021 : if (*s != EMPTY)
172 12787 : free(*s);
173 114021 : p->dstr_s[0] = 0;
174 114021 : p->dstr_size = length;
175 114021 : *s = p;
176 114021 : return s;
177 : }
178 :
179 : /** @} */
|