src/ucx/string.c

4 weeks ago

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 02 Mar 2025 18:10:52 +0100 (4 weeks ago)
changeset 579
e10457d74fe1
parent 490
d218607f5a7e
permissions
-rw-r--r--

update ucx

91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
1 /*
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
3 *
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
5 *
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
6 * Redistribution and use in source and binary forms, with or without
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
7 * modification, are permitted provided that the following conditions are met:
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
8 *
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
9 * 1. Redistributions of source code must retain the above copyright
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
10 * notice, this list of conditions and the following disclaimer.
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
11 *
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
12 * 2. Redistributions in binary form must reproduce the above copyright
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
13 * notice, this list of conditions and the following disclaimer in the
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
14 * documentation and/or other materials provided with the distribution.
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
15 *
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
26 * POSSIBILITY OF SUCH DAMAGE.
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
27 */
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
28 #include "cx/string.h"
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
29
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
30 #include <string.h>
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
31 #include <stdarg.h>
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
32 #include <assert.h>
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
33 #include <errno.h>
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
34 #include <limits.h>
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
35 #include <float.h>
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
36
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
37 #ifdef _WIN32
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
38 #define cx_strcasecmp_impl _strnicmp
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
39 #else
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
40 #include <strings.h>
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
41 #define cx_strcasecmp_impl strncasecmp
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
42 #endif
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
43
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
44 cxmutstr cx_mutstr(char *cstring) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
45 return (cxmutstr) {cstring, strlen(cstring)};
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
46 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
47
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
48 cxmutstr cx_mutstrn(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
49 char *cstring,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
50 size_t length
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
51 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
52 return (cxmutstr) {cstring, length};
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
53 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
54
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
55 cxstring cx_str(const char *cstring) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
56 return (cxstring) {cstring, strlen(cstring)};
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
57 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
58
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
59 cxstring cx_strn(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
60 const char *cstring,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
61 size_t length
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
62 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
63 return (cxstring) {cstring, length};
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
64 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
65
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
66 void cx_strfree(cxmutstr *str) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
67 if (str == NULL) return;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
68 free(str->ptr);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
69 str->ptr = NULL;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
70 str->length = 0;
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
71 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
72
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
73 void cx_strfree_a(
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
74 const CxAllocator *alloc,
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
75 cxmutstr *str
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
76 ) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
77 if (str == NULL) return;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
78 cxFree(alloc, str->ptr);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
79 str->ptr = NULL;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
80 str->length = 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
81 }
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
82
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
83 size_t cx_strlen(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
84 size_t count,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
85 ...
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
86 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
87 if (count == 0) return 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
88
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
89 va_list ap;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
90 va_start(ap, count);
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
91 size_t size = 0;
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
92 for (size_t i = 0; i < count; i++) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
93 cxstring str = va_arg(ap, cxstring);
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
94 if (size > SIZE_MAX - str.length) errno = EOVERFLOW;
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
95 size += str.length;
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
96 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
97 va_end(ap);
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
98
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
99 return size;
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
100 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
101
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
102 cxmutstr cx_strcat_ma(
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
103 const CxAllocator *alloc,
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
104 cxmutstr str,
99
b9a6af0ae41a ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 91
diff changeset
105 size_t count,
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
106 ...
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
107 ) {
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
108 if (count == 0) return str;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
109
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
110 cxstring strings_stack[8];
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
111 cxstring *strings;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
112 if (count > 8) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
113 strings = calloc(count, sizeof(cxstring));
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
114 if (strings == NULL) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
115 return (cxmutstr) {NULL, 0};
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
116 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
117 } else {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
118 strings = strings_stack;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
119 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
120
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
121 va_list ap;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
122 va_start(ap, count);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
123
99
b9a6af0ae41a ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 91
diff changeset
124 // get all args and overall length
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
125 bool overflow = false;
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
126 size_t slen = str.length;
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
127 for (size_t i = 0; i < count; i++) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
128 cxstring s = va_arg (ap, cxstring);
99
b9a6af0ae41a ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 91
diff changeset
129 strings[i] = s;
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
130 if (slen > SIZE_MAX - str.length) overflow = true;
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
131 slen += s.length;
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
132 }
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
133 va_end(ap);
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
134
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
135 // abort in case of overflow
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
136 if (overflow) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
137 errno = EOVERFLOW;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
138 if (strings != strings_stack) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
139 free(strings);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
140 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
141 return (cxmutstr) { NULL, 0 };
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
142 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
143
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
144 // reallocate or create new string
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
145 char *newstr;
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
146 if (str.ptr == NULL) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
147 newstr = cxMalloc(alloc, slen + 1);
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
148 } else {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
149 newstr = cxRealloc(alloc, str.ptr, slen + 1);
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
150 }
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
151 if (newstr == NULL) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
152 if (strings != strings_stack) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
153 free(strings);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
154 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
155 return (cxmutstr) {NULL, 0};
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
156 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
157 str.ptr = newstr;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
158
99
b9a6af0ae41a ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 91
diff changeset
159 // concatenate strings
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
160 size_t pos = str.length;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
161 str.length = slen;
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
162 for (size_t i = 0; i < count; i++) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
163 cxstring s = strings[i];
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
164 memcpy(str.ptr + pos, s.ptr, s.length);
99
b9a6af0ae41a ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 91
diff changeset
165 pos += s.length;
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
166 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
167
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
168 // terminate string
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
169 str.ptr[str.length] = '\0';
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
170
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
171 // free temporary array
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
172 if (strings != strings_stack) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
173 free(strings);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
174 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
175
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
176 return str;
99
b9a6af0ae41a ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 91
diff changeset
177 }
b9a6af0ae41a ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 91
diff changeset
178
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
179 cxstring cx_strsubs(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
180 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
181 size_t start
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
182 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
183 return cx_strsubsl(string, start, string.length - start);
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
184 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
185
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
186 cxmutstr cx_strsubs_m(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
187 cxmutstr string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
188 size_t start
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
189 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
190 return cx_strsubsl_m(string, start, string.length - start);
99
b9a6af0ae41a ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 91
diff changeset
191 }
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
192
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
193 cxstring cx_strsubsl(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
194 cxstring string,
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
195 size_t start,
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
196 size_t length
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
197 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
198 if (start > string.length) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
199 return (cxstring) {NULL, 0};
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
200 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
201
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
202 size_t rem_len = string.length - start;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
203 if (length > rem_len) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
204 length = rem_len;
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
205 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
206
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
207 return (cxstring) {string.ptr + start, length};
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
208 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
209
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
210 cxmutstr cx_strsubsl_m(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
211 cxmutstr string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
212 size_t start,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
213 size_t length
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
214 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
215 cxstring result = cx_strsubsl(cx_strcast(string), start, length);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
216 return (cxmutstr) {(char *) result.ptr, result.length};
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
217 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
218
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
219 cxstring cx_strchr(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
220 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
221 int chr
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
222 ) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
223 char *ret = memchr(string.ptr, 0xFF & chr, string.length);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
224 if (ret == NULL) return (cxstring) {NULL, 0};
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
225 return (cxstring) {ret, string.length - (ret - string.ptr)};
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
226 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
227
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
228 cxmutstr cx_strchr_m(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
229 cxmutstr string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
230 int chr
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
231 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
232 cxstring result = cx_strchr(cx_strcast(string), chr);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
233 return (cxmutstr) {(char *) result.ptr, result.length};
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
234 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
235
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
236 cxstring cx_strrchr(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
237 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
238 int chr
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
239 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
240 chr = 0xFF & chr;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
241 size_t i = string.length;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
242 while (i > 0) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
243 i--;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
244 // TODO: improve by comparing multiple bytes at once
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
245 if (string.ptr[i] == chr) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
246 return cx_strsubs(string, i);
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
247 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
248 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
249 return (cxstring) {NULL, 0};
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
250 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
251
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
252 cxmutstr cx_strrchr_m(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
253 cxmutstr string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
254 int chr
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
255 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
256 cxstring result = cx_strrchr(cx_strcast(string), chr);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
257 return (cxmutstr) {(char *) result.ptr, result.length};
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
258 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
259
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
260 #ifndef CX_STRSTR_SBO_SIZE
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
261 #define CX_STRSTR_SBO_SIZE 128
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
262 #endif
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
263 const unsigned cx_strstr_sbo_size = CX_STRSTR_SBO_SIZE;
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
264
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
265 cxstring cx_strstr(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
266 cxstring haystack,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
267 cxstring needle
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
268 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
269 if (needle.length == 0) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
270 return haystack;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
271 }
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
272
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
273 // optimize for single-char needles
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
274 if (needle.length == 1) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
275 return cx_strchr(haystack, *needle.ptr);
135
471e28cca288 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 99
diff changeset
276 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
277
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
278 /*
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
279 * IMPORTANT:
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
280 * Our prefix table contains the prefix length PLUS ONE
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
281 * this is our decision, because we want to use the full range of size_t.
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
282 * The original algorithm needs a (-1) at one single place,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
283 * and we want to avoid that.
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
284 */
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
285
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
286 // local prefix table
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
287 size_t s_prefix_table[CX_STRSTR_SBO_SIZE];
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
288
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
289 // check needle length and use appropriate prefix table
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
290 // if the pattern exceeds static prefix table, allocate on the heap
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
291 const bool useheap = needle.length >= CX_STRSTR_SBO_SIZE;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
292 register size_t *ptable = useheap ? calloc(needle.length + 1,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
293 sizeof(size_t)) : s_prefix_table;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
294
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
295 // keep counter in registers
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
296 register size_t i, j;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
297
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
298 // fill prefix table
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
299 i = 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
300 j = 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
301 ptable[i] = j;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
302 while (i < needle.length) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
303 while (j >= 1 && needle.ptr[j - 1] != needle.ptr[i]) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
304 j = ptable[j - 1];
135
471e28cca288 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 99
diff changeset
305 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
306 i++;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
307 j++;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
308 ptable[i] = j;
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
309 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
310
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
311 // search
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
312 cxstring result = {NULL, 0};
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
313 i = 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
314 j = 1;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
315 while (i < haystack.length) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
316 while (j >= 1 && haystack.ptr[i] != needle.ptr[j - 1]) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
317 j = ptable[j - 1];
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
318 }
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
319 i++;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
320 j++;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
321 if (j - 1 == needle.length) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
322 size_t start = i - needle.length;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
323 result.ptr = haystack.ptr + start;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
324 result.length = haystack.length - start;
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
325 break;
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
326 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
327 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
328
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
329 // if prefix table was allocated on the heap, free it
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
330 if (useheap) {
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
331 free(ptable);
135
471e28cca288 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 99
diff changeset
332 }
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
333
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
334 return result;
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
335 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
336
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
337 cxmutstr cx_strstr_m(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
338 cxmutstr haystack,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
339 cxstring needle
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
340 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
341 cxstring result = cx_strstr(cx_strcast(haystack), needle);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
342 return (cxmutstr) {(char *) result.ptr, result.length};
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
343 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
344
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
345 size_t cx_strsplit(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
346 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
347 cxstring delim,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
348 size_t limit,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
349 cxstring *output
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
350 ) {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
351 // special case: output limit is zero
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
352 if (limit == 0) return 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
353
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
354 // special case: delimiter is empty
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
355 if (delim.length == 0) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
356 output[0] = string;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
357 return 1;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
358 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
359
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
360 // special cases: delimiter is at least as large as the string
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
361 if (delim.length >= string.length) {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
362 // exact match
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
363 if (cx_strcmp(string, delim) == 0) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
364 output[0] = cx_strn(string.ptr, 0);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
365 output[1] = cx_strn(string.ptr + string.length, 0);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
366 return 2;
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
367 } else {
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
368 // no match possible
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
369 output[0] = string;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
370 return 1;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
371 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
372 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
373
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
374 size_t n = 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
375 cxstring curpos = string;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
376 while (1) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
377 ++n;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
378 cxstring match = cx_strstr(curpos, delim);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
379 if (match.length > 0) {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
380 // is the limit reached?
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
381 if (n < limit) {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
382 // copy the current string to the array
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
383 cxstring item = cx_strn(curpos.ptr, match.ptr - curpos.ptr);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
384 output[n - 1] = item;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
385 size_t processed = item.length + delim.length;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
386 curpos.ptr += processed;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
387 curpos.length -= processed;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
388 } else {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
389 // limit reached, copy the _full_ remaining string
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
390 output[n - 1] = curpos;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
391 break;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
392 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
393 } else {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
394 // no more matches, copy last string
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
395 output[n - 1] = curpos;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
396 break;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
397 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
398 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
399
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
400 return n;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
401 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
402
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
403 size_t cx_strsplit_a(
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
404 const CxAllocator *allocator,
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
405 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
406 cxstring delim,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
407 size_t limit,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
408 cxstring **output
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
409 ) {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
410 // find out how many splits we're going to make and allocate memory
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
411 size_t n = 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
412 cxstring curpos = string;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
413 while (1) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
414 ++n;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
415 cxstring match = cx_strstr(curpos, delim);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
416 if (match.length > 0) {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
417 // is the limit reached?
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
418 if (n < limit) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
419 size_t processed = match.ptr - curpos.ptr + delim.length;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
420 curpos.ptr += processed;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
421 curpos.length -= processed;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
422 } else {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
423 // limit reached
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
424 break;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
425 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
426 } else {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
427 // no more matches
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
428 break;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
429 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
430 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
431 *output = cxCalloc(allocator, n, sizeof(cxstring));
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
432 return cx_strsplit(string, delim, n, *output);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
433 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
434
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
435 size_t cx_strsplit_m(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
436 cxmutstr string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
437 cxstring delim,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
438 size_t limit,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
439 cxmutstr *output
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
440 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
441 return cx_strsplit(cx_strcast(string),
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
442 delim, limit, (cxstring *) output);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
443 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
444
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
445 size_t cx_strsplit_ma(
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
446 const CxAllocator *allocator,
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
447 cxmutstr string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
448 cxstring delim,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
449 size_t limit,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
450 cxmutstr **output
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
451 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
452 return cx_strsplit_a(allocator, cx_strcast(string),
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
453 delim, limit, (cxstring **) output);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
454 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
455
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
456 int cx_strcmp(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
457 cxstring s1,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
458 cxstring s2
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
459 ) {
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
460 if (s1.length == s2.length) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
461 return strncmp(s1.ptr, s2.ptr, s1.length);
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
462 } else if (s1.length > s2.length) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
463 int r = strncmp(s1.ptr, s2.ptr, s2.length);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
464 if (r != 0) return r;
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
465 return 1;
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
466 } else {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
467 int r = strncmp(s1.ptr, s2.ptr, s1.length);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
468 if (r != 0) return r;
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
469 return -1;
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
470 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
471 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
472
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
473 int cx_strcasecmp(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
474 cxstring s1,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
475 cxstring s2
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
476 ) {
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
477 if (s1.length == s2.length) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
478 return cx_strcasecmp_impl(s1.ptr, s2.ptr, s1.length);
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
479 } else if (s1.length > s2.length) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
480 int r = cx_strcasecmp_impl(s1.ptr, s2.ptr, s2.length);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
481 if (r != 0) return r;
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
482 return 1;
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
483 } else {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
484 int r = cx_strcasecmp_impl(s1.ptr, s2.ptr, s1.length);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
485 if (r != 0) return r;
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
486 return -1;
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
487 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
488 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
489
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
490 int cx_strcmp_p(
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
491 const void *s1,
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
492 const void *s2
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
493 ) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
494 const cxstring *left = s1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
495 const cxstring *right = s2;
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
496 return cx_strcmp(*left, *right);
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
497 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
498
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
499 int cx_strcasecmp_p(
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
500 const void *s1,
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
501 const void *s2
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
502 ) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
503 const cxstring *left = s1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
504 const cxstring *right = s2;
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
505 return cx_strcasecmp(*left, *right);
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
506 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
507
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
508 cxmutstr cx_strdup_a_(
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
509 const CxAllocator *allocator,
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
510 cxstring string
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
511 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
512 cxmutstr result = {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
513 cxMalloc(allocator, string.length + 1),
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
514 string.length
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
515 };
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
516 if (result.ptr == NULL) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
517 result.length = 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
518 return result;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
519 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
520 memcpy(result.ptr, string.ptr, string.length);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
521 result.ptr[string.length] = '\0';
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
522 return result;
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
523 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
524
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
525 static bool str_isspace(char c) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
526 // TODO: remove once UCX has public API for this
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
527 return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v' || c == '\f';
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
528 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
529
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
530 cxstring cx_strtrim(cxstring string) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
531 cxstring result = string;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
532 // TODO: optimize by comparing multiple bytes at once
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
533 while (result.length > 0 && str_isspace(*result.ptr)) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
534 result.ptr++;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
535 result.length--;
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
536 }
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
537 while (result.length > 0 && str_isspace(result.ptr[result.length - 1])) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
538 result.length--;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
539 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
540 return result;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
541 }
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
542
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
543 cxmutstr cx_strtrim_m(cxmutstr string) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
544 cxstring result = cx_strtrim(cx_strcast(string));
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
545 return (cxmutstr) {(char *) result.ptr, result.length};
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
546 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
547
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
548 bool cx_strprefix(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
549 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
550 cxstring prefix
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
551 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
552 if (string.length < prefix.length) return false;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
553 return memcmp(string.ptr, prefix.ptr, prefix.length) == 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
554 }
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
555
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
556 bool cx_strsuffix(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
557 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
558 cxstring suffix
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
559 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
560 if (string.length < suffix.length) return false;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
561 return memcmp(string.ptr + string.length - suffix.length,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
562 suffix.ptr, suffix.length) == 0;
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
563 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
564
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
565 bool cx_strcaseprefix(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
566 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
567 cxstring prefix
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
568 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
569 if (string.length < prefix.length) return false;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
570 #ifdef _WIN32
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
571 return _strnicmp(string.ptr, prefix.ptr, prefix.length) == 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
572 #else
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
573 return strncasecmp(string.ptr, prefix.ptr, prefix.length) == 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
574 #endif
91
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
575 }
fac51f87def0 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
576
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
577 bool cx_strcasesuffix(
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
578 cxstring string,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
579 cxstring suffix
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
580 ) {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
581 if (string.length < suffix.length) return false;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
582 #ifdef _WIN32
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
583 return _strnicmp(string.ptr+string.length-suffix.length,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
584 suffix.ptr, suffix.length) == 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
585 #else
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
586 return strncasecmp(string.ptr + string.length - suffix.length,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
587 suffix.ptr, suffix.length) == 0;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
588 #endif
254
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
589 }
4784c14aa639 ucx update
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 135
diff changeset
590
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
591 #ifndef CX_STRREPLACE_INDEX_BUFFER_SIZE
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
592 #define CX_STRREPLACE_INDEX_BUFFER_SIZE 64
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
593 #endif
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
594
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
595 struct cx_strreplace_ibuf {
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
596 size_t *buf;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
597 struct cx_strreplace_ibuf *next;
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
598 unsigned int len;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
599 };
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
600
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
601 static void cx_strrepl_free_ibuf(struct cx_strreplace_ibuf *buf) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
602 // remember, the first data is on the stack!
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
603 buf = buf->next;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
604 while (buf) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
605 struct cx_strreplace_ibuf *next = buf->next;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
606 free(buf->buf);
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
607 free(buf);
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
608 buf = next;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
609 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
610 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
611
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
612 cxmutstr cx_strreplacen_a(
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
613 const CxAllocator *allocator,
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
614 cxstring str,
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
615 cxstring search,
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
616 cxstring replacement,
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
617 size_t replmax
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
618 ) {
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
619
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
620 if (search.length == 0 || search.length > str.length || replmax == 0)
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
621 return cx_strdup_a(allocator, str);
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
622
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
623 // Compute expected buffer length
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
624 size_t ibufmax = str.length / search.length;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
625 size_t ibuflen = replmax < ibufmax ? replmax : ibufmax;
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
626 if (ibuflen > CX_STRREPLACE_INDEX_BUFFER_SIZE) {
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
627 ibuflen = CX_STRREPLACE_INDEX_BUFFER_SIZE;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
628 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
629
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
630 // First index buffer can be on the stack
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
631 struct cx_strreplace_ibuf ibuf, *curbuf = &ibuf;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
632 size_t ibuf_sbo[CX_STRREPLACE_INDEX_BUFFER_SIZE];
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
633 ibuf.buf = ibuf_sbo;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
634 ibuf.next = NULL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
635 ibuf.len = 0;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
636
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
637 // Search occurrences
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
638 cxstring searchstr = str;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
639 size_t found = 0;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
640 do {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
641 cxstring match = cx_strstr(searchstr, search);
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
642 if (match.length > 0) {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
643 // Allocate next buffer in chain, if required
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
644 if (curbuf->len == ibuflen) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
645 struct cx_strreplace_ibuf *nextbuf =
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
646 calloc(1, sizeof(struct cx_strreplace_ibuf));
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
647 if (!nextbuf) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
648 cx_strrepl_free_ibuf(&ibuf);
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
649 return cx_mutstrn(NULL, 0);
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
650 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
651 nextbuf->buf = calloc(ibuflen, sizeof(size_t));
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
652 if (!nextbuf->buf) {
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
653 free(nextbuf);
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
654 cx_strrepl_free_ibuf(&ibuf);
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
655 return cx_mutstrn(NULL, 0);
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
656 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
657 curbuf->next = nextbuf;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
658 curbuf = nextbuf;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
659 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
660
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
661 // Record match index
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
662 found++;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
663 size_t idx = match.ptr - str.ptr;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
664 curbuf->buf[curbuf->len++] = idx;
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
665 searchstr.ptr = match.ptr + search.length;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
666 searchstr.length = str.length - idx - search.length;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
667 } else {
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
668 break;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
669 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
670 } while (searchstr.length > 0 && found < replmax);
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
671
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
672 // Allocate result string
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
673 cxmutstr result;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
674 {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
675 long long adjlen = (long long) replacement.length - (long long) search.length;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
676 size_t rcount = 0;
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
677 curbuf = &ibuf;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
678 do {
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
679 rcount += curbuf->len;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
680 curbuf = curbuf->next;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
681 } while (curbuf);
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
682 result.length = str.length + rcount * adjlen;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
683 result.ptr = cxMalloc(allocator, result.length + 1);
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
684 if (!result.ptr) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
685 cx_strrepl_free_ibuf(&ibuf);
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
686 return cx_mutstrn(NULL, 0);
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
687 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
688 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
689
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
690 // Build result string
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
691 curbuf = &ibuf;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
692 size_t srcidx = 0;
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
693 char *destptr = result.ptr;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
694 do {
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
695 for (size_t i = 0; i < curbuf->len; i++) {
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
696 // Copy source part up to next match
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
697 size_t idx = curbuf->buf[i];
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
698 size_t srclen = idx - srcidx;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
699 if (srclen > 0) {
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
700 memcpy(destptr, str.ptr + srcidx, srclen);
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
701 destptr += srclen;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
702 srcidx += srclen;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
703 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
704
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
705 // Copy the replacement and skip the source pattern
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
706 srcidx += search.length;
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
707 memcpy(destptr, replacement.ptr, replacement.length);
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
708 destptr += replacement.length;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
709 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
710 curbuf = curbuf->next;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
711 } while (curbuf);
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
712 memcpy(destptr, str.ptr + srcidx, str.length - srcidx);
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
713
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
714 // Result is guaranteed to be zero-terminated
415
d938228c382e switch from ucx 2 to 3
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 260
diff changeset
715 result.ptr[result.length] = '\0';
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
716
438
22eca559aded refactore http listener creation
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 415
diff changeset
717 // Free index buffer
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
718 cx_strrepl_free_ibuf(&ibuf);
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
719
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
720 return result;
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
721 }
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
722
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
723 CxStrtokCtx cx_strtok_(
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
724 cxstring str,
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
725 cxstring delim,
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
726 size_t limit
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
727 ) {
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
728 CxStrtokCtx ctx;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
729 ctx.str = str;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
730 ctx.delim = delim;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
731 ctx.limit = limit;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
732 ctx.pos = 0;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
733 ctx.next_pos = 0;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
734 ctx.delim_pos = 0;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
735 ctx.found = 0;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
736 ctx.delim_more = NULL;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
737 ctx.delim_more_count = 0;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
738 return ctx;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
739 }
260
4779a6fb4fbe fix freebsd build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 254
diff changeset
740
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
741 bool cx_strtok_next(
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
742 CxStrtokCtx *ctx,
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
743 cxstring *token
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
744 ) {
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
745 // abortion criteria
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
746 if (ctx->found >= ctx->limit || ctx->delim_pos >= ctx->str.length) {
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
747 return false;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
748 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
749
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
750 // determine the search start
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
751 cxstring haystack = cx_strsubs(ctx->str, ctx->next_pos);
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
752
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
753 // search the next delimiter
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
754 cxstring delim = cx_strstr(haystack, ctx->delim);
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
755
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
756 // if found, make delim capture exactly the delimiter
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
757 if (delim.length > 0) {
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
758 delim.length = ctx->delim.length;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
759 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
760
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
761 // if more delimiters are specified, check them now
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
762 if (ctx->delim_more_count > 0) {
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
763 for (size_t i = 0; i < ctx->delim_more_count; i++) {
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
764 cxstring d = cx_strstr(haystack, ctx->delim_more[i]);
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
765 if (d.length > 0 && (delim.length == 0 || d.ptr < delim.ptr)) {
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
766 delim.ptr = d.ptr;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
767 delim.length = ctx->delim_more[i].length;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
768 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
769 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
770 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
771
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
772 // store the token information and adjust the context
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
773 ctx->found++;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
774 ctx->pos = ctx->next_pos;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
775 token->ptr = &ctx->str.ptr[ctx->pos];
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
776 ctx->delim_pos = delim.length == 0 ?
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
777 ctx->str.length : (size_t) (delim.ptr - ctx->str.ptr);
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
778 token->length = ctx->delim_pos - ctx->pos;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
779 ctx->next_pos = ctx->delim_pos + delim.length;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
780
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
781 return true;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
782 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
783
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
784 bool cx_strtok_next_m(
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
785 CxStrtokCtx *ctx,
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
786 cxmutstr *token
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
787 ) {
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
788 return cx_strtok_next(ctx, (cxstring *) token);
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
789 }
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
790
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
791 void cx_strtok_delim(
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
792 CxStrtokCtx *ctx,
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
793 const cxstring *delim,
490
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
794 size_t count
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
795 ) {
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
796 ctx->delim_more = delim;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
797 ctx->delim_more_count = count;
d218607f5a7e update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 438
diff changeset
798 }
579
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
799
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
800 #define cx_strtoX_signed_impl(rtype, rmin, rmax) \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
801 long long result; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
802 if (cx_strtoll_lc(str, &result, base, groupsep)) { \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
803 return -1; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
804 } \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
805 if (result < rmin || result > rmax) { \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
806 errno = ERANGE; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
807 return -1; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
808 } \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
809 *output = (rtype) result; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
810 return 0
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
811
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
812 int cx_strtos_lc_(cxstring str, short *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
813 cx_strtoX_signed_impl(short, SHRT_MIN, SHRT_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
814 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
815
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
816 int cx_strtoi_lc_(cxstring str, int *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
817 cx_strtoX_signed_impl(int, INT_MIN, INT_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
818 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
819
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
820 int cx_strtol_lc_(cxstring str, long *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
821 cx_strtoX_signed_impl(long, LONG_MIN, LONG_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
822 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
823
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
824 int cx_strtoll_lc_(cxstring str, long long *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
825 // strategy: parse as unsigned, check range, negate if required
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
826 bool neg = false;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
827 size_t start_unsigned = 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
828
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
829 // emptiness check
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
830 if (str.length == 0) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
831 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
832 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
833 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
834
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
835 // test if we have a negative sign character
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
836 if (str.ptr[start_unsigned] == '-') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
837 neg = true;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
838 start_unsigned++;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
839 // must not be followed by positive sign character
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
840 if (str.length == 1 || str.ptr[start_unsigned] == '+') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
841 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
842 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
843 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
844 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
845
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
846 // now parse the number with strtoull
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
847 unsigned long long v;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
848 cxstring ustr = start_unsigned == 0 ? str
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
849 : cx_strn(str.ptr + start_unsigned, str.length - start_unsigned);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
850 int ret = cx_strtoull_lc(ustr, &v, base, groupsep);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
851 if (ret != 0) return ret;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
852 if (neg) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
853 if (v - 1 > LLONG_MAX) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
854 errno = ERANGE;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
855 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
856 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
857 *output = -(long long) v;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
858 return 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
859 } else {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
860 if (v > LLONG_MAX) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
861 errno = ERANGE;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
862 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
863 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
864 *output = (long long) v;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
865 return 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
866 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
867 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
868
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
869 int cx_strtoi8_lc_(cxstring str, int8_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
870 cx_strtoX_signed_impl(int8_t, INT8_MIN, INT8_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
871 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
872
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
873 int cx_strtoi16_lc_(cxstring str, int16_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
874 cx_strtoX_signed_impl(int16_t, INT16_MIN, INT16_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
875 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
876
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
877 int cx_strtoi32_lc_(cxstring str, int32_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
878 cx_strtoX_signed_impl(int32_t, INT32_MIN, INT32_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
879 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
880
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
881 int cx_strtoi64_lc_(cxstring str, int64_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
882 assert(sizeof(long long) == sizeof(int64_t)); // should be true on all platforms
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
883 return cx_strtoll_lc(str, (long long*) output, base, groupsep);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
884 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
885
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
886 #define cx_strtoX_unsigned_impl(rtype, rmax) \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
887 uint64_t result; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
888 if (cx_strtou64_lc(str, &result, base, groupsep)) { \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
889 return -1; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
890 } \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
891 if (result > rmax) { \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
892 errno = ERANGE; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
893 return -1; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
894 } \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
895 *output = (rtype) result; \
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
896 return 0
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
897
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
898 int cx_strtous_lc_(cxstring str, unsigned short *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
899 cx_strtoX_unsigned_impl(unsigned short, USHRT_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
900 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
901
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
902 int cx_strtou_lc_(cxstring str, unsigned int *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
903 cx_strtoX_unsigned_impl(unsigned int, UINT_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
904 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
905
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
906 int cx_strtoul_lc_(cxstring str, unsigned long *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
907 cx_strtoX_unsigned_impl(unsigned long, ULONG_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
908 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
909
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
910 int cx_strtoull_lc_(cxstring str, unsigned long long *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
911 // some sanity checks
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
912 if (str.length == 0) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
913 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
914 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
915 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
916 if (!(base == 2 || base == 8 || base == 10 || base == 16)) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
917 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
918 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
919 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
920 if (groupsep == NULL) groupsep = "";
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
921
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
922 // find the actual start of the number
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
923 if (str.ptr[0] == '+') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
924 str.ptr++;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
925 str.length--;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
926 if (str.length == 0) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
927 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
928 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
929 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
930 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
931 size_t start = 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
932
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
933 // if base is 2 or 16, some leading stuff may appear
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
934 if (base == 2) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
935 if ((str.ptr[0] | 32) == 'b') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
936 start = 1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
937 } else if (str.ptr[0] == '0' && str.length > 1) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
938 if ((str.ptr[1] | 32) == 'b') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
939 start = 2;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
940 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
941 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
942 } else if (base == 16) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
943 if ((str.ptr[0] | 32) == 'x' || str.ptr[0] == '#') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
944 start = 1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
945 } else if (str.ptr[0] == '0' && str.length > 1) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
946 if ((str.ptr[1] | 32) == 'x') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
947 start = 2;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
948 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
949 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
950 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
951
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
952 // check if there are digits left
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
953 if (start >= str.length) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
954 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
955 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
956 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
957
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
958 // now parse the number
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
959 unsigned long long result = 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
960 for (size_t i = start; i < str.length; i++) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
961 // ignore group separators
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
962 if (strchr(groupsep, str.ptr[i])) continue;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
963
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
964 // determine the digit value of the character
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
965 unsigned char c = str.ptr[i];
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
966 if (c >= 'a') c = 10 + (c - 'a');
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
967 else if (c >= 'A') c = 10 + (c - 'A');
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
968 else if (c >= '0') c = c - '0';
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
969 else c = 255;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
970 if (c >= base) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
971 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
972 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
973 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
974
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
975 // now combine the digit with what we already have
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
976 unsigned long right = (result & 0xff) * base + c;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
977 unsigned long long left = (result >> 8) * base + (right >> 8);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
978 if (left > (ULLONG_MAX >> 8)) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
979 errno = ERANGE;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
980 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
981 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
982 result = (left << 8) + (right & 0xff);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
983 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
984
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
985 *output = result;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
986 return 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
987 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
988
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
989 int cx_strtou8_lc_(cxstring str, uint8_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
990 cx_strtoX_unsigned_impl(uint8_t, UINT8_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
991 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
992
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
993 int cx_strtou16_lc_(cxstring str, uint16_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
994 cx_strtoX_unsigned_impl(uint16_t, UINT16_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
995 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
996
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
997 int cx_strtou32_lc_(cxstring str, uint32_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
998 cx_strtoX_unsigned_impl(uint32_t, UINT32_MAX);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
999 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1000
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1001 int cx_strtou64_lc_(cxstring str, uint64_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1002 assert(sizeof(unsigned long long) == sizeof(uint64_t)); // should be true on all platforms
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1003 return cx_strtoull_lc(str, (unsigned long long*) output, base, groupsep);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1004 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1005
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1006 int cx_strtoz_lc_(cxstring str, size_t *output, int base, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1007 #if SIZE_MAX == UINT32_MAX
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1008 return cx_strtou32_lc_(str, (uint32_t*) output, base, groupsep);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1009 #elif SIZE_MAX == UINT64_MAX
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1010 return cx_strtoull_lc_(str, (unsigned long long *) output, base, groupsep);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1011 #else
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1012 #error "unsupported size_t size"
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1013 #endif
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1014 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1015
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1016 int cx_strtof_lc_(cxstring str, float *output, char decsep, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1017 // use string to double and add a range check
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1018 double d;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1019 int ret = cx_strtod_lc_(str, &d, decsep, groupsep);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1020 if (ret != 0) return ret;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1021 // note: FLT_MIN is the smallest POSITIVE number that can be represented
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1022 double test = d < 0 ? -d : d;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1023 if (test < FLT_MIN || test > FLT_MAX) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1024 errno = ERANGE;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1025 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1026 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1027 *output = (float) d;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1028 return 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1029 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1030
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1031 static bool str_isdigit(char c) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1032 // TODO: remove once UCX has public API for this
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1033 return c >= '0' && c <= '9';
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1034 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1035
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1036 int cx_strtod_lc_(cxstring str, double *output, char decsep, const char *groupsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1037 // TODO: overflow check
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1038 // TODO: increase precision
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1039
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1040 // emptiness check
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1041 if (str.length == 0) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1042 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1043 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1044 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1045
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1046 double result = 0.;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1047 int sign = 1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1048
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1049 // check if there is a sign
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1050 if (str.ptr[0] == '-') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1051 sign = -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1052 str.ptr++;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1053 str.length--;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1054 } else if (str.ptr[0] == '+') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1055 str.ptr++;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1056 str.length--;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1057 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1058
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1059 // there must be at least one char to parse
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1060 if (str.length == 0) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1061 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1062 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1063 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1064
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1065 // parse all digits until we find the decsep
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1066 size_t pos = 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1067 do {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1068 if (str_isdigit(str.ptr[pos])) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1069 result = result * 10 + (str.ptr[pos] - '0');
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1070 } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1071 break;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1072 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1073 } while (++pos < str.length);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1074
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1075 // already done?
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1076 if (pos == str.length) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1077 *output = result * sign;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1078 return 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1079 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1080
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1081 // is the next char the decsep?
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1082 if (str.ptr[pos] == decsep) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1083 pos++;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1084 // it may end with the decsep, if it did not start with it
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1085 if (pos == str.length) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1086 if (str.length == 1) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1087 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1088 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1089 } else {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1090 *output = result * sign;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1091 return 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1092 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1093 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1094 // parse everything until exponent or end
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1095 double factor = 1.;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1096 do {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1097 if (str_isdigit(str.ptr[pos])) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1098 factor *= 0.1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1099 result = result + factor * (str.ptr[pos] - '0');
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1100 } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1101 break;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1102 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1103 } while (++pos < str.length);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1104 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1105
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1106 // no exponent?
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1107 if (pos == str.length) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1108 *output = result * sign;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1109 return 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1110 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1111
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1112 // now the next separator MUST be the exponent separator
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1113 // and at least one char must follow
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1114 if ((str.ptr[pos] | 32) != 'e' || str.length <= pos + 1) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1115 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1116 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1117 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1118 pos++;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1119
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1120 // check if we have a sign for the exponent
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1121 double factor = 10.;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1122 if (str.ptr[pos] == '-') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1123 factor = .1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1124 pos++;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1125 } else if (str.ptr[pos] == '+') {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1126 pos++;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1127 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1128
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1129 // at least one digit must follow
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1130 if (pos == str.length) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1131 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1132 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1133 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1134
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1135 // parse the exponent
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1136 unsigned int exp = 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1137 do {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1138 if (str_isdigit(str.ptr[pos])) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1139 exp = 10 * exp + (str.ptr[pos] - '0');
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1140 } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1141 errno = EINVAL;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1142 return -1;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1143 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1144 } while (++pos < str.length);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1145
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1146 // apply the exponent by fast exponentiation
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1147 do {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1148 if (exp & 1) {
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1149 result *= factor;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1150 }
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1151 factor *= factor;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1152 } while ((exp >>= 1) > 0);
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1153
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1154 // store the result and exit
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1155 *output = result * sign;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1156 return 0;
e10457d74fe1 update ucx
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 490
diff changeset
1157 }

mercurial