1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2015 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
9 #include "Ttcn2Json.hh"
14 #include "../../common/JSON_Tokenizer.hh"
15 #include "../Value.hh"
16 #include "../Valuestuff.hh"
18 // forward declarations
25 Ttcn2Json::Ttcn2Json(Common::Modules
* p_modules
, const char* p_schema_name
)
29 FILE* file
= open_output_file(p_schema_name
, &is_temporary
);
31 JSON_Tokenizer
json(true);
35 fprintf(file
, "%s\n", json
.get_buffer());
37 close_output_file(p_schema_name
, file
, is_temporary
, 0);
40 void Ttcn2Json::create_schema(JSON_Tokenizer
& json
)
42 // top-level object start
43 json
.put_next_token(JSON_TOKEN_OBJECT_START
, NULL
);
45 // insert the schema header
46 json
.put_next_token(JSON_TOKEN_NAME
, "$schema");
47 json
.put_next_token(JSON_TOKEN_STRING
, "\"http://json-schema.org/draft-04/schema#\"");
49 // start of type definitions
50 json
.put_next_token(JSON_TOKEN_NAME
, "definitions");
51 json
.put_next_token(JSON_TOKEN_OBJECT_START
, NULL
);
53 // insert module names and schemas for types; gather references to types and
54 // JSON encoding/decoding function information
55 map
<Common::Type
*, JSON_Tokenizer
> json_refs
;
56 modules
->generate_json_schema(json
, json_refs
);
58 // end of type definitions
59 json
.put_next_token(JSON_TOKEN_OBJECT_END
, NULL
);
61 if (!json_refs
.empty()) {
62 // top-level "anyOf" structure containing references to the types the schema validates
63 // don't insert an empty "anyOf" if there are no references
64 json
.put_next_token(JSON_TOKEN_NAME
, "anyOf");
65 json
.put_next_token(JSON_TOKEN_ARRAY_START
, NULL
);
67 // close schema segments and add them to the main schema
68 for (size_t i
= 0; i
< json_refs
.size(); ++i
) {
69 JSON_Tokenizer
* segment
= json_refs
.get_nth_elem(i
);
70 segment
->put_next_token(JSON_TOKEN_OBJECT_END
, NULL
);
71 insert_schema(json
, *segment
);
76 // end of the "anyOf" structure
77 json
.put_next_token(JSON_TOKEN_ARRAY_END
, NULL
);
80 // top-level object end
81 json
.put_next_token(JSON_TOKEN_OBJECT_END
, NULL
);
84 void Ttcn2Json::insert_schema(JSON_Tokenizer
& to
, JSON_Tokenizer
& from
)
86 json_token_t token
= JSON_TOKEN_NONE
;
87 char* value_str
= NULL
;
92 from
.get_next_token(&token
, &value_str
, &value_len
);
94 if (token
== JSON_TOKEN_ERROR
) {
95 FATAL_ERROR("Ttcn2Json::insert_schema");
98 if (value_str
!= NULL
) {
99 // put_next_token expects a null terminated string, save the next character
100 // and set it to null
101 temp
= value_str
[value_len
];
102 value_str
[value_len
] = 0;
105 to
.put_next_token(token
, value_str
);
107 if (value_str
!= NULL
) {
108 // put the original character back to its place
109 value_str
[value_len
] = temp
;
111 } while (token
!= JSON_TOKEN_NONE
);
114 JsonOmitCombination::JsonOmitCombination(Common::Value
* p_top_level
)
116 parse_value(p_top_level
->get_value_refd_last());
119 JsonOmitCombination::~JsonOmitCombination()
121 for (size_t i
= 0; i
< combinations
.size(); ++i
) {
122 delete combinations
.get_nth_elem(i
);
124 combinations
.clear();
127 bool JsonOmitCombination::next(int current_value
/* = 0 */)
129 if ((size_t)current_value
== combinations
.size()) {
132 Common::Value
* val
= combinations
.get_nth_key(current_value
);
133 int* omitted_fields
= combinations
.get_nth_elem(current_value
);
134 for (size_t i
= 0; i
< val
->get_nof_comps(); ++i
) {
135 if (omitted_fields
[i
] == OMITTED_ABSENT
) {
136 // ABSENT (zero bit) found, set it to NULL (one bit) and reset all previous
137 // NULLs (ones) to ABSENTs (zeros), first in this value ...
138 omitted_fields
[i
] = OMITTED_NULL
;
139 for (size_t j
= 0; j
< i
; ++j
) {
140 if (omitted_fields
[j
] == OMITTED_NULL
) {
141 omitted_fields
[j
] = OMITTED_ABSENT
;
144 // ... and then in all previous record values
145 reset_previous(current_value
);
149 // no new combinations in this value, check the next one
150 return next(current_value
+ 1);
153 JsonOmitCombination::omit_state_t
JsonOmitCombination::get_state(
154 Common::Value
* p_rec_value
, size_t p_comp
) const
156 return (JsonOmitCombination::omit_state_t
)combinations
[p_rec_value
][p_comp
];
159 void JsonOmitCombination::parse_value(Common::Value
* p_value
)
161 switch (p_value
->get_valuetype()) {
162 case Common::Value::V_SEQ
:
163 case Common::Value::V_SET
: {
164 size_t len
= p_value
->get_nof_comps();
165 int* omitted_fields
= new int[len
]; // stores one combination
166 for (size_t i
= 0; i
< len
; ++i
) {
167 Common::Value
* val
= p_value
->get_se_comp_byIndex(i
)->get_value();
168 if (val
->get_valuetype() == Common::Value::V_OMIT
) {
169 // all omitted fields are absent in the first combination
170 omitted_fields
[i
] = OMITTED_ABSENT
;
173 omitted_fields
[i
] = NOT_OMITTED
;
175 parse_value(val
->get_value_refd_last());
177 combinations
.add(p_value
, omitted_fields
);
179 case Common::Value::V_SEQOF
:
180 case Common::Value::V_SETOF
:
181 for (size_t i
= 0; i
< p_value
->get_nof_comps(); ++i
) {
182 parse_value(p_value
->get_comp_byIndex(i
)->get_value_refd_last());
185 case Common::Value::V_CHOICE
:
186 parse_value(p_value
->get_alt_value()->get_value_refd_last());
192 void JsonOmitCombination::reset_previous(int value_count
)
194 for (int i
= 0; i
< value_count
; ++i
) {
195 Common::Value
* val
= combinations
.get_nth_key(i
);
196 int* omitted_fields
= combinations
.get_nth_elem(i
);
197 for (size_t j
= 0; j
< val
->get_nof_comps(); ++j
) {
198 if (omitted_fields
[j
] == OMITTED_NULL
) {
199 omitted_fields
[j
] = OMITTED_ABSENT
;
This page took 0.034498 seconds and 5 git commands to generate.