Skip to content

Commit 9720e5a

Browse files
committed
Refactor responses into a non-JSON type that can be converted to and from JSON
1 parent 47e18ad commit 9720e5a

20 files changed

+1783
-1136
lines changed

CMakeLists.txt

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ find_package(Threads MODULE REQUIRED)
1313

1414
find_package(pegtl CONFIG REQUIRED)
1515

16-
add_executable(schemagen GraphQLTree.cpp SchemaGenerator.cpp)
16+
add_executable(schemagen
17+
GraphQLTree.cpp
18+
GraphQLResponse.cpp
19+
SchemaGenerator.cpp)
1720
target_link_libraries(schemagen PRIVATE taocpp::pegtl)
18-
target_include_directories(schemagen SYSTEM PUBLIC ${RAPIDJSON_INCLUDE_DIRS})
1921
target_include_directories(schemagen PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
2022
set_property(TARGET schemagen PROPERTY CXX_STANDARD 11)
2123

@@ -26,16 +28,14 @@ add_custom_command(
2628
COMMENT "Generating IntrospectionSchema files"
2729
)
2830

29-
find_package(RapidJSON CONFIG REQUIRED)
30-
3131
add_library(graphqlservice
3232
GraphQLTree.cpp
33+
GraphQLResponse.cpp
3334
GraphQLService.cpp
3435
Introspection.cpp
3536
IntrospectionSchema.cpp)
3637
target_link_libraries(graphqlservice PRIVATE taocpp::pegtl)
3738
target_link_libraries(graphqlservice PUBLIC ${CMAKE_THREAD_LIBS_INIT})
38-
target_include_directories(graphqlservice SYSTEM PUBLIC ${RAPIDJSON_INCLUDE_DIRS})
3939
target_include_directories(graphqlservice SYSTEM INTERFACE $<INSTALL_INTERFACE:include>)
4040
target_include_directories(graphqlservice PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
4141
set_property(TARGET graphqlservice PROPERTY CXX_STANDARD 11)
@@ -57,21 +57,22 @@ if(BUILD_TESTS OR UPDATE_SAMPLES)
5757
)
5858

5959
if(BUILD_TESTS)
60+
find_package(RapidJSON CONFIG REQUIRED)
61+
6062
add_library(todaygraphql
6163
${CMAKE_BINARY_DIR}/TodaySchema.cpp
62-
Today.cpp)
63-
target_link_libraries(todaygraphql
64+
Today.cpp
65+
JSONResponse.cpp)
66+
target_link_libraries(todaygraphql PUBLIC
6467
graphqlservice)
65-
target_include_directories(todaygraphql SYSTEM PRIVATE ${RAPIDJSON_INCLUDE_DIRS})
68+
target_include_directories(todaygraphql SYSTEM PUBLIC ${RAPIDJSON_INCLUDE_DIRS})
6669
target_include_directories(todaygraphql PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
6770
set_property(TARGET todaygraphql PROPERTY CXX_STANDARD 11)
6871

6972
add_executable(test_today
7073
test_today.cpp)
71-
target_link_libraries(test_today
72-
graphqlservice
74+
target_link_libraries(test_today PRIVATE
7375
todaygraphql)
74-
target_include_directories(test_today SYSTEM PRIVATE ${RAPIDJSON_INCLUDE_DIRS})
7576
target_include_directories(test_today PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
7677
set_property(TARGET test_today PROPERTY CXX_STANDARD 11)
7778

@@ -80,12 +81,10 @@ if(BUILD_TESTS OR UPDATE_SAMPLES)
8081

8182
add_executable(tests
8283
tests.cpp)
83-
target_link_libraries(tests
84-
graphqlservice
84+
target_link_libraries(tests PRIVATE
8585
todaygraphql
8686
GTest::GTest
8787
GTest::Main)
88-
target_include_directories(tests SYSTEM PRIVATE ${RAPIDJSON_INCLUDE_DIRS})
8988
target_include_directories(tests PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
9089
set_property(TARGET tests PROPERTY CXX_STANDARD 11)
9190

@@ -122,9 +121,11 @@ install(TARGETS schemagen
122121

123122
install(FILES
124123
GraphQLTree.h
124+
GraphQLResponse.h
125125
GraphQLService.h
126126
Introspection.h
127127
${CMAKE_BINARY_DIR}/IntrospectionSchema.h
128+
JSONResponse.h
128129
DESTINATION include/graphqlservice
129130
CONFIGURATIONS Release)
130131

GraphQLResponse.cpp

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#include "GraphQLResponse.h"
5+
6+
#include <stdexcept>
7+
8+
namespace facebook {
9+
namespace graphql {
10+
namespace response {
11+
12+
Value::Value(Type type /*= Type::Null*/)
13+
: _type(type)
14+
{
15+
switch (type)
16+
{
17+
case Type::Map:
18+
_members.reset(new std::unordered_map<std::string, size_t>());
19+
_map.reset(new MapType());
20+
break;
21+
22+
case Type::List:
23+
_list.reset(new ListType());
24+
break;
25+
26+
case Type::String:
27+
case Type::EnumValue:
28+
_string.reset(new StringType());
29+
break;
30+
31+
case Type::Boolean:
32+
_boolean = false;
33+
break;
34+
35+
case Type::Int:
36+
_int = 0;
37+
break;
38+
39+
case Type::Float:
40+
_float = 0;
41+
break;
42+
43+
case Type::Scalar:
44+
_scalar.reset(new Value());
45+
break;
46+
47+
default:
48+
break;
49+
}
50+
}
51+
52+
Value::Value(StringType&& value)
53+
: _type(Type::String)
54+
, _string(new StringType(std::move(value)))
55+
{
56+
}
57+
58+
Value::Value(BooleanType value)
59+
: _type(Type::Boolean)
60+
, _boolean(value)
61+
{
62+
}
63+
64+
Value::Value(IntType value)
65+
: _type(Type::Int)
66+
, _int(value)
67+
{
68+
}
69+
70+
Value::Value(FloatType value)
71+
: _type(Type::Float)
72+
, _float(value)
73+
{
74+
}
75+
76+
Value::Value(Value&& other)
77+
: _type(other._type)
78+
, _members(std::move(other._members))
79+
, _map(std::move(other._map))
80+
, _list(std::move(other._list))
81+
, _string(std::move(other._string))
82+
, _scalar(std::move(other._scalar))
83+
{
84+
switch (_type)
85+
{
86+
case Type::Boolean:
87+
_boolean = other._boolean;
88+
break;
89+
90+
case Type::Int:
91+
_int = other._int;
92+
break;
93+
94+
case Type::Float:
95+
_float = other._float;
96+
break;
97+
98+
default:
99+
break;
100+
}
101+
}
102+
103+
Value::Value(const Value& other)
104+
: _type(other._type)
105+
{
106+
switch (_type)
107+
{
108+
case Type::Map:
109+
_members.reset(new std::unordered_map<std::string, size_t>(*other._members));
110+
_map.reset(new MapType(*other._map));
111+
break;
112+
113+
case Type::List:
114+
_list.reset(new ListType(*other._list));
115+
break;
116+
117+
case Type::String:
118+
case Type::EnumValue:
119+
_string.reset(new StringType(*other._string));
120+
break;
121+
122+
case Type::Boolean:
123+
_boolean = other._boolean;
124+
break;
125+
126+
case Type::Int:
127+
_int = other._int;
128+
break;
129+
130+
case Type::Float:
131+
_float = other._float;
132+
break;
133+
134+
case Type::Scalar:
135+
_scalar.reset(new Value(*other._scalar));
136+
break;
137+
138+
default:
139+
break;
140+
}
141+
}
142+
143+
Value& Value::operator=(Value&& rhs)
144+
{
145+
const_cast<Type&>(_type) = rhs._type;
146+
const_cast<Type&>(rhs._type) = Type::Null;
147+
148+
_members = std::move(rhs._members);
149+
_map = std::move(rhs._map);
150+
_list = std::move(rhs._list);
151+
_string = std::move(rhs._string);
152+
_scalar = std::move(rhs._scalar);
153+
154+
switch (_type)
155+
{
156+
case Type::Boolean:
157+
_boolean = rhs._boolean;
158+
break;
159+
160+
case Type::Int:
161+
_int = rhs._int;
162+
break;
163+
164+
case Type::Float:
165+
_float = rhs._float;
166+
break;
167+
168+
default:
169+
break;
170+
}
171+
172+
return *this;
173+
}
174+
175+
Value::Type Value::type() const
176+
{
177+
return _type;
178+
}
179+
180+
void Value::reserve(size_t count)
181+
{
182+
switch (_type)
183+
{
184+
case Type::Map:
185+
_members->reserve(count);
186+
_map->reserve(count);
187+
break;
188+
189+
case Type::List:
190+
_list->reserve(count);
191+
break;
192+
193+
default:
194+
throw std::logic_error("Invalid call to Value::reserve");
195+
}
196+
}
197+
198+
size_t Value::size() const
199+
{
200+
switch (_type)
201+
{
202+
case Type::Map:
203+
return _map->size();
204+
205+
case Type::List:
206+
return _list->size();
207+
208+
default:
209+
throw std::logic_error("Invalid call to Value::size");
210+
}
211+
}
212+
213+
void Value::emplace_back(std::string&& name, Value&& value)
214+
{
215+
if (_type != Type::Map)
216+
{
217+
throw std::logic_error("Invalid call to Value::emplace_back for MapType");
218+
}
219+
220+
if (_members->find(name) != _members->cend())
221+
{
222+
throw std::runtime_error("Duplicate Map member");
223+
}
224+
225+
_members->insert({ name, _map->size() });
226+
_map->emplace_back(std::make_pair(std::move(name), std::move(value)));
227+
}
228+
229+
Value::MapType::const_iterator Value::find(const std::string& name) const
230+
{
231+
if (_type != Type::Map)
232+
{
233+
throw std::logic_error("Invalid call to Value::find for MapType");
234+
}
235+
236+
const auto itr = _members->find(name);
237+
238+
if (itr == _members->cend())
239+
{
240+
return _map->cend();
241+
}
242+
243+
return _map->cbegin() + itr->second;
244+
}
245+
246+
const Value& Value::operator[](const std::string& name) const
247+
{
248+
const auto itr = find(name);
249+
250+
if (itr == _map->cend())
251+
{
252+
throw std::runtime_error("Missing Map member");
253+
}
254+
255+
return itr->second;
256+
}
257+
258+
void Value::emplace_back(Value&& value)
259+
{
260+
if (_type != Type::List)
261+
{
262+
throw std::logic_error("Invalid call to Value::emplace_back for ListType");
263+
}
264+
265+
_list->emplace_back(std::move(value));
266+
}
267+
268+
const Value& Value::operator[](size_t index) const
269+
{
270+
if (_type != Type::List)
271+
{
272+
throw std::logic_error("Invalid call to Value::emplace_back for ListType");
273+
}
274+
275+
return _list->at(index);
276+
}
277+
278+
} /* namespace response */
279+
} /* namespace graphql */
280+
} /* namespace facebook */

0 commit comments

Comments
 (0)