Skip to content

Set the stream locale to "C" locally #724

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 2, 2024
Merged
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ libjsonnet++.so
libjsonnet++.so.*
libjsonnet_test_file
libjsonnet_test_snippet
libjsonnet_test_locale
**/core.*
**/vgcore
**/vgcore.*
Expand Down
5 changes: 1 addition & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,6 @@ if (BUILD_TESTS)
# target runs tests without building them.
add_custom_target(run_tests COMMAND ${CMAKE_CTEST_COMMAND}
DEPENDS libjsonnet_test libjsonnet_test_file libjsonnet_test_snippet
jsonnet parser_test lexer_test libjsonnet++_test
jsonnet parser_test lexer_test libjsonnet++_test libjsonnet_test_locale
)

endif()


14 changes: 12 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ LIBS = \
ALL = \
libjsonnet_test_snippet \
libjsonnet_test_file \
libjsonnet_test_locale \
$(BINS) \
$(LIBS) \
$(LIB_OBJ) \
Expand Down Expand Up @@ -133,7 +134,7 @@ install: bins libs

all: $(ALL)

test: jsonnet jsonnetfmt libjsonnet.so libjsonnet_test_snippet libjsonnet_test_file
test: jsonnet jsonnetfmt libjsonnet.so libjsonnet_test_snippet libjsonnet_test_file libjsonnet_test_locale
./tests.sh

reformat:
Expand All @@ -146,7 +147,8 @@ MAKEDEPEND_SRCS = \
cmd/jsonnet.cpp \
cmd/jsonnetfmt.cpp \
core/libjsonnet_test_snippet.c \
core/libjsonnet_test_file.c
core/libjsonnet_test_file.c \
cpp/libjsonnet_test_locale.cpp

depend: core/std.jsonnet.h
rm -f Makefile.depend
Expand Down Expand Up @@ -196,6 +198,14 @@ LIBJSONNET_TEST_FILE_SRCS = \
libjsonnet_test_file: $(LIBJSONNET_TEST_FILE_SRCS)
$(CC) $(CFLAGS) $(LDFLAGS) $< -L. -ljsonnet -o $@

LIBJSONNET_TEST_LOCALE_SRCS = \
cpp/libjsonnet_test_locale.cpp \
libjsonnet++.so \
include/libjsonnet++.h

libjsonnet_test_locale: $(LIBJSONNET_TEST_LOCALE_SRCS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $< -L. -ljsonnet++ -o $@

# Encode standard library for embedding in C
core/%.jsonnet.h: stdlib/%.jsonnet
(($(OD) -v -Anone -t u1 $< \
Expand Down
4 changes: 4 additions & 0 deletions core/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ limitations under the License.
#include <memory>
#include <set>
#include <sstream>
#include <locale>
#include <string>

#include "ast.h"
Expand All @@ -36,6 +37,9 @@ namespace jsonnet::internal {
std::string jsonnet_unparse_number(double v)
{
std::stringstream ss;
// Make sure we output the same thing, even if the user
// of the library changed the global locale
ss.imbue(std::locale::classic());
if (v == floor(v)) {
ss << std::fixed << std::setprecision(0) << v;
} else {
Expand Down
3 changes: 3 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ if (BUILD_TESTS)
add_test_executablepp(libjsonnet++_test)
# Run this in the source tree because it needs to access testdata files.
add_test(NAME libjsonnet++_test COMMAND ${GLOBAL_OUTPUT_PATH}/libjsonnet++_test WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/..")

add_test_executablepp(libjsonnet_test_locale)
add_test(NAME libjsonnet_test_locale COMMAND ${GLOBAL_OUTPUT_PATH}/libjsonnet_test_locale WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/..")
endif()
40 changes: 40 additions & 0 deletions cpp/libjsonnet_test_locale.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include <iostream>
#include <sstream>
#include <locale>
#include <cassert>
#include <libjsonnet++.h>

// Regression test for the follwing issue: https://github.com/google/jsonnet/issues/722

// Define a custom numpunct facet, so that we don't rely on any particular locale
// being available on the system where the test is built and run.
class Punctuator : public std::numpunct<char> {
protected:
virtual char do_decimal_point() const override { return '!'; }
virtual std::string do_grouping() const override { return "\1\2"; }
virtual char do_thousands_sep() const override { return '\''; }
};

int main() {
std::string templatedJSONString { "20000.5" };
Punctuator punctuator;
std::locale glocale(std::locale::classic(), &punctuator);
std::locale::global(glocale);

// Self-test to make sure the custom global locale is actually being applied.
std::ostringstream ss;
ss << 20000.5;
assert(ss.str() == "20'00'0!5");

jsonnet::Jsonnet jsonnet {};
jsonnet.init();

std::string expanded;
if (!jsonnet.evaluateSnippet("", templatedJSONString, &expanded)) {
std::cerr << "Error parsing Jsonnet: "+jsonnet.lastError();
exit(1);
}
std::string expected = "20000.5\n";
assert(expected == expanded);
return 0;
}
2 changes: 2 additions & 0 deletions tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ if [ -z "$DISABLE_LIB_TESTS" ]; then
LD_LIBRARY_PATH=. ./libjsonnet_test_snippet "${TEST_SNIPPET}" || FAIL=TRUE
printf 'libjsonnet_test_file: '
LD_LIBRARY_PATH=. ./libjsonnet_test_file "test_suite/object.jsonnet" || FAIL=TRUE
echo -n 'libjsonnet_test_locale: '
LD_LIBRARY_PATH=. ./libjsonnet_test_locale || FAIL=TRUE
fi
examples/check.sh || FAIL=TRUE
examples/terraform/check.sh || FAIL=TRUE
Expand Down