diff --git a/include/internal/string_view.h b/include/internal/string_view.h index 64fed40..a109d45 100644 --- a/include/internal/string_view.h +++ b/include/internal/string_view.h @@ -96,7 +96,8 @@ void CpuFeatures_StringView_CopyString(const StringView src, char* dst, // Checks if line contains the specified whitespace separated word. bool CpuFeatures_StringView_HasWord(const StringView line, - const char* const word); + const char* const word, + const char separator); // Get key/value from line. key and value are separated by ": ". // key and value are cleaned up from leading and trailing whitespaces. diff --git a/src/cpuinfo_aarch64.c b/src/cpuinfo_aarch64.c index 62d6905..0b15759 100644 --- a/src/cpuinfo_aarch64.c +++ b/src/cpuinfo_aarch64.c @@ -87,8 +87,8 @@ static bool HandleAarch64Line(const LineResult result, if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { if (CpuFeatures_StringView_IsEquals(key, str("Features"))) { for (size_t i = 0; i < AARCH64_LAST_; ++i) { - kSetters[i](&info->features, - CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + kSetters[i](&info->features, CpuFeatures_StringView_HasWord( + value, kCpuInfoFlags[i], ' ')); } } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) { info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value); diff --git a/src/cpuinfo_arm.c b/src/cpuinfo_arm.c index 0f216bf..05ee399 100644 --- a/src/cpuinfo_arm.c +++ b/src/cpuinfo_arm.c @@ -77,8 +77,8 @@ static bool HandleArmLine(const LineResult result, ArmInfo* const info, if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { if (CpuFeatures_StringView_IsEquals(key, str("Features"))) { for (size_t i = 0; i < ARM_LAST_; ++i) { - kSetters[i](&info->features, - CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + kSetters[i](&info->features, CpuFeatures_StringView_HasWord( + value, kCpuInfoFlags[i], ' ')); } } else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) { info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value); diff --git a/src/cpuinfo_mips.c b/src/cpuinfo_mips.c index 83e959f..887ab9f 100644 --- a/src/cpuinfo_mips.c +++ b/src/cpuinfo_mips.c @@ -37,8 +37,8 @@ static bool HandleMipsLine(const LineResult result, if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) { if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) { for (size_t i = 0; i < MIPS_LAST_; ++i) { - kSetters[i](features, - CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + kSetters[i](features, CpuFeatures_StringView_HasWord( + value, kCpuInfoFlags[i], ' ')); } } } diff --git a/src/cpuinfo_ppc.c b/src/cpuinfo_ppc.c index de82bf2..53dc1d5 100644 --- a/src/cpuinfo_ppc.c +++ b/src/cpuinfo_ppc.c @@ -82,7 +82,7 @@ static bool HandlePPCLine(const LineResult result, StringView line = result.line; StringView key, value; if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { - if (CpuFeatures_StringView_HasWord(key, "platform")) { + if (CpuFeatures_StringView_HasWord(key, "platform", ' ')) { CpuFeatures_StringView_CopyString(value, strings->platform, sizeof(strings->platform)); } else if (CpuFeatures_StringView_IsEquals(key, str("model"))) { diff --git a/src/cpuinfo_x86.c b/src/cpuinfo_x86.c index 6452fc4..9ae2c66 100644 --- a/src/cpuinfo_x86.c +++ b/src/cpuinfo_x86.c @@ -1337,36 +1337,32 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, if (fd >= 0) { StackLineReader reader; StackLineReader_Initialize(&reader, fd); - for (;;) { + for (bool stop = false; !stop;) { const LineResult result = StackLineReader_NextLine(&reader); + if (result.eof) stop = true; const StringView line = result.line; - const bool is_feature = - CpuFeatures_StringView_StartsWith(line, str(" Features=")); - const bool is_feature2 = - CpuFeatures_StringView_StartsWith(line, str(" Features2=")); - if (is_feature || is_feature2) { - // Lines of interests are of the following form: - // " Features=0x1783fbff" - // We replace '<', '>' and ',' with space so we can search by - // whitespace separated word. - // TODO: Fix CpuFeatures_StringView_HasWord to allow for different - // separators. - for (size_t i = 0; i < line.size; ++i) { - char* c = (char*)(&(line.ptr[i])); - if (*c == '<' || *c == '>' || *c == ',') *c = ' '; - } - if (is_feature) { - features->sse = CpuFeatures_StringView_HasWord(line, "SSE"); - features->sse2 = CpuFeatures_StringView_HasWord(line, "SSE2"); - } - if (is_feature2) { - features->sse3 = CpuFeatures_StringView_HasWord(line, "SSE3"); - features->ssse3 = CpuFeatures_StringView_HasWord(line, "SSSE3"); - features->sse4_1 = CpuFeatures_StringView_HasWord(line, "SSE4.1"); - features->sse4_2 = CpuFeatures_StringView_HasWord(line, "SSE4.2"); - } - } - if (result.eof) break; + if (!CpuFeatures_StringView_StartsWith(line, str(" Features"))) + continue; + // Lines of interests are of the following form: + // " Features=0x1783fbff" + // We first extract the comma separated values between angle brackets. + StringView csv = result.line; + int index = CpuFeatures_StringView_IndexOfChar(csv, '<'); + if (index >= 0) csv = CpuFeatures_StringView_PopFront(csv, index + 1); + if (csv.size > 0 && CpuFeatures_StringView_Back(csv) == '>') + csv = CpuFeatures_StringView_PopBack(csv, 1); + if (CpuFeatures_StringView_HasWord(csv, "SSE", ',')) + features->sse = true; + if (CpuFeatures_StringView_HasWord(csv, "SSE2", ',')) + features->sse2 = true; + if (CpuFeatures_StringView_HasWord(csv, "SSE3", ',')) + features->sse3 = true; + if (CpuFeatures_StringView_HasWord(csv, "SSSE3", ',')) + features->ssse3 = true; + if (CpuFeatures_StringView_HasWord(csv, "SSE4.1", ',')) + features->sse4_1 = true; + if (CpuFeatures_StringView_HasWord(csv, "SSE4.2", ',')) + features->sse4_2 = true; } CpuFeatures_CloseFile(fd); } @@ -1376,22 +1372,21 @@ static void ParseCpuId(const uint32_t max_cpuid_leaf, X86Info* info, if (fd >= 0) { StackLineReader reader; StackLineReader_Initialize(&reader, fd); - for (;;) { + for (bool stop = false; !stop;) { const LineResult result = StackLineReader_NextLine(&reader); + if (result.eof) stop = true; const StringView line = result.line; StringView key, value; - if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) { - if (CpuFeatures_StringView_IsEquals(key, str("flags"))) { - features->sse = CpuFeatures_StringView_HasWord(value, "sse"); - features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2"); - features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3"); - features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3"); - features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1"); - features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2"); - break; - } - } - if (result.eof) break; + if (!CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) + continue; + if (!CpuFeatures_StringView_IsEquals(key, str("flags"))) continue; + features->sse = CpuFeatures_StringView_HasWord(value, "sse", ' '); + features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2", ' '); + features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3", ' '); + features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3", ' '); + features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1", ' '); + features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2", ' '); + break; } CpuFeatures_CloseFile(fd); } diff --git a/src/string_view.c b/src/string_view.c index dc3158f..a20585c 100644 --- a/src/string_view.c +++ b/src/string_view.c @@ -144,7 +144,8 @@ void CpuFeatures_StringView_CopyString(const StringView src, char* dst, } bool CpuFeatures_StringView_HasWord(const StringView line, - const char* const word_str) { + const char* const word_str, + const char separator) { const StringView word = str(word_str); StringView remainder = line; for (;;) { @@ -157,9 +158,9 @@ bool CpuFeatures_StringView_HasWord(const StringView line, const StringView after = CpuFeatures_StringView_PopFront(line, index_of_word + word.size); const bool valid_before = - before.size == 0 || CpuFeatures_StringView_Back(before) == ' '; + before.size == 0 || CpuFeatures_StringView_Back(before) == separator; const bool valid_after = - after.size == 0 || CpuFeatures_StringView_Front(after) == ' '; + after.size == 0 || CpuFeatures_StringView_Front(after) == separator; if (valid_before && valid_after) return true; remainder = CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size); diff --git a/test/string_view_test.cc b/test/string_view_test.cc index ca3e023..772ac3f 100644 --- a/test/string_view_test.cc +++ b/test/string_view_test.cc @@ -163,15 +163,25 @@ TEST(StringViewTest, CpuFeatures_StringView_CopyString) { TEST(StringViewTest, CpuFeatures_StringView_HasWord) { // Find flags at beginning, middle and end. EXPECT_TRUE( - CpuFeatures_StringView_HasWord(str("first middle last"), "first")); + CpuFeatures_StringView_HasWord(str("first middle last"), "first", ' ')); EXPECT_TRUE( - CpuFeatures_StringView_HasWord(str("first middle last"), "middle")); - EXPECT_TRUE(CpuFeatures_StringView_HasWord(str("first middle last"), "last")); + CpuFeatures_StringView_HasWord(str("first middle last"), "middle", ' ')); + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first middle last"), "last", ' ')); + // Find flags at beginning, middle and end with a different separator + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first-middle-last"), "first", '-')); + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first-middle-last"), "middle", '-')); + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first-middle-last"), "last", '-')); // Do not match partial flags EXPECT_FALSE( - CpuFeatures_StringView_HasWord(str("first middle last"), "irst")); - EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "mid")); - EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "las")); + CpuFeatures_StringView_HasWord(str("first middle last"), "irst", ' ')); + EXPECT_FALSE( + CpuFeatures_StringView_HasWord(str("first middle last"), "mid", ' ')); + EXPECT_FALSE( + CpuFeatures_StringView_HasWord(str("first middle last"), "las", ' ')); } TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue) {