1 /*
2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 #include "schema.h"
26
27 void Schema::show(std::ostream &out, char *argArray) {
28 }
29
30 void indent(std::ostream &out, int depth, char ch) {
31 while (depth-- > 0) {
32 out << ch;
33 }
34 }
35
36 void Schema::show(std::ostream &out, int depth, Node *node) {
37 indent(out, depth, ' ');
38 if (const auto *schemaNode = dynamic_cast<SchemaNode *>(node)) {
39 std::cout << schemaNode->type;
40 } else if (const auto *arg = dynamic_cast<ArgNode *>(node)) {
41 std::cout << arg->idx;
42 } else if (const auto *structNode = dynamic_cast<StructNode *>(node)) {
43 std::cout << ((structNode->name == nullptr) ? "?" : structNode->name);
44 } else if (const auto *unionNode = dynamic_cast<UnionNode *>(node)) {
45 std::cout << ((unionNode->name == nullptr) ? "?" : unionNode->name);
46 } else if (auto *array = dynamic_cast<Array *>(node)) {
47 if (array->flexible) {
48 std::cout << "[*]";
49 } else {
50 std::cout << "[" << array->elementCount << "]";
51 }
52 } else if (auto *fieldNode = dynamic_cast<FieldNode *>(node)) {
53 std::cout << ((fieldNode->name == nullptr) ? "?" : fieldNode->name) << ":" << fieldNode->typeName;
54 } else {
55 std::cout << "<node?>";
56 }
57 if (node->children.empty()) {
58 std::cout << std::endl;
59 } else {
60 std::cout << "{" << std::endl;
61 for (Node *n: node->children) {
62 show(out, depth + 1, n);
63 }
64 indent(out, depth, ' ');
65 std::cout << "}" << std::endl;
66 }
67 }
68
69 void Schema::show(std::ostream &out, SchemaNode *schemaNode) {
70 show(out, 0, schemaNode);
71 }
72
73 Schema::FieldNode *Schema::FieldNode::parse(SchemaCursor *cursor) {
74 typeName = cursor->getIdentifier();
75 return this;
76 }
77
78 Schema::Array *Schema::Array::parse(SchemaCursor *cursor) {
79 cursor->in("Array::Parse");
80 if (cursor->is('*')) {
81 flexible = true;
82 } else if (cursor->peekDigit()) {
83 elementCount = cursor->getLong();
84 }
85 cursor->expect(':', "after element count in array", __LINE__);
86 char *identifier = nullptr;
87 if (cursor->is('?')) {
88 } else if (cursor->peekAlpha()) {
89 identifier = cursor->getIdentifier();
90 } else {
91 cursor->error(std::cerr, __FILE__, __LINE__, "expecting '?' or identifier for element");
92 }
93 cursor->expect(':', "after name in array", __LINE__);
94 if (cursor->peekAlpha()) {
95 elementType = addChild(cursor, new FieldNode(this, identifier));
96 } else if (cursor->is('{')) {
97 elementType = addChild(cursor, new StructNode(this, identifier));
98 } else if (cursor->is('<')) {
99 elementType = addChild(cursor, new UnionNode(this, identifier));
100 } else {
101 cursor->error(std::cerr, __FILE__, __LINE__, "expecting type for element");
102 }
103 cursor->expect(']', "after array type", __LINE__);
104 cursor->out();
105 return this;
106 }
107
108 Schema::AbstractStructOrUnionNode *Schema::AbstractStructOrUnionNode::parse(SchemaCursor *cursor) {
109 cursor->in("StructUnion::parse");
110 do {
111 char *identifier = nullptr;
112 if (cursor->is('?')) {
113 // no name name = null!
114 } else if (cursor->peekAlpha()) {
115 identifier = cursor->getIdentifier();
116 }
117 cursor->expect(':', "after StrutOrUnion name", __LINE__);
118 if (cursor->peekAlpha()) {
119 typeNode = addChild(cursor, new FieldNode(this, identifier));
120 } else if (cursor->is('[')) {
121 typeNode = addChild(cursor, new Array(this));
122 } else if (cursor->is('{')) {
123 typeNode = addChild(cursor, new StructNode(this, identifier));
124 } else if (cursor->is('<')) {
125 typeNode = addChild(cursor, new UnionNode(this, identifier));
126 } else {
127 cursor->error(std::cerr, __FILE__, __LINE__, "expecting type");
128 }
129 } while (cursor->is(separator));
130 cursor->expect(terminator, "at end of struct or union ", __LINE__);
131 cursor->out();
132 return this;
133 }
134
135 Schema::StructNode *Schema::StructNode::parse(SchemaCursor *cursor) {
136 return dynamic_cast<StructNode *>(AbstractStructOrUnionNode::parse(cursor));
137 }
138
139 Schema::UnionNode *Schema::UnionNode::parse(SchemaCursor *cursor) {
140 return dynamic_cast<UnionNode *>(AbstractStructOrUnionNode::parse(cursor));
141 }
142
143 Schema::ArgNode *Schema::ArgNode::parse(SchemaCursor *cursor) {
144 cursor->in("ArgNode::parse");
145 char actual;
146 cursor->expectEither('!', '?', &actual, __LINE__);
147
148 cursor->expect(':', __LINE__);
149 if (cursor->peekAlpha()) {
150 addChild(cursor, new FieldNode(this, nullptr));
151 } else {
152 cursor->expectDigit("long byteCount of buffer", __LINE__);
153 long bytes = cursor->getLong();
154 if (cursor->isEither('#', '+', &actual)) {
155 bool complete = (actual == '#');
156 cursor->expectAlpha("identifier", __LINE__);
157 char *identifier = cursor->getIdentifier();
158 cursor->expect(':', "after identifier ", __LINE__);
159 cursor->expect('{', "top level arg struct", __LINE__);
160 addChild(cursor, new ArgStructNode(this, complete, identifier));
161 } else if (cursor->peekAlpha()) {
162 addChild(cursor, new FieldNode(this, cursor->getIdentifier()));
163 } else {
164 cursor->error(std::cerr, __FILE__, __LINE__, "expecting '#' ");
165 }
166 }
167 cursor->expect(')', "at end of NamedStructOrUnion", __LINE__);
168 cursor->out();
169
170 return this;
171 }
172
173 Schema::SchemaNode *Schema::SchemaNode::parse(SchemaCursor *cursor) {
174 cursor->in("SchemaNode::parse");
175 cursor->expectDigit("arg count", __LINE__);
176 int argc = cursor->getInt();
177 for (int i = 0; i < argc; i++) {
178 cursor->expect('(', __LINE__);
179 addChild(cursor, new ArgNode(this, i));
180 if (i < (argc - 1)) {
181 cursor->expect(',', __LINE__);
182 }
183 }
184 cursor->out();
185 return this;
186 }