From 460fe7ac9018628fd89d61ba0830fe19c9c7c85a Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Wed, 20 Feb 2019 16:16:30 +0300 Subject: [PATCH] Introduced nxt_file_basename() and nxt_file_dirname(). --- njs/njs_shell.c | 4 +- njs/test/njs_unit_test.c | 100 +++++++++++++++++++++++++++++++++++++-- nxt/nxt_file.c | 59 ++++++++++++++++++----- nxt/nxt_file.h | 3 +- 4 files changed, 150 insertions(+), 16 deletions(-) diff --git a/njs/njs_shell.c b/njs/njs_shell.c index cc274d5c..91bc4092 100644 --- a/njs/njs_shell.c +++ b/njs/njs_shell.c @@ -216,7 +216,9 @@ main(int argc, char **argv) if (!opts.quiet) { if (opts.file != NULL) { - nxt_file_name(&vm_options.file, opts.file); + vm_options.file.start = (u_char *) opts.file; + vm_options.file.length = strlen(opts.file); + nxt_file_basename(&vm_options.file, &vm_options.file); } else { vm_options.file = nxt_string_value("shell"); diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 2672d85f..b1afdb63 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -11994,6 +11994,97 @@ njs_vm_object_alloc_test(njs_vm_t * vm, nxt_bool_t disassemble, } +static nxt_int_t +nxt_file_basename_test(njs_vm_t * vm, nxt_bool_t disassemble, + nxt_bool_t verbose) +{ + nxt_str_t name; + nxt_bool_t success; + nxt_uint_t i; + + static const struct { + nxt_str_t path; + nxt_str_t expected; + } tests[] = { + { nxt_string(""), nxt_string("") }, + { nxt_string("/"), nxt_string("") }, + { nxt_string("/a"), nxt_string("a") }, + { nxt_string("///"), nxt_string("") }, + { nxt_string("///a"), nxt_string("a") }, + { nxt_string("///a/"), nxt_string("") }, + { nxt_string("a"), nxt_string("a") }, + { nxt_string("a/"), nxt_string("") }, + { nxt_string("a//"), nxt_string("") }, + { nxt_string("path/name"), nxt_string("name") }, + { nxt_string("/path/name"), nxt_string("name") }, + { nxt_string("/path/name/"), nxt_string("") }, + }; + + for (i = 0; i < nxt_nitems(tests); i++) { + nxt_file_basename(&tests[i].path, &name); + + success = nxt_strstr_eq(&tests[i].expected, &name); + + if (!success) { + printf("nxt_file_basename_test(\"%.*s\"):\n" + "expected: \"%.*s\"\n got: \"%.*s\"\n", + (int) tests[i].path.length, tests[i].path.start, + (int) tests[i].expected.length, tests[i].expected.start, + (int) name.length, name.start); + return NXT_ERROR; + } + } + + return NXT_OK; +} + + +static nxt_int_t +nxt_file_dirname_test(njs_vm_t * vm, nxt_bool_t disassemble, + nxt_bool_t verbose) +{ + nxt_str_t name; + nxt_bool_t success; + nxt_uint_t i; + + static const struct { + nxt_str_t path; + nxt_str_t expected; + } tests[] = { + { nxt_string(""), nxt_string("") }, + { nxt_string("/"), nxt_string("/") }, + { nxt_string("/a"), nxt_string("/") }, + { nxt_string("///"), nxt_string("///") }, + { nxt_string("///a"), nxt_string("///") }, + { nxt_string("///a/"), nxt_string("///a") }, + { nxt_string("a"), nxt_string("") }, + { nxt_string("a/"), nxt_string("a") }, + { nxt_string("a//"), nxt_string("a") }, + { nxt_string("p1/p2/name"), nxt_string("p1/p2") }, + { nxt_string("/p1/p2/name"), nxt_string("/p1/p2") }, + { nxt_string("/p1/p2///name"), nxt_string("/p1/p2") }, + { nxt_string("/p1/p2/name/"), nxt_string("/p1/p2/name") }, + }; + + for (i = 0; i < nxt_nitems(tests); i++) { + nxt_file_dirname(&tests[i].path, &name); + + success = nxt_strstr_eq(&tests[i].expected, &name); + + if (!success) { + printf("nxt_file_dirname_test(\"%.*s\"):\n" + "expected: \"%.*s\"\n got: \"%.*s\"\n", + (int) tests[i].path.length, tests[i].path.start, + (int) tests[i].expected.length, tests[i].expected.start, + (int) name.length, name.start); + return NXT_ERROR; + } + } + + return NXT_OK; +} + + typedef struct { nxt_int_t (*test)(njs_vm_t *, nxt_bool_t, nxt_bool_t); nxt_str_t name; @@ -12009,10 +12100,13 @@ njs_api_test(nxt_bool_t disassemble, nxt_bool_t verbose) njs_vm_opt_t options; njs_api_test_t *test; - static njs_api_test_t njs_api_test[] = - { + static njs_api_test_t njs_api_test[] = { { njs_vm_object_alloc_test, - nxt_string("njs_vm_object_alloc_test") } + nxt_string("njs_vm_object_alloc_test") }, + { nxt_file_basename_test, + nxt_string("nxt_file_basename_test") }, + { nxt_file_dirname_test, + nxt_string("nxt_file_dirname_test") }, }; rc = NXT_ERROR; diff --git a/nxt/nxt_file.c b/nxt/nxt_file.c index 2bf3aae3..4552e484 100644 --- a/nxt/nxt_file.c +++ b/nxt/nxt_file.c @@ -14,20 +14,57 @@ void -nxt_file_name(nxt_str_t *name, char *path) +nxt_file_basename(const nxt_str_t *path, nxt_str_t *name) { - char *p; - size_t length; + const u_char *p, *end; - length = strlen(path); + end = path->start + path->length; + p = end - 1; - for (p = path + length; p >= path; p--) { - if (*p == '/') { - p++; - break; - } - } + /* Stripping dir prefix. */ + + while (p >= path->start && *p != '/') { p--; } + + p++; name->start = (u_char *) p; - name->length = length - (p - path); + name->length = end - p; +} + + +void +nxt_file_dirname(const nxt_str_t *path, nxt_str_t *name) +{ + const u_char *p, *end; + + if (path->length == 0) { + *name = nxt_string_value(""); + return; + } + + p = path->start + path->length - 1; + + /* Stripping basename. */ + + while (p >= path->start && *p != '/') { p--; } + + end = p + 1; + + if (end == path->start) { + *name = nxt_string_value(""); + return; + } + + /* Stripping trailing slashes. */ + + while (p >= path->start && *p == '/') { p--; } + + p++; + + if (p == path->start) { + p = end; + } + + name->start = path->start; + name->length = p - path->start; } diff --git a/nxt/nxt_file.h b/nxt/nxt_file.h index 545c5a0a..3c603cc8 100644 --- a/nxt/nxt_file.h +++ b/nxt/nxt_file.h @@ -8,7 +8,8 @@ #define _NXT_FILE_H_INCLUDED_ -void nxt_file_name(nxt_str_t *name, char *path); +void nxt_file_basename(const nxt_str_t *path, nxt_str_t *name); +void nxt_file_dirname(const nxt_str_t *path, nxt_str_t *name); #endif /* _NXT_FILE_H_INCLUDED_ */ -- 2.47.3