src/string.c

changeset 1296
2a2403c63439
parent 1221
304f4f7b37d1
equal deleted inserted replaced
1295:b00c6ae1441a 1296:2a2403c63439
104 cxmutstr str, 104 cxmutstr str,
105 size_t count, 105 size_t count,
106 ... 106 ...
107 ) { 107 ) {
108 if (count == 0) return str; 108 if (count == 0) return str;
109
110 cxstring strings_stack[8];
111 cxstring *strings;
112 if (count > 8) {
113 strings = calloc(count, sizeof(cxstring));
114 if (strings == NULL) {
115 return (cxmutstr) {NULL, 0};
116 }
117 } else {
118 strings = strings_stack;
119 }
120
121 va_list ap; 109 va_list ap;
122 va_start(ap, count); 110 va_start(ap, count);
123 111 va_list ap2;
124 // get all args and overall length 112 va_copy(ap2, ap);
113
114 // compute overall length
125 bool overflow = false; 115 bool overflow = false;
126 size_t slen = str.length; 116 size_t slen = str.length;
127 for (size_t i = 0; i < count; i++) { 117 for (size_t i = 0; i < count; i++) {
128 cxstring s = va_arg (ap, cxstring); 118 cxstring s = va_arg(ap, cxstring);
129 strings[i] = s;
130 if (slen > SIZE_MAX - str.length) overflow = true; 119 if (slen > SIZE_MAX - str.length) overflow = true;
131 slen += s.length; 120 slen += s.length;
132 } 121 }
133 va_end(ap); 122 va_end(ap);
134 123
135 // abort in case of overflow 124 // abort in case of overflow
136 if (overflow) { 125 if (overflow) {
126 va_end(ap2);
137 errno = EOVERFLOW; 127 errno = EOVERFLOW;
138 if (strings != strings_stack) {
139 free(strings);
140 }
141 return (cxmutstr) { NULL, 0 }; 128 return (cxmutstr) { NULL, 0 };
142 } 129 }
143 130
144 // reallocate or create new string 131 // reallocate or create new string
145 char *newstr; 132 char *newstr;
147 newstr = cxMalloc(alloc, slen + 1); 134 newstr = cxMalloc(alloc, slen + 1);
148 } else { 135 } else {
149 newstr = cxRealloc(alloc, str.ptr, slen + 1); 136 newstr = cxRealloc(alloc, str.ptr, slen + 1);
150 } 137 }
151 if (newstr == NULL) { 138 if (newstr == NULL) {
152 if (strings != strings_stack) { 139 va_end(ap2);
153 free(strings);
154 }
155 return (cxmutstr) {NULL, 0}; 140 return (cxmutstr) {NULL, 0};
156 } 141 }
157 str.ptr = newstr; 142 str.ptr = newstr;
158 143
159 // concatenate strings 144 // concatenate strings
160 size_t pos = str.length; 145 size_t pos = str.length;
161 str.length = slen; 146 str.length = slen;
162 for (size_t i = 0; i < count; i++) { 147 for (size_t i = 0; i < count; i++) {
163 cxstring s = strings[i]; 148 cxstring s = va_arg(ap2, cxstring);
164 memcpy(str.ptr + pos, s.ptr, s.length); 149 memcpy(str.ptr + pos, s.ptr, s.length);
165 pos += s.length; 150 pos += s.length;
166 } 151 }
152 va_end(ap2);
167 153
168 // terminate string 154 // terminate string
169 str.ptr[str.length] = '\0'; 155 str.ptr[str.length] = '\0';
170
171 // free temporary array
172 if (strings != strings_stack) {
173 free(strings);
174 }
175 156
176 return str; 157 return str;
177 } 158 }
178 159
179 cxstring cx_strsubs( 160 cxstring cx_strsubs(

mercurial