]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
refactor: Use util::BitSet for hash_source_code_file
authorJoel Rosdahl <joel@rosdahl.net>
Mon, 6 Mar 2023 19:26:06 +0000 (20:26 +0100)
committerJoel Rosdahl <joel@rosdahl.net>
Tue, 7 Mar 2023 19:17:35 +0000 (20:17 +0100)
src/InodeCache.cpp
src/InodeCache.hpp
src/ccache.cpp
src/core/Manifest.cpp
src/hashutil.cpp
src/hashutil.hpp
unittest/test_InodeCache.cpp
unittest/test_hashutil.cpp

index 17e92417769e258bc280a5cc8bf5ca4d125c3927..7610417e2727cf421d86d3949e04186d4d8b1d3d 100644 (file)
@@ -469,7 +469,7 @@ bool
 InodeCache::get(const std::string& path,
                 ContentType type,
                 Digest& file_digest,
-                int* return_value)
+                HashSourceCodeResult* return_value)
 {
   if (!initialize()) {
     return false;
@@ -492,7 +492,8 @@ InodeCache::get(const std::string& path,
 
         file_digest = bucket->entries[0].file_digest;
         if (return_value) {
-          *return_value = bucket->entries[0].return_value;
+          *return_value =
+            HashSourceCodeResult::from_bitmask(bucket->entries[0].return_value);
         }
         found = true;
         break;
@@ -518,7 +519,7 @@ bool
 InodeCache::put(const std::string& path,
                 ContentType type,
                 const Digest& file_digest,
-                int return_value)
+                HashSourceCodeResult return_value)
 {
   if (!initialize()) {
     return false;
@@ -536,7 +537,7 @@ InodeCache::put(const std::string& path,
 
     bucket->entries[0].key_digest = key_digest;
     bucket->entries[0].file_digest = file_digest;
-    bucket->entries[0].return_value = return_value;
+    bucket->entries[0].return_value = return_value.to_bitmask();
   });
 
   if (!success) {
index 5819ed070a17b4bbfb16615b0bb35971e56b510a..eea3b49d662bf56ab2764353d56b976145b87ac5 100644 (file)
@@ -19,6 +19,7 @@
 #pragma once
 
 #include <Fd.hpp>
+#include <hashutil.hpp>
 #include <util/Duration.hpp>
 #include <util/TimePoint.hpp>
 
@@ -79,7 +80,7 @@ public:
   bool get(const std::string& path,
            ContentType type,
            Digest& file_digest,
-           int* return_value = nullptr);
+           HashSourceCodeResult* return_value = nullptr);
 
   // Put hash digest and return value from a successful call to do_hash_file()
   // in hashutil.cpp.
@@ -88,7 +89,7 @@ public:
   bool put(const std::string& path,
            ContentType type,
            const Digest& file_digest,
-           int return_value = 0);
+           HashSourceCodeResult return_value);
 
   // Unmaps the current cache and removes the mapped file from disk.
   //
index 7d3eabdf3bdcc6c1e11e83b9ce598f0252ee185e..9efbd563a21f71ee3cd02ef3b0acbd5d7b5dfaf3 100644 (file)
@@ -394,9 +394,9 @@ do_remember_include_file(Context& ctx,
 
   if (ctx.config.direct_mode()) {
     if (!is_pch) { // else: the file has already been hashed.
-      int result = hash_source_code_file(ctx, file_digest, path);
-      if (result & HASH_SOURCE_CODE_ERROR
-          || result & HASH_SOURCE_CODE_FOUND_TIME) {
+      auto ret = hash_source_code_file(ctx, file_digest, path);
+      if (ret.contains(HashSourceCode::error)
+          || ret.contains(HashSourceCode::found_time)) {
         return false;
       }
     }
@@ -1822,12 +1822,12 @@ get_manifest_key(Context& ctx, Hash& hash)
 
   hash.hash_delimiter("sourcecode hash");
   Digest input_file_digest;
-  int result =
+  auto ret =
     hash_source_code_file(ctx, input_file_digest, ctx.args_info.input_file);
-  if (result & HASH_SOURCE_CODE_ERROR) {
+  if (ret.contains(HashSourceCode::error)) {
     return nonstd::make_unexpected(Statistic::internal_error);
   }
-  if (result & HASH_SOURCE_CODE_FOUND_TIME) {
+  if (ret.contains(HashSourceCode::found_time)) {
     LOG_RAW("Disabling direct mode");
     ctx.config.set_direct_mode(false);
     return {};
index 2137103e9b9b69ef31df58f7955499a55ef0bc46..c1c3e0cd80794d2398588b46626b238c5feb2abd 100644 (file)
@@ -400,12 +400,12 @@ Manifest::result_matches(
     auto hashed_files_iter = hashed_files.find(path);
     if (hashed_files_iter == hashed_files.end()) {
       Digest actual_digest;
-      int ret = hash_source_code_file(ctx, actual_digest, path, fs.size);
-      if (ret & HASH_SOURCE_CODE_ERROR) {
+      auto ret = hash_source_code_file(ctx, actual_digest, path, fs.size);
+      if (ret.contains(HashSourceCode::error)) {
         LOG("Failed hashing {}", path);
         return false;
       }
-      if (ret & HASH_SOURCE_CODE_FOUND_TIME) {
+      if (ret.contains(HashSourceCode::found_time)) {
         return false;
       }
 
index 968384566828ae4283a2dea634c9a09bff2c3a1a..f241903da34f4d0341e8ca0ece0ee58e5d070e56 100644 (file)
 
 namespace {
 
-// Returns one of HASH_SOURCE_CODE_FOUND_DATE, HASH_SOURCE_CODE_FOUND_TIME or
-// HASH_SOURCE_CODE_FOUND_TIMESTAMP if "_DATE__", "_TIME__" or "_TIMESTAMP__"
-// starts at str[pos].
-//
 // Pre-condition: str[pos - 1] == '_'
-int
+HashSourceCode
 check_for_temporal_macros_helper(std::string_view str, size_t pos)
 {
   if (pos + 7 > str.length()) {
-    return 0;
+    return HashSourceCode::ok;
   }
 
-  int found = 0;
+  HashSourceCode found = HashSourceCode::ok;
   int macro_len = 7;
   if (memcmp(&str[pos], "_DATE__", 7) == 0) {
-    found = HASH_SOURCE_CODE_FOUND_DATE;
+    found = HashSourceCode::found_date;
   } else if (memcmp(&str[pos], "_TIME__", 7) == 0) {
-    found = HASH_SOURCE_CODE_FOUND_TIME;
+    found = HashSourceCode::found_time;
   } else if (pos + 12 <= str.length()
              && memcmp(&str[pos], "_TIMESTAMP__", 12) == 0) {
-    found = HASH_SOURCE_CODE_FOUND_TIMESTAMP;
+    found = HashSourceCode::found_timestamp;
     macro_len = 12;
   } else {
-    return 0;
+    return HashSourceCode::ok;
   }
 
   // Check char before and after macro to verify that the found macro isn't part
@@ -89,13 +85,13 @@ check_for_temporal_macros_helper(std::string_view str, size_t pos)
     return found;
   }
 
-  return 0;
+  return HashSourceCode::ok;
 }
 
-int
+HashSourceCodeResult
 check_for_temporal_macros_bmh(std::string_view str, size_t start = 0)
 {
-  int result = 0;
+  HashSourceCodeResult result;
 
   // We're using the Boyer-Moore-Horspool algorithm, which searches starting
   // from the *end* of the needle. Our needles are 8 characters long, so i
@@ -107,7 +103,7 @@ check_for_temporal_macros_bmh(std::string_view str, size_t start = 0)
     // the assumption that 'E' is less common in source than '_', we check
     // str[i-2] first.
     if (str[i - 2] == 'E' && str[i - 7] == '_') {
-      result |= check_for_temporal_macros_helper(str, i - 6);
+      result.insert(check_for_temporal_macros_helper(str, i - 6));
     }
 
     // macro_skip tells us how far we can skip forward upon seeing str[i] at
@@ -120,17 +116,17 @@ check_for_temporal_macros_bmh(std::string_view str, size_t start = 0)
 
 #ifdef HAVE_AVX2
 #  ifndef _MSC_VER // MSVC does not need explicit enabling of AVX2.
-int check_for_temporal_macros_avx2(std::string_view str)
+HashSourceCodeResult check_for_temporal_macros_avx2(std::string_view str)
   __attribute__((target("avx2")));
 #  endif
 
 // The following algorithm, which uses AVX2 instructions to find __DATE__,
 // __TIME__ and __TIMESTAMP__, is heavily inspired by
 // <http://0x80.pl/articles/simd-strfind.html>.
-int
+HashSourceCodeResult
 check_for_temporal_macros_avx2(std::string_view str)
 {
-  int result = 0;
+  HashSourceCodeResult result;
 
   // Set all 32 bytes in first and last to '_' and 'E' respectively.
   const __m256i first = _mm256_set1_epi8('_');
@@ -169,17 +165,17 @@ check_for_temporal_macros_avx2(std::string_view str)
       // Clear the least significant bit set.
       mask = mask & (mask - 1);
 
-      result |= check_for_temporal_macros_helper(str, start);
+      result.insert(check_for_temporal_macros_helper(str, start));
     }
   }
 
-  result |= check_for_temporal_macros_bmh(str, pos);
+  result.insert(check_for_temporal_macros_bmh(str, pos));
 
   return result;
 }
 #endif
 
-int
+HashSourceCodeResult
 do_hash_file(const Context& ctx,
              Digest& digest,
              const std::string& path,
@@ -191,7 +187,7 @@ do_hash_file(const Context& ctx,
     check_temporal_macros ? InodeCache::ContentType::checked_for_temporal_macros
                           : InodeCache::ContentType::raw;
   if (ctx.config.inode_cache()) {
-    int result;
+    HashSourceCodeResult result;
     if (ctx.inode_cache.get(path, content_type, digest, &result)) {
       return result;
     }
@@ -203,12 +199,12 @@ do_hash_file(const Context& ctx,
   const auto data = util::read_file<std::string>(path, size_hint);
   if (!data) {
     LOG("Failed to read {}: {}", path, data.error());
-    return HASH_SOURCE_CODE_ERROR;
+    return HashSourceCodeResult(HashSourceCode::error);
   }
 
-  int result = HASH_SOURCE_CODE_OK;
+  HashSourceCodeResult result;
   if (check_temporal_macros) {
-    result |= check_for_temporal_macros(*data);
+    result.insert(check_for_temporal_macros(*data));
   }
 
   Hash hash;
@@ -224,7 +220,7 @@ do_hash_file(const Context& ctx,
 
 } // namespace
 
-int
+HashSourceCodeResult
 check_for_temporal_macros(std::string_view str)
 {
 #ifdef HAVE_AVX2
@@ -235,7 +231,7 @@ check_for_temporal_macros(std::string_view str)
   return check_for_temporal_macros_bmh(str);
 }
 
-int
+HashSourceCodeResult
 hash_source_code_file(const Context& ctx,
                       Digest& digest,
                       const std::string& path,
@@ -246,12 +242,12 @@ hash_source_code_file(const Context& ctx,
   auto result =
     do_hash_file(ctx, digest, path, size_hint, check_temporal_macros);
 
-  if (!check_temporal_macros || result == HASH_SOURCE_CODE_OK
-      || (result & HASH_SOURCE_CODE_ERROR)) {
+  if (!check_temporal_macros || result.empty()
+      || result.contains(HashSourceCode::error)) {
     return result;
   }
 
-  if (result & HASH_SOURCE_CODE_FOUND_TIME) {
+  if (result.contains(HashSourceCode::found_time)) {
     // We don't know for sure that the program actually uses the __TIME__ macro,
     // but we have to assume it anyway and hash the time stamp. However, that's
     // not very useful since the chance that we get a cache hit later the same
@@ -269,13 +265,14 @@ hash_source_code_file(const Context& ctx,
   Hash hash;
   hash.hash(digest.to_string());
 
-  if (result & HASH_SOURCE_CODE_FOUND_DATE) {
+  if (result.contains(HashSourceCode::found_date)) {
     LOG("Found __DATE__ in {}", path);
 
     hash.hash_delimiter("date");
     auto now = Util::localtime();
     if (!now) {
-      return HASH_SOURCE_CODE_ERROR;
+      result.insert(HashSourceCode::error);
+      return result;
     }
     hash.hash(now->tm_year);
     hash.hash(now->tm_mon);
@@ -291,17 +288,19 @@ hash_source_code_file(const Context& ctx,
     }
   }
 
-  if (result & HASH_SOURCE_CODE_FOUND_TIMESTAMP) {
+  if (result.contains(HashSourceCode::found_timestamp)) {
     LOG("Found __TIMESTAMP__ in {}", path);
 
     const auto stat = Stat::stat(path);
     if (!stat) {
-      return HASH_SOURCE_CODE_ERROR;
+      result.insert(HashSourceCode::error);
+      return result;
     }
 
     auto modified_time = Util::localtime(stat.mtime());
     if (!modified_time) {
-      return HASH_SOURCE_CODE_ERROR;
+      result.insert(HashSourceCode::error);
+      return result;
     }
     hash.hash_delimiter("timestamp");
 #ifdef HAVE_ASCTIME_R
@@ -311,7 +310,8 @@ hash_source_code_file(const Context& ctx,
     auto timestamp = asctime(&*modified_time);
 #endif
     if (!timestamp) {
-      return HASH_SOURCE_CODE_ERROR;
+      result.insert(HashSourceCode::error);
+      return result;
     }
     hash.hash(timestamp);
   }
@@ -326,8 +326,7 @@ hash_binary_file(const Context& ctx,
                  const std::string& path,
                  size_t size_hint)
 {
-  return do_hash_file(ctx, digest, path, size_hint, false)
-         == HASH_SOURCE_CODE_OK;
+  return do_hash_file(ctx, digest, path, size_hint, false).empty();
 }
 
 bool
index d0fd1420a1abb8c1aa5c235c1e039a7b170a9bb7..c270b38e87332954897f54a3414cc38d87702925 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2009-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2009-2023 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -18,6 +18,8 @@
 
 #pragma once
 
+#include <util/BitSet.hpp>
+
 #include <cstddef>
 #include <string>
 #include <string_view>
@@ -27,26 +29,24 @@ class Context;
 class Digest;
 class Hash;
 
-const int HASH_SOURCE_CODE_OK = 0;
-const int HASH_SOURCE_CODE_ERROR = (1 << 0);
-const int HASH_SOURCE_CODE_FOUND_DATE = (1 << 1);
-const int HASH_SOURCE_CODE_FOUND_TIME = (1 << 2);
-const int HASH_SOURCE_CODE_FOUND_TIMESTAMP = (1 << 3);
+enum class HashSourceCode {
+  ok = 0,
+  error = 1U << 0,
+  found_date = 1U << 1,
+  found_time = 1U << 2,
+  found_timestamp = 1U << 3,
+};
 
-// Search for the strings "DATE", "TIME" and "TIMESTAMP" with two surrounding
-// underscores in `str`.
-//
-// Returns a bitmask with HASH_SOURCE_CODE_FOUND_DATE,
-// HASH_SOURCE_CODE_FOUND_TIME and HASH_SOURCE_CODE_FOUND_TIMESTAMP set
-// appropriately.
-int check_for_temporal_macros(std::string_view str);
+using HashSourceCodeResult = util::BitSet<HashSourceCode>;
+
+// Search for tokens (described in HashSourceCode) in `str`.
+HashSourceCodeResult check_for_temporal_macros(std::string_view str);
 
-// Hash a source code file using the inode cache if enabled. Returns a bitmask
-// of HASH_SOURCE_CODE_* results.
-int hash_source_code_file(const Context& ctx,
-                          Digest& digest,
-                          const std::string& path,
-                          size_t size_hint = 0);
+// Hash a source code file using the inode cache if enabled.
+HashSourceCodeResult hash_source_code_file(const Context& ctx,
+                                           Digest& digest,
+                                           const std::string& path,
+                                           size_t size_hint = 0);
 
 // Hash a binary file (using the inode cache if enabled) and put its digest in
 // `digest`
index 5f08f36fb9827a798fd7d46e2f6d5dd1e5cdf7ba..e60a0733a74506923c9624ced17c76f2981ababe 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2020-2023 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -55,7 +55,7 @@ bool
 put(InodeCache& inode_cache,
     const std::string& filename,
     const std::string& str,
-    int return_value)
+    HashSourceCodeResult return_value)
 {
   return inode_cache.put(filename,
                          InodeCache::ContentType::checked_for_temporal_macros,
@@ -77,7 +77,7 @@ TEST_CASE("Test disabled")
   InodeCache inode_cache(config, util::Duration(0));
 
   Digest digest;
-  int return_value;
+  HashSourceCodeResult return_value;
 
   CHECK(!inode_cache.get("a",
                          InodeCache::ContentType::checked_for_temporal_macros,
@@ -103,7 +103,7 @@ TEST_CASE("Test lookup nonexistent")
   util::write_file("a", "");
 
   Digest digest;
-  int return_value;
+  HashSourceCodeResult return_value;
 
   CHECK(!inode_cache.get("a",
                          InodeCache::ContentType::checked_for_temporal_macros,
@@ -124,17 +124,20 @@ TEST_CASE("Test put and lookup")
   InodeCache inode_cache(config, util::Duration(0));
   util::write_file("a", "a text");
 
-  CHECK(put(inode_cache, "a", "a text", 1));
+  HashSourceCodeResult result;
+  result.insert(HashSourceCode::found_date);
+  CHECK(put(inode_cache, "a", "a text", result));
 
   Digest digest;
-  int return_value;
+  HashSourceCodeResult return_value;
 
   CHECK(inode_cache.get("a",
                         InodeCache::ContentType::checked_for_temporal_macros,
                         digest,
                         &return_value));
   CHECK(digest == Hash().hash("a text").digest());
-  CHECK(return_value == 1);
+  CHECK(return_value.to_bitmask()
+        == static_cast<int>(HashSourceCode::found_date));
   CHECK(inode_cache.get_hits() == 1);
   CHECK(inode_cache.get_misses() == 0);
   CHECK(inode_cache.get_errors() == 0);
@@ -149,14 +152,18 @@ TEST_CASE("Test put and lookup")
   CHECK(inode_cache.get_misses() == 1);
   CHECK(inode_cache.get_errors() == 0);
 
-  CHECK(put(inode_cache, "a", "something else", 2));
+  CHECK(put(inode_cache,
+            "a",
+            "something else",
+            HashSourceCodeResult(HashSourceCode::found_time)));
 
   CHECK(inode_cache.get("a",
                         InodeCache::ContentType::checked_for_temporal_macros,
                         digest,
                         &return_value));
   CHECK(digest == Hash().hash("something else").digest());
-  CHECK(return_value == 2);
+  CHECK(return_value.to_bitmask()
+        == static_cast<int>(HashSourceCode::found_time));
   CHECK(inode_cache.get_hits() == 2);
   CHECK(inode_cache.get_misses() == 1);
   CHECK(inode_cache.get_errors() == 0);
@@ -192,24 +199,31 @@ TEST_CASE("Test content type")
   Digest binary_digest = Hash().hash("binary").digest();
   Digest code_digest = Hash().hash("code").digest();
 
-  CHECK(inode_cache.put("a", InodeCache::ContentType::raw, binary_digest, 1));
-  CHECK(inode_cache.put(
-    "a", InodeCache::ContentType::checked_for_temporal_macros, code_digest, 2));
+  CHECK(inode_cache.put("a",
+                        InodeCache::ContentType::raw,
+                        binary_digest,
+                        HashSourceCodeResult(HashSourceCode::found_date)));
+  CHECK(inode_cache.put("a",
+                        InodeCache::ContentType::checked_for_temporal_macros,
+                        code_digest,
+                        HashSourceCodeResult(HashSourceCode::found_time)));
 
   Digest digest;
-  int return_value;
+  HashSourceCodeResult return_value;
 
   CHECK(
     inode_cache.get("a", InodeCache::ContentType::raw, digest, &return_value));
   CHECK(digest == binary_digest);
-  CHECK(return_value == 1);
+  CHECK(return_value.to_bitmask()
+        == static_cast<int>(HashSourceCode::found_date));
 
   CHECK(inode_cache.get("a",
                         InodeCache::ContentType::checked_for_temporal_macros,
                         digest,
                         &return_value));
   CHECK(digest == code_digest);
-  CHECK(return_value == 2);
+  CHECK(return_value.to_bitmask()
+        == static_cast<int>(HashSourceCode::found_time));
 }
 
 TEST_SUITE_END();
index 84199d16403084ef43869d28780b4ae9b4342da5..bb4522c5535b470bb7767b6ffaa206f734abf467 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2010-2022 Joel Rosdahl and other contributors
+// Copyright (C) 2010-2023 Joel Rosdahl and other contributors
 //
 // See doc/AUTHORS.adoc for a complete list of contributors.
 //
@@ -171,70 +171,80 @@ TEST_CASE("check_for_temporal_macros")
     "#define alphabet abcdefghijklmnopqrstuvwxyz\n"
     "a__DATE__";
 
-  CHECK(check_for_temporal_macros(time_start));
-  CHECK(!check_for_temporal_macros(time_start.substr(1)));
-
-  CHECK(check_for_temporal_macros(time_middle.substr(0)));
-  CHECK(check_for_temporal_macros(time_middle.substr(1)));
-  CHECK(check_for_temporal_macros(time_middle.substr(2)));
-  CHECK(check_for_temporal_macros(time_middle.substr(3)));
-  CHECK(check_for_temporal_macros(time_middle.substr(4)));
-  CHECK(check_for_temporal_macros(time_middle.substr(5)));
-  CHECK(check_for_temporal_macros(time_middle.substr(6)));
-  CHECK(check_for_temporal_macros(time_middle.substr(7)));
-
-  CHECK(check_for_temporal_macros(time_end));
-  CHECK(check_for_temporal_macros(time_end.substr(time_end.length() - 8)));
-  CHECK(!check_for_temporal_macros(time_end.substr(time_end.length() - 7)));
-
-  CHECK(check_for_temporal_macros(date_start));
-  CHECK(!check_for_temporal_macros(date_start.substr(1)));
-
-  CHECK(check_for_temporal_macros(date_middle.substr(0)));
-  CHECK(check_for_temporal_macros(date_middle.substr(1)));
-  CHECK(check_for_temporal_macros(date_middle.substr(2)));
-  CHECK(check_for_temporal_macros(date_middle.substr(3)));
-  CHECK(check_for_temporal_macros(date_middle.substr(4)));
-  CHECK(check_for_temporal_macros(date_middle.substr(5)));
-  CHECK(check_for_temporal_macros(date_middle.substr(6)));
-  CHECK(check_for_temporal_macros(date_middle.substr(7)));
-
-  CHECK(check_for_temporal_macros(date_end));
-  CHECK(check_for_temporal_macros(date_end.substr(date_end.length() - 8)));
-  CHECK(!check_for_temporal_macros(date_end.substr(date_end.length() - 7)));
-
-  CHECK(check_for_temporal_macros(timestamp_start));
-  CHECK(!check_for_temporal_macros(timestamp_start.substr(1)));
-
-  CHECK(check_for_temporal_macros(timestamp_middle));
-  CHECK(check_for_temporal_macros(timestamp_middle.substr(1)));
-  CHECK(check_for_temporal_macros(timestamp_middle.substr(2)));
-  CHECK(check_for_temporal_macros(timestamp_middle.substr(3)));
-  CHECK(check_for_temporal_macros(timestamp_middle.substr(4)));
-  CHECK(check_for_temporal_macros(timestamp_middle.substr(5)));
-  CHECK(check_for_temporal_macros(timestamp_middle.substr(6)));
-  CHECK(check_for_temporal_macros(timestamp_middle.substr(7)));
-
-  CHECK(check_for_temporal_macros(timestamp_end));
-  CHECK(check_for_temporal_macros(
-    timestamp_end.substr(timestamp_end.length() - 13)));
-  CHECK(!check_for_temporal_macros(
-    timestamp_end.substr(timestamp_end.length() - 12)));
-
-  CHECK(!check_for_temporal_macros(no_temporal.substr(0)));
-  CHECK(!check_for_temporal_macros(no_temporal.substr(1)));
-  CHECK(!check_for_temporal_macros(no_temporal.substr(2)));
-  CHECK(!check_for_temporal_macros(no_temporal.substr(3)));
-  CHECK(!check_for_temporal_macros(no_temporal.substr(4)));
-  CHECK(!check_for_temporal_macros(no_temporal.substr(5)));
-  CHECK(!check_for_temporal_macros(no_temporal.substr(6)));
-  CHECK(!check_for_temporal_macros(no_temporal.substr(7)));
+  auto check = check_for_temporal_macros;
+
+  CHECK(check(time_start).contains(HashSourceCode::found_time));
+  CHECK(check(time_start.substr(1)).empty());
+
+  CHECK(check(time_middle.substr(0)).contains(HashSourceCode::found_time));
+  CHECK(check(time_middle.substr(1)).contains(HashSourceCode::found_time));
+  CHECK(check(time_middle.substr(2)).contains(HashSourceCode::found_time));
+  CHECK(check(time_middle.substr(3)).contains(HashSourceCode::found_time));
+  CHECK(check(time_middle.substr(4)).contains(HashSourceCode::found_time));
+  CHECK(check(time_middle.substr(5)).contains(HashSourceCode::found_time));
+  CHECK(check(time_middle.substr(6)).contains(HashSourceCode::found_time));
+  CHECK(check(time_middle.substr(7)).contains(HashSourceCode::found_time));
+
+  CHECK(check(time_end).contains(HashSourceCode::found_time));
+  CHECK(check(time_end.substr(time_end.length() - 8))
+          .contains(HashSourceCode::found_time));
+  CHECK(check(time_end.substr(time_end.length() - 7)).empty());
+
+  CHECK(check(date_start).contains(HashSourceCode::found_date));
+  CHECK(check(date_start.substr(1)).empty());
+
+  CHECK(check(date_middle.substr(0)).contains(HashSourceCode::found_date));
+  CHECK(check(date_middle.substr(1)).contains(HashSourceCode::found_date));
+  CHECK(check(date_middle.substr(2)).contains(HashSourceCode::found_date));
+  CHECK(check(date_middle.substr(3)).contains(HashSourceCode::found_date));
+  CHECK(check(date_middle.substr(4)).contains(HashSourceCode::found_date));
+  CHECK(check(date_middle.substr(5)).contains(HashSourceCode::found_date));
+  CHECK(check(date_middle.substr(6)).contains(HashSourceCode::found_date));
+  CHECK(check(date_middle.substr(7)).contains(HashSourceCode::found_date));
+
+  CHECK(check(date_end).contains(HashSourceCode::found_date));
+  CHECK(check(date_end.substr(date_end.length() - 8))
+          .contains(HashSourceCode::found_date));
+  CHECK(check(date_end.substr(date_end.length() - 7)).empty());
+
+  CHECK(check(timestamp_start).contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_start.substr(1)).empty());
+
+  CHECK(check(timestamp_middle).contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_middle.substr(1))
+          .contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_middle.substr(2))
+          .contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_middle.substr(3))
+          .contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_middle.substr(4))
+          .contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_middle.substr(5))
+          .contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_middle.substr(6))
+          .contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_middle.substr(7))
+          .contains(HashSourceCode::found_timestamp));
+
+  CHECK(check(timestamp_end).contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_end.substr(timestamp_end.length() - 13))
+          .contains(HashSourceCode::found_timestamp));
+  CHECK(check(timestamp_end.substr(timestamp_end.length() - 12)).empty());
+
+  CHECK(check(no_temporal.substr(0)).empty());
+  CHECK(check(no_temporal.substr(1)).empty());
+  CHECK(check(no_temporal.substr(2)).empty());
+  CHECK(check(no_temporal.substr(3)).empty());
+  CHECK(check(no_temporal.substr(4)).empty());
+  CHECK(check(no_temporal.substr(5)).empty());
+  CHECK(check(no_temporal.substr(6)).empty());
+  CHECK(check(no_temporal.substr(7)).empty());
 
   for (size_t i = 0; i < temporal_at_avx_boundary.size() - 8; ++i) {
-    CHECK(check_for_temporal_macros(temporal_at_avx_boundary.substr(i)));
+    CHECK(!check(temporal_at_avx_boundary.substr(i)).empty());
   }
   for (size_t i = 0; i < no_temporal_at_avx_boundary.size() - 8; ++i) {
-    CHECK(!check_for_temporal_macros(no_temporal_at_avx_boundary.substr(i)));
+    CHECK(check(no_temporal_at_avx_boundary.substr(i)).empty());
   }
 }