1
0
mirror of https://github.com/google/cpu_features.git synced 2025-04-27 15:12:30 +02:00

Add JSON output. Fixes #24

This commit is contained in:
Guillaume Chatelet 2018-03-27 15:28:40 +02:00
parent 9b872ce0b2
commit 07fd90d4f5
4 changed files with 229 additions and 110 deletions

View File

@ -74,7 +74,7 @@ add_library(CpuFeature::cpu_features ALIAS cpu_features)
# program : list_cpu_features
#
add_executable(list_cpu_features src/list_cpu_features.c)
add_executable(list_cpu_features src/utils/list_cpu_features.c)
target_link_libraries(list_cpu_features PRIVATE cpu_features)
add_executable(CpuFeature::list_cpu_features ALIAS list_cpu_features)

View File

@ -121,7 +121,12 @@ family : 6 (0x06)
model : 45 (0x2D)
stepping : 7 (0x07)
uarch : INTEL_SNB
flags : aes, avx, sse4_1, sse4_2, ssse3
flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
```
```shell
% ./build/list_cpu_features --json
{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]}
```
<a name="support"></a>

View File

@ -1,108 +0,0 @@
// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpu_features_macros.h"
#include "cpuinfo_aarch64.h"
#include "cpuinfo_arm.h"
#include "cpuinfo_mips.h"
#include "cpuinfo_x86.h"
// Prints a named numeric value in both decimal and hexadecimal.
void PrintN(const char* field, int value) {
printf("%-15s : %3d (0x%02X)\n", field, value, value);
}
// Prints a named string.
void PrintS(const char* field, const char* value) {
printf("%-15s : %s\n", field, value);
}
static int cmp(const void* p1, const void* p2) {
return strcmp(*(const char* const*)p1, *(const char* const*)p2);
}
#define DEFINE_PRINT_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
void PrintFlags(const FeatureType* features) { \
size_t i; \
const char* ptrs[LastEnum] = {0}; \
size_t count = 0; \
for (i = 0; i < LastEnum; ++i) { \
if (HasFeature(features, i)) { \
ptrs[count] = FeatureName(i); \
++count; \
} \
} \
qsort(ptrs, count, sizeof(char*), cmp); \
printf("%-15s : ", "flags"); \
for (i = 0; i < count; ++i) { \
if (i > 0) printf(", "); \
printf("%s", ptrs[i]); \
} \
printf("\n"); \
}
#if defined(CPU_FEATURES_ARCH_X86)
DEFINE_PRINT_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
X86_LAST_)
#elif defined(CPU_FEATURES_ARCH_ARM)
DEFINE_PRINT_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
ARM_LAST_)
#elif defined(CPU_FEATURES_ARCH_AARCH64)
DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
Aarch64Features, AARCH64_LAST_)
#elif defined(CPU_FEATURES_ARCH_MIPS)
DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
MipsFeatures, MIPS_LAST_)
#endif
int main(int argc, char** argv) {
#if defined(CPU_FEATURES_ARCH_X86)
char brand_string[49];
const X86Info info = GetX86Info();
FillX86BrandString(brand_string);
PrintS("arch", "x86");
PrintS("brand", brand_string);
PrintN("family", info.family);
PrintN("model", info.model);
PrintN("stepping", info.stepping);
PrintS("uarch", GetX86MicroarchitectureName(GetX86Microarchitecture(&info)));
PrintFlags(&info.features);
#elif defined(CPU_FEATURES_ARCH_ARM)
const ArmInfo info = GetArmInfo();
PrintS("arch", "ARM");
PrintN("implementer", info.implementer);
PrintN("architecture", info.architecture);
PrintN("variant", info.variant);
PrintN("part", info.part);
PrintN("revision", info.revision);
PrintFlags(&info.features);
#elif defined(CPU_FEATURES_ARCH_AARCH64)
const Aarch64Info info = GetAarch64Info();
PrintS("arch", "aarch64");
PrintN("implementer", info.implementer);
PrintN("variant", info.variant);
PrintN("part", info.part);
PrintN("revision", info.revision);
PrintFlags(&info.features);
#elif defined(CPU_FEATURES_ARCH_MIPS)
const MipsInfo info = GetMipsInfo();
PrintS("arch", "mips");
PrintFlags(&info.features);
#endif
return 0;
}

View File

@ -0,0 +1,222 @@
// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cpu_features_macros.h"
#include "cpuinfo_aarch64.h"
#include "cpuinfo_arm.h"
#include "cpuinfo_mips.h"
#include "cpuinfo_x86.h"
static void PrintEscapedAscii(const char* str) {
putchar('"');
for (; str && *str; ++str) {
switch (*str) {
case '\"':
case '\\':
case '/':
case '\b':
case '\f':
case '\n':
case '\r':
case '\t':
putchar('\\');
}
putchar(*str);
}
putchar('"');
}
static void PrintVoid(void) {}
static void PrintComma(void) { putchar(','); }
static void PrintLineFeed(void) { putchar('\n'); }
static void PrintOpenBrace(void) { putchar('{'); }
static void PrintCloseBrace(void) { putchar('}'); }
static void PrintOpenBracket(void) { putchar('['); }
static void PrintCloseBracket(void) { putchar(']'); }
static void PrintString(const char* field) { printf("%s", field); }
static void PrintAlignedHeader(const char* field) { printf("%-15s : ", field); }
static void PrintIntValue(int value) { printf("%d", value); }
static void PrintDecHexValue(int value) {
printf("%3d (0x%02X)", value, value);
}
static void PrintJsonHeader(const char* field) {
PrintEscapedAscii(field);
putchar(':');
}
typedef struct {
void (*Start)(void);
void (*ArrayStart)(void);
void (*ArraySeparator)(void);
void (*ArrayEnd)(void);
void (*PrintString)(const char* value);
void (*PrintValue)(int value);
void (*EndField)(void);
void (*StartField)(const char* field);
void (*End)(void);
} Printer;
static Printer getJsonPrinter(void) {
return (Printer){
.Start = &PrintOpenBrace,
.ArrayStart = &PrintOpenBracket,
.ArraySeparator = &PrintComma,
.ArrayEnd = &PrintCloseBracket,
.PrintString = &PrintEscapedAscii,
.PrintValue = &PrintIntValue,
.EndField = &PrintComma,
.StartField = &PrintJsonHeader,
.End = &PrintCloseBrace,
};
}
static Printer getTextPrinter(void) {
return (Printer){
.Start = &PrintVoid,
.ArrayStart = &PrintVoid,
.ArraySeparator = &PrintComma,
.ArrayEnd = &PrintVoid,
.PrintString = &PrintString,
.PrintValue = &PrintDecHexValue,
.EndField = &PrintLineFeed,
.StartField = &PrintAlignedHeader,
.End = &PrintVoid,
};
}
// Prints a named numeric value in both decimal and hexadecimal.
static void PrintN(const Printer p, const char* field, int value) {
p.StartField(field);
p.PrintValue(value);
p.EndField();
}
// Prints a named string.
static void PrintS(const Printer p, const char* field, const char* value) {
p.StartField(field);
p.PrintString(value);
p.EndField();
}
static int cmp(const void* p1, const void* p2) {
return strcmp(*(const char* const*)p1, *(const char* const*)p2);
}
#define DEFINE_PRINT_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
static void PrintFlags(const Printer p, const FeatureType* features) { \
size_t i; \
const char* ptrs[LastEnum] = {0}; \
size_t count = 0; \
for (i = 0; i < LastEnum; ++i) { \
if (HasFeature(features, i)) { \
ptrs[count] = FeatureName(i); \
++count; \
} \
} \
qsort(ptrs, count, sizeof(char*), cmp); \
p.StartField("flags"); \
p.ArrayStart(); \
for (i = 0; i < count; ++i) { \
if (i > 0) p.ArraySeparator(); \
p.PrintString(ptrs[i]); \
} \
p.ArrayEnd(); \
}
#if defined(CPU_FEATURES_ARCH_X86)
DEFINE_PRINT_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
X86_LAST_)
#elif defined(CPU_FEATURES_ARCH_ARM)
DEFINE_PRINT_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
ARM_LAST_)
#elif defined(CPU_FEATURES_ARCH_AARCH64)
DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
Aarch64Features, AARCH64_LAST_)
#elif defined(CPU_FEATURES_ARCH_MIPS)
DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
MipsFeatures, MIPS_LAST_)
#endif
static void PrintFeatures(const Printer printer) {
#if defined(CPU_FEATURES_ARCH_X86)
char brand_string[49];
const X86Info info = GetX86Info();
FillX86BrandString(brand_string);
PrintS(printer, "arch", "x86");
PrintS(printer, "brand", brand_string);
PrintN(printer, "family", info.family);
PrintN(printer, "model", info.model);
PrintN(printer, "stepping", info.stepping);
PrintS(printer, "uarch",
GetX86MicroarchitectureName(GetX86Microarchitecture(&info)));
PrintFlags(printer, &info.features);
#elif defined(CPU_FEATURES_ARCH_ARM)
const ArmInfo info = GetArmInfo();
PrintS(printer, "arch", "ARM");
PrintN(printer, "implementer", info.implementer);
PrintN(printer, "architecture", info.architecture);
PrintN(printer, "variant", info.variant);
PrintN(printer, "part", info.part);
PrintN(printer, "revision", info.revision);
PrintFlags(printer, &info.features);
#elif defined(CPU_FEATURES_ARCH_AARCH64)
const Aarch64Info info = GetAarch64Info();
PrintS(printer, "arch", "aarch64");
PrintN(printer, "implementer", info.implementer);
PrintN(printer, "variant", info.variant);
PrintN(printer, "part", info.part);
PrintN(printer, "revision", info.revision);
PrintFlags(printer, &info.features);
#elif defined(CPU_FEATURES_ARCH_MIPS)
const MipsInfo info = GetMipsInfo();
PrintS(printer, "arch", "mips");
PrintFlags(printer, &info.features);
#endif
}
static void showUsage(const char* name) {
printf(
"\n"
"Usage: %s [options]\n"
" Options:\n"
" -h | --help Show help message.\n"
" -j | --json Format output as json instead of plain text.\n"
"\n",
name);
}
int main(int argc, char** argv) {
Printer printer = getTextPrinter();
int i = 1;
for (; i < argc; ++i) {
const char* arg = argv[i];
if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) {
printer = getJsonPrinter();
} else {
showUsage(argv[0]);
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
return EXIT_SUCCESS;
return EXIT_FAILURE;
}
}
printer.Start();
PrintFeatures(printer);
printer.End();
PrintLineFeed();
return EXIT_SUCCESS;
}