Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,42 @@ ruberoid/local.properties
ruberoid/proguard-project.txt
ruberoid/project.properties
rapidjson

# Bazel
MODULE.bazel.lock
# Ignore backup files.
*~
# Ignore Vim swap files.
.*.swp
# macOS-specific excludes
.DS_Store
# Ignore files generated by IDEs.
/.aswb/
/.bazelbsp/
/.cache/
/.classpath
/.clwb/
/.factorypath
/.idea/
/.ijwb/
/.project
/.settings
/.vscode/
.eclipse/
.settings/
.classpath
.project
eclipse-*bin/
/bazel.iml
# Ignore all bazel-* symlinks. There is no full list since this can change
# based on the name of the directory bazel is cloned into.
/bazel-*
# Ignore outputs generated during Bazel bootstrapping.
/output/
# Ignore jekyll build output.
/production
/.sass-cache
# Bazelisk version file
.bazelversion
# User-specific .bazelrc
user.bazelrc
82 changes: 82 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load("//:tools.bzl", "download_data")

cc_library(
name = "gason",
srcs = ["src/gason.cpp"],
hdrs = ["src/gason.h"],
includes = ["src"], # Expose for import without src prefix
visibility = ["//visibility:public"],
)

cc_binary(
name = "pretty-print",
srcs = ["src/pretty-print.cpp"],
deps = [":gason"],
)

test_suite(
name = "all_tests",
tests = [
"benchmark",
"test-suite",
],
)

COPTS = select({
"@platforms//os:windows": [],
"//conditions:default": [
"-g", # Debug symbols
"-Wall", # All warnings
],
})

cc_test(
name = "test-suite",
size = "small",
srcs = ["src/test-suite.cpp"],
copts = COPTS,
deps = [":gason"],
)

# NOTE: To see benchmark output, use `bazel test //:benchmark --test_output=all`
cc_test(
name = "benchmark",
size = "small",
srcs = ["src/benchmark.cpp"],
args = [
"$(location :canada_data)",
"$(location :big_data)",
"$(location :citm_catalog_data)",
"-n",
"10",
],
copts = COPTS,
data = [
":big_data",
":canada_data",
":citm_catalog_data",
],
deps = [
":gason",
"@rapidjson",
],
)

download_data(
name = "canada_data",
sha256 = "bfbc12b8b6da35cdcc15046304be1739a82a335de17ef9959ea3dd75225467a4",
url = "https://raw.githubusercontent.com/mloskot/json_benchmark/master/data/canada.json",
)

download_data(
name = "big_data",
sha256 = "73b421d426fd561d0828970a46ccfe2a6e7213c97079676fb8574d4cd42f6527",
url = "https://raw.githubusercontent.com/Newbilius/big_json_import_demo/master/test_data/big.json",
)

