Skip to content

Commit 0ac9e69

Browse files
committed
Add preliminary C++ API.
This change also adds an external dependency for gmock to the Bazel build, which is used by the C++ library's unit test. Issue #71
1 parent c46d01d commit 0ac9e69

18 files changed

+606
-111482
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
jsonnet
1111
_jsonnet.so
1212
libjsonnet.so
13+
libjsonnet++.so
1314
libjsonnet.js
1415
libjsonnet_test_file
1516
libjsonnet_test_snippet

BUILD

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ filegroup(
88
genrule(
99
name = "gen-std-jsonnet-h",
1010
srcs = ["stdlib/std.jsonnet"],
11-
outs = ["core/std.jsonnet.h"],
11+
outs = ["std.jsonnet.h"],
1212
cmd = "((od -v -Anone -t u1 $< | tr \" \" \"\n\" | grep -v \"^$$\" " +
1313
"| tr \"\n\" \",\" ) && echo \"0\") > $@; " +
1414
"echo >> $@",
@@ -19,12 +19,13 @@ cc_library(
1919
srcs = [
2020
"core/desugarer.cpp",
2121
"core/formatter.cpp",
22+
"core/libjsonnet.cpp",
2223
"core/lexer.cpp",
2324
"core/parser.cpp",
2425
"core/static_analysis.cpp",
2526
"core/string_utils.cpp",
2627
"core/vm.cpp",
27-
"core/std.jsonnet.h",
28+
"std.jsonnet.h",
2829
],
2930
hdrs = [
3031
"core/ast.h",
@@ -38,17 +39,24 @@ cc_library(
3839
"core/string_utils.h",
3940
"core/unicode.h",
4041
"core/vm.h",
41-
"include/libjsonnet.h",
42+
],
43+
deps = [
44+
"//include:libjsonnet",
4245
],
4346
linkopts = ["-lm"],
44-
includes = ["core", "include"],
47+
includes = [
48+
"core",
49+
"include",
50+
],
4551
)
4652

4753
cc_library(
4854
name = "libjsonnet",
4955
srcs = ["core/libjsonnet.cpp"],
50-
hdrs = ["include/libjsonnet.h"],
51-
deps = [":jsonnet-common"],
56+
deps = [
57+
":jsonnet-common",
58+
"//include:libjsonnet",
59+
],
5260
includes = ["include"],
5361
)
5462

Makefile

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,24 @@ LIB_SRC = \
5050
core/static_analysis.cpp \
5151
core/string_utils.cpp \
5252
core/vm.cpp
53+
5354
LIB_OBJ = $(LIB_SRC:.cpp=.o)
5455

56+
LIB_CPP_SRC = \
57+
cpp/libjsonnet++.cc
58+
59+
LIB_CPP_OBJ = $(LIB_OBJ) $(LIB_CPP_SRC:.cc=.o)
60+
5561
ALL = \
5662
jsonnet \
5763
libjsonnet.so \
64+
libjsonnet++.so \
5865
libjsonnet_test_snippet \
5966
libjsonnet_test_file \
6067
libjsonnet.js \
6168
doc/js/libjsonnet.js \
6269
$(LIB_OBJ)
70+
6371
ALL_HEADERS = \
6472
core/ast.h \
6573
core/desugarer.h \
@@ -72,7 +80,8 @@ ALL_HEADERS = \
7280
core/string_utils.h \
7381
core/vm.h \
7482
core/std.jsonnet.h \
75-
include/libjsonnet.h
83+
include/libjsonnet.h \
84+
include/libjsonnet++.h
7685

7786
default: jsonnet
7887

@@ -91,7 +100,9 @@ test: jsonnet libjsonnet.so libjsonnet_test_snippet libjsonnet_test_file
91100
MAKEDEPEND_SRCS = \
92101
cmd/jsonnet.cpp \
93102
core/libjsonnet_test_snippet.c \
94-
core/libjsonnet_test_file.c
103+
core/libjsonnet_test_file.c \
104+
cpp/libjsonnet_cpp_test_snippet.c \
105+
cpp/libjsonnet_cpp_test_file.c
95106

96107
depend:
97108
makedepend -f- $(LIB_SRC) $(MAKEDEPEND_SRCS) > Makefile.depend
@@ -102,6 +113,9 @@ core/desugarer.cpp: core/std.jsonnet.h
102113
%.o: %.cpp
103114
$(CXX) -c $(CXXFLAGS) $< -o $@
104115

116+
%.o: %.cc
117+
$(CXX) -c $(CXXFLAGS) $< -o $@
118+
105119
# Commandline executable.
106120
jsonnet: cmd/jsonnet.cpp $(LIB_OBJ)
107121
$(CXX) $(CXXFLAGS) $(LDFLAGS) $< $(LIB_SRC:.cpp=.o) -o $@
@@ -110,6 +124,9 @@ jsonnet: cmd/jsonnet.cpp $(LIB_OBJ)
110124
libjsonnet.so: $(LIB_OBJ)
111125
$(CXX) $(LDFLAGS) $(LIB_OBJ) $(SHARED_LDFLAGS) -o $@
112126

127+
libjsonnet++.so: $(LIB_CPP_OBJ)
128+
$(CXX) $(LDFLAGS) $(LIB_CPP_OBJ) $(SHARED_LDFLAGS) -o $@
129+
113130
# Javascript build of C binding
114131
JS_EXPORTED_FUNCTIONS = 'EXPORTED_FUNCTIONS=["_jsonnet_make", "_jsonnet_evaluate_snippet", "_jsonnet_realloc", "_jsonnet_destroy"]'
115132

WORKSPACE

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
new_http_archive(
2+
name = "gmock_archive",
3+
url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip",
4+
sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b",
5+
build_file = "gmock.BUILD",
6+
)
7+
8+
bind(
9+
name = "gtest",
10+
actual = "@gmock_archive//:gtest",
11+
)
12+
13+
bind(
14+
name = "gtest_main",
15+
actual = "@gmock_archive//:gtest_main",
16+
)

cpp/BUILD

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
cc_library(
4+
name = "libjsonnet++",
5+
srcs = ["libjsonnet++.cc"],
6+
deps = [
7+
"//:libjsonnet",
8+
"//include:libjsonnet++",
9+
],
10+
includes = ["include"],
11+
)
12+
13+
cc_test(
14+
name = "libjsonnet++_test",
15+
srcs = ["libjsonnet++_test.cc"],
16+
data = ["//cpp/testdata"],
17+
deps = [
18+
":libjsonnet++",
19+
"//external:gtest_main",
20+
],
21+
)

cpp/libjsonnet++.cc

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
// Copyright 2015 Google Inc. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "libjsonnet++.h"
16+
17+
namespace jsonnet {
18+
19+
Jsonnet::Jsonnet() {}
20+
Jsonnet::~Jsonnet() {
21+
if (vm_ != nullptr) {
22+
::jsonnet_destroy(vm_);
23+
}
24+
}
25+
26+
/* static */
27+
std::string Jsonnet::Version() {
28+
return ::jsonnet_version();
29+
}
30+
31+
bool Jsonnet::Init() {
32+
vm_ = static_cast<struct JsonnetVm*>(::jsonnet_make());
33+
return vm_ != nullptr;
34+
}
35+
36+
void Jsonnet::SetMaxStack(uint32_t depth) {
37+
::jsonnet_max_stack(vm_, static_cast<unsigned>(depth));
38+
}
39+
40+
void Jsonnet::SetGcMinObjects(uint32_t objects) {
41+
::jsonnet_gc_min_objects(vm_, static_cast<unsigned>(objects));
42+
}
43+
44+
void Jsonnet::SetGcGrowthTrigger(double growth) {
45+
::jsonnet_gc_growth_trigger(vm_, growth);
46+
}
47+
48+
void Jsonnet::SetStringOutput(bool string_output) {
49+
::jsonnet_string_output(vm_, string_output);
50+
}
51+
52+
void Jsonnet::AddImportPath(const std::string& path) {
53+
::jsonnet_jpath_add(vm_, path.c_str());
54+
}
55+
56+
void Jsonnet::SetMaxTrace(uint32_t lines) {
57+
::jsonnet_max_trace(vm_, static_cast<unsigned>(lines));
58+
}
59+
60+
void Jsonnet::BindExtVar(const std::string& key, const std::string& value) {
61+
::jsonnet_ext_var(vm_, key.c_str(), value.c_str());
62+
}
63+
64+
void Jsonnet::BindExtCodeVar(const std::string& key,
65+
const std::string& value) {
66+
::jsonnet_ext_code(vm_, key.c_str(), value.c_str());
67+
}
68+
69+
bool Jsonnet::EvaluateFile(const std::string& filename, std::string* output) {
70+
if (output == nullptr) {
71+
return false;
72+
}
73+
int error = 0;
74+
const char* jsonnet_output =
75+
::jsonnet_evaluate_file(vm_, filename.c_str(), &error);
76+
if (error != 0) {
77+
last_error_.assign(jsonnet_output);
78+
return false;
79+
}
80+
output->assign(jsonnet_output);
81+
return true;
82+
}
83+
84+
bool Jsonnet::EvaluateSnippet(const std::string& filename,
85+
const std::string& snippet,
86+
std::string* output) {
87+
if (output == nullptr) {
88+
return false;
89+
}
90+
int error = 0;
91+
const char* jsonnet_output = ::jsonnet_evaluate_snippet(
92+
vm_, filename.c_str(), snippet.c_str(), &error);
93+
if (error != 0) {
94+
last_error_.assign(jsonnet_output);
95+
return false;
96+
}
97+
output->assign(jsonnet_output);
98+
return true;
99+
}
100+
101+
namespace {
102+
void ParseMultiOutput(const char* jsonnet_output,
103+
std::map<std::string, std::string>* outputs) {
104+
for (const char* c = jsonnet_output; *c != '\0'; ) {
105+
const char *filename = c;
106+
const char *c2 = c;
107+
while (*c2 != '\0') ++c2;
108+
++c2;
109+
const char *json = c2;
110+
while (*c2 != '\0') ++c2;
111+
++c2;
112+
c = c2;
113+
outputs->insert(std::make_pair(filename, json));
114+
}
115+
}
116+
} // namespace
117+
118+
bool Jsonnet::EvaluateFileMulti(
119+
const std::string& filename,
120+
std::map<std::string, std::string>* outputs) {
121+
if (outputs == nullptr) {
122+
return false;
123+
}
124+
int error = 0;
125+
const char* jsonnet_output =
126+
::jsonnet_evaluate_file_multi(vm_, filename.c_str(), &error);
127+
if (error != 0) {
128+
last_error_.assign(jsonnet_output);
129+
return false;
130+
}
131+
ParseMultiOutput(jsonnet_output, outputs);
132+
return true;
133+
}
134+
135+
bool Jsonnet::EvaluateSnippetMulti(
136+
const std::string& filename,
137+
const std::string& snippet,
138+
std::map<std::string, std::string>* outputs) {
139+
if (outputs == nullptr) {
140+
return false;
141+
}
142+
int error = 0;
143+
const char* jsonnet_output = ::jsonnet_evaluate_snippet_multi(
144+
vm_, filename.c_str(), snippet.c_str(), &error);
145+
if (error != 0) {
146+
last_error_.assign(jsonnet_output);
147+
return false;
148+
}
149+
ParseMultiOutput(jsonnet_output, outputs);
150+
return true;
151+
}
152+
153+
std::string Jsonnet::LastError() const {
154+
return last_error_;
155+
}
156+
157+
} // namespace jsonnet

0 commit comments

Comments
 (0)