From 071b9b13cdb786792a47a925bc952873f6c2a7c5 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Wed, 17 Feb 2021 12:17:06 -0600 Subject: [PATCH] Reverse const_strlen() recursion logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than making the run-time complexity of the algorithm 𝒪(n) where n is the length of the string, make it 𝒪(k) where k is the number of trailing nul bytes. The second parameter `index` with a default non-value is in lieu of a helper function that would have had a name like `count_trailing_nuls()`. --- src/common.h | 11 ++++++++--- src/history_file.cpp | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/common.h b/src/common.h index 3bf06bef1..876e40164 100644 --- a/src/common.h +++ b/src/common.h @@ -731,9 +731,14 @@ static_assert(const_strcmp("a", "aa") < 0, "const_strcmp failure"); static_assert(const_strcmp("b", "aa") > 0, "const_strcmp failure"); /// Compile-time agnostic-size strlen/wcslen implementation. Unicode-unaware. -template -constexpr size_t const_strlen(const T *str) { - return *str == static_cast(0) ? 0 : 1 + const_strlen(str + 1); +template +constexpr size_t const_strlen(const T(&val)[N], ssize_t index = -1) { + // N is the length of the character array, but that includes one **or more** trailing nulls. + return index == -1 ? N - const_strlen(val, N - 1) + // Prevent an underflow in case the string is comprised of all \0 bytes + : index == 0 ? 1 + // Keep back-tracking until a non-null byte is found + : (val[index] == static_cast(0) ? 1 + const_strlen(val, index - 1) : 0); } static_assert(const_strlen("") == 0, "const_strlen failure"); static_assert(const_strlen("hello") == 5, "const_strlen failure"); diff --git a/src/history_file.cpp b/src/history_file.cpp index 7fb0fdc86..dbb177654 100644 --- a/src/history_file.cpp +++ b/src/history_file.cpp @@ -370,7 +370,7 @@ static size_t offset_of_next_item_fish_2_0(const history_file_contents_t &conten // Hackish: fish 1.x rewriting a fish 2.0 history file can produce lines with lots of // leading "- cmd: - cmd: - cmd:". Trim all but one leading "- cmd:". - constexpr const char *double_cmd = "- cmd: - cmd: "; + constexpr const char double_cmd[] = "- cmd: - cmd: "; constexpr const size_t double_cmd_len = const_strlen(double_cmd); while (static_cast(a_newline - line_start) > double_cmd_len && !std::memcmp(line_start, double_cmd, double_cmd_len)) { @@ -380,7 +380,7 @@ static size_t offset_of_next_item_fish_2_0(const history_file_contents_t &conten // Hackish: fish 1.x rewriting a fish 2.0 history file can produce commands like "when: // 123456". Ignore those. - constexpr const char *cmd_when = "- cmd: when:"; + constexpr const char cmd_when[] = "- cmd: when:"; constexpr const size_t cmd_when_len = const_strlen(cmd_when); if (static_cast(a_newline - line_start) >= cmd_when_len && !std::memcmp(line_start, cmd_when, cmd_when_len)) {