core: add thread-safe strtok implementation (#3553)
This commit adds the support for a custom strtok implementation, which is reentrant. On some systems strtok_r or strstep is available for that purpose; however, since these are an extension, it is difficult to control if it will be available on every supported system.
This commit is contained in:
parent
9f2ed35da0
commit
2a31fe8552
@ -125,6 +125,7 @@ set(uv_sources
|
||||
src/inet.c
|
||||
src/random.c
|
||||
src/strscpy.c
|
||||
src/strtok.c
|
||||
src/threadpool.c
|
||||
src/timer.c
|
||||
src/uv-common.c
|
||||
@ -562,6 +563,7 @@ if(LIBUV_BUILD_TESTS)
|
||||
test/test-spawn.c
|
||||
test/test-stdio-over-pipes.c
|
||||
test/test-strscpy.c
|
||||
test/test-strtok.c
|
||||
test/test-tcp-alloc-cb-fail.c
|
||||
test/test-tcp-bind-error.c
|
||||
test/test-tcp-bind6-error.c
|
||||
|
||||
@ -43,7 +43,9 @@ libuv_la_SOURCES = src/fs-poll.c \
|
||||
src/uv-data-getter-setters.c \
|
||||
src/uv-common.c \
|
||||
src/uv-common.h \
|
||||
src/version.c
|
||||
src/version.c \
|
||||
src/strtok.c \
|
||||
src/strtok.h
|
||||
|
||||
if SUNOS
|
||||
# Can't be turned into a CC_CHECK_CFLAGS in configure.ac, it makes compilers
|
||||
@ -250,6 +252,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
|
||||
test/test-spawn.c \
|
||||
test/test-stdio-over-pipes.c \
|
||||
test/test-strscpy.c \
|
||||
test/test-strtok.c \
|
||||
test/test-tcp-alloc-cb-fail.c \
|
||||
test/test-tcp-bind-error.c \
|
||||
test/test-tcp-bind6-error.c \
|
||||
|
||||
52
src/strtok.c
Normal file
52
src/strtok.c
Normal file
@ -0,0 +1,52 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "strtok.h"
|
||||
|
||||
char* uv__strtok(char* str, const char* sep, char** itr) {
|
||||
const char* sep_itr;
|
||||
char* tmp;
|
||||
char* start;
|
||||
|
||||
if (str == NULL)
|
||||
start = tmp = *itr;
|
||||
else
|
||||
start = tmp = str;
|
||||
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
|
||||
while (*tmp != '\0') {
|
||||
sep_itr = sep;
|
||||
while (*sep_itr != '\0') {
|
||||
if (*tmp == *sep_itr) {
|
||||
*itr = tmp + 1;
|
||||
*tmp = '\0';
|
||||
return start;
|
||||
}
|
||||
sep_itr++;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
*itr = NULL;
|
||||
return start;
|
||||
}
|
||||
27
src/strtok.h
Normal file
27
src/strtok.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UV_STRTOK_H_
|
||||
#define UV_STRTOK_H_
|
||||
|
||||
char* uv__strtok(char* str, const char* sep, char** itr);
|
||||
|
||||
#endif /* UV_STRTOK_H_ */
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
#include "uv.h"
|
||||
#include "internal.h"
|
||||
#include "strtok.h"
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdio.h> /* printf */
|
||||
@ -1546,6 +1547,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
|
||||
char* cloned_path;
|
||||
char* path_env;
|
||||
char* token;
|
||||
char* itr;
|
||||
|
||||
if (buf == NULL || buflen == NULL || *buflen == 0)
|
||||
return UV_EINVAL;
|
||||
@ -1587,7 +1589,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
|
||||
if (cloned_path == NULL)
|
||||
return UV_ENOMEM;
|
||||
|
||||
token = strtok(cloned_path, ":");
|
||||
token = uv__strtok(cloned_path, ":", &itr);
|
||||
while (token != NULL) {
|
||||
snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, prog);
|
||||
if (realpath(trypath, abspath) == abspath) {
|
||||
@ -1606,7 +1608,7 @@ int uv__search_path(const char* prog, char* buf, size_t* buflen) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
token = strtok(NULL, ":");
|
||||
token = uv__strtok(NULL, ":", &itr);
|
||||
}
|
||||
uv__free(cloned_path);
|
||||
|
||||
|
||||
@ -423,6 +423,7 @@ TEST_DECLARE (fs_invalid_mkdir_name)
|
||||
#endif
|
||||
TEST_DECLARE (fs_get_system_error)
|
||||
TEST_DECLARE (strscpy)
|
||||
TEST_DECLARE (strtok)
|
||||
TEST_DECLARE (threadpool_queue_work_simple)
|
||||
TEST_DECLARE (threadpool_queue_work_einval)
|
||||
TEST_DECLARE (threadpool_multiple_event_loops)
|
||||
@ -1088,6 +1089,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (get_osfhandle_valid_handle)
|
||||
TEST_ENTRY (open_osfhandle_valid_handle)
|
||||
TEST_ENTRY (strscpy)
|
||||
TEST_ENTRY (strtok)
|
||||
TEST_ENTRY (threadpool_queue_work_simple)
|
||||
TEST_ENTRY (threadpool_queue_work_einval)
|
||||
TEST_ENTRY_CUSTOM (threadpool_multiple_event_loops, 0, 0, 60000)
|
||||
|
||||
90
test/test-strtok.c
Normal file
90
test/test-strtok.c
Normal file
@ -0,0 +1,90 @@
|
||||
/* Copyright libuv project contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "uv.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "../src/strtok.h"
|
||||
#include "../src/strtok.c"
|
||||
|
||||
struct strtok_test_case {
|
||||
const char* str;
|
||||
const char* sep;
|
||||
};
|
||||
|
||||
const char* tokens[] = {
|
||||
"abc",
|
||||
NULL,
|
||||
|
||||
"abc",
|
||||
"abf",
|
||||
NULL,
|
||||
|
||||
"This",
|
||||
"is.a",
|
||||
"test",
|
||||
"of",
|
||||
"the",
|
||||
"string",
|
||||
"tokenizer",
|
||||
"function.",
|
||||
NULL,
|
||||
|
||||
"Hello",
|
||||
"This-is-a-nice",
|
||||
"-string",
|
||||
NULL
|
||||
};
|
||||
|
||||
#define ASSERT_STRCMP(x, y) \
|
||||
ASSERT((x != NULL && y != NULL && strcmp(x, y) == 0) || (x == y && x == NULL))
|
||||
|
||||
TEST_IMPL(strtok) {
|
||||
struct strtok_test_case tests[] = {
|
||||
{ "abc", "" },
|
||||
{ "abc.abf", "." },
|
||||
{ "This;is.a:test:of=the/string\\tokenizer-function.", "\\/:;=-" },
|
||||
{ "Hello This-is-a-nice.-string", " ." },
|
||||
};
|
||||
size_t tokens_len = ARRAY_SIZE(tokens);
|
||||
size_t tests_len = ARRAY_SIZE(tests);
|
||||
size_t i;
|
||||
size_t j;
|
||||
char* itr;
|
||||
char* tok_r;
|
||||
char current_test[2048];
|
||||
|
||||
for (i = 0, j = 0; i < tests_len; i += 1) {
|
||||
ASSERT(j < tokens_len);
|
||||
snprintf(current_test, sizeof(current_test), "%s", tests[i].str);
|
||||
tok_r = uv__strtok(current_test, tests[i].sep, &itr);
|
||||
ASSERT_STRCMP(tok_r, tokens[j]);
|
||||
j++;
|
||||
while (tok_r) {
|
||||
ASSERT(j < tokens_len);
|
||||
tok_r = uv__strtok(NULL, tests[i].sep, &itr);
|
||||
ASSERT_STRCMP(tok_r, tokens[j]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user