96 va_end(ap); |
96 va_end(ap); |
97 |
97 |
98 return size; |
98 return size; |
99 } |
99 } |
100 |
100 |
101 cxmutstr cx_strcat_a( |
101 cxmutstr cx_strcat_ma( |
102 CxAllocator const *alloc, |
102 CxAllocator const *alloc, |
|
103 cxmutstr str, |
103 size_t count, |
104 size_t count, |
104 ... |
105 ... |
105 ) { |
106 ) { |
|
107 if (count == 0) return str; |
|
108 |
106 cxstring *strings = calloc(count, sizeof(cxstring)); |
109 cxstring *strings = calloc(count, sizeof(cxstring)); |
107 if (!strings) abort(); |
110 if (!strings) abort(); |
108 |
111 |
109 va_list ap; |
112 va_list ap; |
110 va_start(ap, count); |
113 va_start(ap, count); |
111 |
114 |
112 // get all args and overall length |
115 // get all args and overall length |
113 size_t slen = 0; |
116 size_t slen = str.length; |
114 cx_for_n(i, count) { |
117 cx_for_n(i, count) { |
115 cxstring s = va_arg (ap, cxstring); |
118 cxstring s = va_arg (ap, cxstring); |
116 strings[i] = s; |
119 strings[i] = s; |
117 slen += s.length; |
120 slen += s.length; |
118 } |
121 } |
119 |
122 va_end(ap); |
120 // create new string |
123 |
121 cxmutstr result; |
124 // reallocate or create new string |
122 result.ptr = cxMalloc(alloc, slen + 1); |
125 if (str.ptr == NULL) { |
123 result.length = slen; |
126 str.ptr = cxMalloc(alloc, slen + 1); |
124 if (result.ptr == NULL) abort(); |
127 } else { |
|
128 str.ptr = cxRealloc(alloc, str.ptr, slen + 1); |
|
129 } |
|
130 if (str.ptr == NULL) abort(); |
125 |
131 |
126 // concatenate strings |
132 // concatenate strings |
127 size_t pos = 0; |
133 size_t pos = str.length; |
|
134 str.length = slen; |
128 cx_for_n(i, count) { |
135 cx_for_n(i, count) { |
129 cxstring s = strings[i]; |
136 cxstring s = strings[i]; |
130 memcpy(result.ptr + pos, s.ptr, s.length); |
137 memcpy(str.ptr + pos, s.ptr, s.length); |
131 pos += s.length; |
138 pos += s.length; |
132 } |
139 } |
133 |
140 |
134 // terminate string |
141 // terminate string |
135 result.ptr[result.length] = '\0'; |
142 str.ptr[str.length] = '\0'; |
136 |
143 |
137 // free temporary array |
144 // free temporary array |
138 free(strings); |
145 free(strings); |
139 |
146 |
140 return result; |
147 return str; |
141 } |
148 } |
142 |
149 |
143 cxstring cx_strsubs( |
150 cxstring cx_strsubs( |
144 cxstring string, |
151 cxstring string, |
145 size_t start |
152 size_t start |