| 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
| 27 */ |
27 */ |
| 28 #ifdef MEMRCHR_NEED_GNU |
28 |
| |
29 #ifdef WITH_MEMRCHR |
| 29 #define _GNU_SOURCE |
30 #define _GNU_SOURCE |
| 30 #endif |
31 #endif |
| 31 |
32 |
| 32 #include "cx/string.h" |
33 #include "cx/string.h" |
| 33 |
34 |
| 44 #else |
45 #else |
| 45 #include <strings.h> |
46 #include <strings.h> |
| 46 #define cx_strcasecmp_impl strncasecmp |
47 #define cx_strcasecmp_impl strncasecmp |
| 47 #endif |
48 #endif |
| 48 |
49 |
| 49 cxmutstr cx_mutstr(char *cstring) { |
|
| 50 return (cxmutstr) {cstring, cstring == NULL ? 0 : strlen(cstring)}; |
|
| 51 } |
|
| 52 |
|
| 53 cxmutstr cx_mutstrn( |
|
| 54 char *cstring, |
|
| 55 size_t length |
|
| 56 ) { |
|
| 57 return (cxmutstr) {cstring, length}; |
|
| 58 } |
|
| 59 |
|
| 60 cxstring cx_str(const char *cstring) { |
|
| 61 return (cxstring) {cstring, cstring == NULL ? 0 : strlen(cstring)}; |
|
| 62 } |
|
| 63 |
|
| 64 cxstring cx_strn( |
|
| 65 const char *cstring, |
|
| 66 size_t length |
|
| 67 ) { |
|
| 68 return (cxstring) {cstring, length}; |
|
| 69 } |
|
| 70 |
|
| 71 void cx_strfree(cxmutstr *str) { |
50 void cx_strfree(cxmutstr *str) { |
| 72 if (str == NULL) return; |
51 if (str == NULL) return; |
| 73 cxFreeDefault(str->ptr); |
52 cxFreeDefault(str->ptr); |
| 74 str->ptr = NULL; |
53 str->ptr = NULL; |
| 75 str->length = 0; |
54 str->length = 0; |
| 89 const CxAllocator *alloc, |
68 const CxAllocator *alloc, |
| 90 cxmutstr *dest, |
69 cxmutstr *dest, |
| 91 cxstring src |
70 cxstring src |
| 92 ) { |
71 ) { |
| 93 if (cxReallocate(alloc, &dest->ptr, src.length + 1)) { |
72 if (cxReallocate(alloc, &dest->ptr, src.length + 1)) { |
| 94 return 1; |
73 return 1; // LCOV_EXCL_LINE |
| 95 } |
74 } |
| 96 |
75 |
| 97 memcpy(dest->ptr, src.ptr, src.length); |
76 memcpy(dest->ptr, src.ptr, src.length); |
| 98 dest->length = src.length; |
77 dest->length = src.length; |
| 99 dest->ptr[dest->length] = '\0'; |
78 dest->ptr[dest->length] = '\0'; |
| 135 // compute overall length |
114 // compute overall length |
| 136 bool overflow = false; |
115 bool overflow = false; |
| 137 size_t slen = str.length; |
116 size_t slen = str.length; |
| 138 for (size_t i = 0; i < count; i++) { |
117 for (size_t i = 0; i < count; i++) { |
| 139 cxstring s = va_arg(ap, cxstring); |
118 cxstring s = va_arg(ap, cxstring); |
| 140 if (slen > SIZE_MAX - str.length) overflow = true; |
119 if (slen > SIZE_MAX - s.length) overflow = true; |
| 141 slen += s.length; |
120 slen += s.length; |
| 142 } |
121 } |
| 143 va_end(ap); |
122 va_end(ap); |
| 144 |
123 |
| 145 // abort in case of overflow |
124 // abort in case of overflow |
| 154 if (str.ptr == NULL) { |
133 if (str.ptr == NULL) { |
| 155 newstr = cxMalloc(alloc, slen + 1); |
134 newstr = cxMalloc(alloc, slen + 1); |
| 156 } else { |
135 } else { |
| 157 newstr = cxRealloc(alloc, str.ptr, slen + 1); |
136 newstr = cxRealloc(alloc, str.ptr, slen + 1); |
| 158 } |
137 } |
| 159 if (newstr == NULL) { |
138 if (newstr == NULL) { // LCOV_EXCL_START |
| 160 va_end(ap2); |
139 va_end(ap2); |
| 161 return (cxmutstr) {NULL, 0}; |
140 return (cxmutstr) {NULL, 0}; |
| 162 } |
141 } // LCOV_EXCL_STOP |
| 163 str.ptr = newstr; |
142 str.ptr = newstr; |
| 164 |
143 |
| 165 // concatenate strings |
144 // concatenate strings |
| 166 size_t pos = str.length; |
145 size_t pos = str.length; |
| 167 str.length = slen; |
146 str.length = slen; |
| 519 ) { |
498 ) { |
| 520 cxmutstr result = { |
499 cxmutstr result = { |
| 521 cxMalloc(allocator, string.length + 1), |
500 cxMalloc(allocator, string.length + 1), |
| 522 string.length |
501 string.length |
| 523 }; |
502 }; |
| |
503 // LCOV_EXCL_START |
| 524 if (result.ptr == NULL) { |
504 if (result.ptr == NULL) { |
| 525 result.length = 0; |
505 result.length = 0; |
| 526 return result; |
506 return result; |
| 527 } |
507 } |
| |
508 // LCOV_EXCL_STOP |
| 528 memcpy(result.ptr, string.ptr, string.length); |
509 memcpy(result.ptr, string.ptr, string.length); |
| 529 result.ptr[string.length] = '\0'; |
510 result.ptr[string.length] = '\0'; |
| 530 return result; |
511 return result; |
| 531 } |
512 } |
| 532 |
513 |