download_data(
name = "citm_catalog_data",
sha256 = "a73e7a883f6ea8de113dff59702975e60119b4b58d451d518a929f31c92e2059",
url = "https://raw.githubusercontent.com/RichardHightower/json-parsers-benchmark/master/data/citm_catalog.json",
)
16 changes: 16 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Module: gason
Purpose: Provides the gason library compileable as a Bazel target. Includes unit and performance tests through Bazel
Note: pretty-print is also supplied buildable to a binary for testing/example
"""

module(
name = "gason",
version = "1.0.1-0.20211018144204-c9c4aa632bd3",
compatibility_level = 1,
)

bazel_dep(name = "rules_cc", version = "0.1.1")
bazel_dep(name = "platforms", version = "0.0.11")

bazel_dep(name = "rapidjson", version = "1.1.0.bcr.20241007", dev_dependency = True) # For comparison benchmarking test
18 changes: 16 additions & 2 deletions src/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,10 @@ static void print(const Stat &stat) {
#define COMPILER "Clang " __clang_version__
#elif defined(__GNUC__)
#define COMPILER "GCC " __VERSION__
#elif defined(_MSC_VER)
#define COMPILER "MSVC"
#else
#define COMPILER "Unknown"
#endif

#ifndef __x86_64__
Expand All @@ -222,19 +226,29 @@ static void print(const Stat &stat) {
#endif

int main(int argc, const char **argv) {
printf("gason benchmark, %s, x86_64 %d, SIZEOF_POINTER %d, NDEBUG %d\n", COMPILER, __x86_64__, __SIZEOF_POINTER__, NDEBUG);
printf("argc: %d\n", argc);
for (int i = 0; i < argc; ++i) {
printf("argv[%d]: %s\n", i, argv[i]);
}

printf("gason benchmark, %s, x86_64 %d, SIZEOF_POINTER %zu, NDEBUG %d\n", COMPILER, __x86_64__, sizeof(void*), NDEBUG);

printf("%7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s\n",
"Number", "String", "Object", "Array", "False", "True", "Null", "Size", "Update", "Parse", "Speed");

size_t iterations = 10;
if (argc < 2) {
fprintf(stderr, "Error: No input file specified\n");
return 1;
}

for (int i = 1; i < argc; ++i) {
if (!strcmp("-n", argv[i])) {
iterations = strtol(argv[++i], NULL, 0);
continue;
}

FILE *fp = fopen(argv[i], "r");
FILE *fp = fopen(argv[i], "rb");
if (!fp) {
perror(argv[i]);
exit(EXIT_FAILURE);
Expand Down
8 changes: 4 additions & 4 deletions src/test-suite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,9 @@ break"])json");
,"rosebud"])json");

if (failed)
fprintf(stderr, "%d/%d TESTS FAILED\n", failed, parsed);
{ fprintf(stderr, "%d/%d TESTS FAILED\n", failed, parsed);
return 1;}
else
fprintf(stderr, "ALL TESTS PASSED\n");

return 0;
{fprintf(stderr, "ALL TESTS PASSED\n");
return 0;}
}
64 changes: 64 additions & 0 deletions tools.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Rule for downloading and verifying test data"""

def _download_data_impl(ctx):
# Fetch the URL and SHA-256 from attributes
url = ctx.attr.url
expected_sha256 = ctx.attr.sha256
output_file = ctx.actions.declare_file(ctx.label.name + ".json") # Downloaded file
hash_output = ctx.actions.declare_file(ctx.label.name + ".sha256") # File to store computed hash

# Determine if we're on Windows based on the host platform
is_windows = ctx.var.get("HOST_OS", "linux").lower() == "windows"

if is_windows:
# Windows-specific commands
download_command = 'curl -L "%s" -o "%s"' % (url, output_file.path)

# Use certutil for SHA256 on Windows
hash_command = 'certutil -hashfile "%s" SHA256 | findstr /v "hash" > "%s"' % (output_file.path, hash_output.path)
verify_command = """
set /p computed=<"%s"
set "computed=!computed: =!"
if /i "!computed!" NEQ "%s" (
echo SHA-256 mismatch!
echo Expected: %s
echo Got: !computed!
exit /b 1
)
""" % (hash_output.path, expected_sha256, expected_sha256)
full_command = " && ".join([download_command, hash_command, verify_command])
else:
# Unix-specific commands
download_command = "curl -s %s -o %s" % (url, output_file.path)
hash_command = "openssl dgst -sha256 %s | cut -d' ' -f2 > %s" % (output_file.path, hash_output.path)
verify_command = """
computed=$(cat %s)
if [ "$computed" != "%s" ]; then
echo "SHA-256 mismatch!"
echo "Expected: %s"
echo "Got: $computed"
exit 1
fi
""" % (hash_output.path, expected_sha256, expected_sha256)
full_command = " && ".join([download_command, hash_command, verify_command])

# Execute the download and verification
ctx.actions.run_shell(
inputs = [],
outputs = [output_file, hash_output],
command = full_command,
mnemonic = "DownloadAndVerify",
progress_message = "Downloading and verifying test data from %s" % url,
arguments = ["/C" if is_windows else "-c", full_command], # Specify the shell to use
)

# Return the downloaded file as a provider
return [DefaultInfo(files = depset([output_file]))]

download_data = rule(
implementation = _download_data_impl,
attrs = {
"url": attr.string(mandatory = True, doc = "URL of the data file to download"),
"sha256": attr.string(mandatory = True, doc = "Expected SHA-256 checksum of the downloaded file"),
},
)