| 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
| 27 */ |
27 */ |
| 28 #ifdef MEMRCHR_NEED_GNU |
28 |
| |
29 // for memrchr in glibc |
| 29 #define _GNU_SOURCE |
30 #define _GNU_SOURCE |
| 30 #endif |
|
| 31 |
31 |
| 32 #include "cx/string.h" |
32 #include "cx/string.h" |
| 33 |
33 |
| 34 #include <string.h> |
34 #include <string.h> |
| 35 #include <stdarg.h> |
35 #include <stdarg.h> |
| 43 #define cx_strcasecmp_impl _strnicmp |
43 #define cx_strcasecmp_impl _strnicmp |
| 44 #else |
44 #else |
| 45 #include <strings.h> |
45 #include <strings.h> |
| 46 #define cx_strcasecmp_impl strncasecmp |
46 #define cx_strcasecmp_impl strncasecmp |
| 47 #endif |
47 #endif |
| 48 |
|
| 49 cxmutstr cx_mutstr(char *cstring) { |
|
| 50 return (cxmutstr) {cstring, cstring == NULL ? 0 : strlen(cstring)}; |
|
| 51 } |
|
| 52 |
|
| 53 cxmutstr cx_mutstrn( |
|
| 54 char *cstring, |
|
| 55 size_t length |
|
| 56 ) { |
|
| 57 return (cxmutstr) {cstring, length}; |
|
| 58 } |
|
| 59 |
|
| 60 cxstring cx_str(const char *cstring) { |
|
| 61 return (cxstring) {cstring, cstring == NULL ? 0 : strlen(cstring)}; |
|
| 62 } |
|
| 63 |
|
| 64 cxstring cx_strn( |
|
| 65 const char *cstring, |
|
| 66 size_t length |
|
| 67 ) { |
|
| 68 return (cxstring) {cstring, length}; |
|
| 69 } |
|
| 70 |
48 |
| 71 void cx_strfree(cxmutstr *str) { |
49 void cx_strfree(cxmutstr *str) { |
| 72 if (str == NULL) return; |
50 if (str == NULL) return; |
| 73 cxFreeDefault(str->ptr); |
51 cxFreeDefault(str->ptr); |
| 74 str->ptr = NULL; |
52 str->ptr = NULL; |
| 262 ) { |
240 ) { |
| 263 cxstring result = cx_strrchr(cx_strcast(string), chr); |
241 cxstring result = cx_strrchr(cx_strcast(string), chr); |
| 264 return (cxmutstr) {(char *) result.ptr, result.length}; |
242 return (cxmutstr) {(char *) result.ptr, result.length}; |
| 265 } |
243 } |
| 266 |
244 |
| 267 #ifndef CX_STRSTR_SBO_SIZE |
245 #ifndef cx_strSTR_SBO_SIZE |
| 268 #define CX_STRSTR_SBO_SIZE 128 |
246 #define cx_strSTR_SBO_SIZE 128 |
| 269 #endif |
247 #endif |
| 270 const unsigned cx_strstr_sbo_size = CX_STRSTR_SBO_SIZE; |
248 const unsigned cx_strstr_sbo_size = cx_strSTR_SBO_SIZE; |
| 271 |
249 |
| 272 cxstring cx_strstr( |
250 cxstring cx_strstr( |
| 273 cxstring haystack, |
251 cxstring haystack, |
| 274 cxstring needle |
252 cxstring needle |
| 275 ) { |
253 ) { |
| 289 * The original algorithm needs a (-1) at one single place, |
267 * The original algorithm needs a (-1) at one single place, |
| 290 * and we want to avoid that. |
268 * and we want to avoid that. |
| 291 */ |
269 */ |
| 292 |
270 |
| 293 // local prefix table |
271 // local prefix table |
| 294 size_t s_prefix_table[CX_STRSTR_SBO_SIZE]; |
272 size_t s_prefix_table[cx_strSTR_SBO_SIZE]; |
| 295 |
273 |
| 296 // check needle length and use appropriate prefix table |
274 // check needle length and use appropriate prefix table |
| 297 // if the pattern exceeds static prefix table, allocate on the heap |
275 // if the pattern exceeds static prefix table, allocate on the heap |
| 298 const bool useheap = needle.length >= CX_STRSTR_SBO_SIZE; |
276 const bool useheap = needle.length >= cx_strSTR_SBO_SIZE; |
| 299 register size_t *ptable = useheap |
277 register size_t *ptable = useheap |
| 300 ? cxCallocDefault(needle.length + 1, sizeof(size_t)) |
278 ? cxCallocDefault(needle.length + 1, sizeof(size_t)) |
| 301 : s_prefix_table; |
279 : s_prefix_table; |
| 302 |
280 |
| 303 // keep counter in registers |
281 // keep counter in registers |