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 }