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 31 void indent(std::ostream &out, int depth, char ch) { 32 while (depth-- > 0) { 33 out << ch; 34 } 35 } 36 37 void Schema::show(std::ostream &out, int depth, Node *node) { 38 indent(out, depth, ' '); 39 if (auto *schemaNode = dynamic_cast<SchemaNode *>(node)) { 40 std::cout << schemaNode->type; 41 } else if (auto *arg = dynamic_cast<ArgNode *>(node)) { 42 std::cout << arg->idx; 43 } else if (auto *structNode = dynamic_cast<StructNode *>(node)) { 44 std::cout << ((structNode->name== nullptr)?"?":structNode->name); 45 } else if (auto *unionNode = dynamic_cast<UnionNode *>(node)) { 46 std::cout << ((unionNode->name== nullptr)?"?":unionNode->name); 47 } else if (auto *array = dynamic_cast<Array *>(node)) { 48 if(array->flexible) { 49 std::cout << "[*]"; 50 }else{ 51 std::cout << "[" << array->elementCount << "]"; 52 } 53 } else if (auto *fieldNode = dynamic_cast<FieldNode *>(node)) { 54 std::cout << ((fieldNode->name== nullptr)?"?":fieldNode->name)<<":"<<fieldNode->typeName; 55 } else { 56 std::cout << "<node?>"; 57 } 58 if (node->children.empty()) { 59 std::cout << std::endl; 60 }else{ 61 std::cout << "{" << std::endl; 62 for (Node *n: node->children) { 63 show(out, depth + 1, n); 64 } 65 indent(out, depth, ' '); 66 std::cout << "}" << std::endl; 67 } 68 } 69 70 void Schema::show(std::ostream &out, SchemaNode *schemaNode) { 71 show(out, 0, schemaNode); 72 } 73 74 Schema::FieldNode *Schema::FieldNode::parse(Cursor *cursor) { 75 typeName = cursor->getIdentifier(); 76 return this; 77 } 78 79 Schema::Array *Schema::Array::parse(Cursor *cursor) { 80 cursor->in("Array::Parse"); 81 if (cursor->is('*')) { 82 flexible = true; 83 } else if (cursor->peekDigit()) { 84 elementCount = cursor->getLong(); 85 } 86 cursor->expect(':', "after element count in array", __LINE__); 87 char *identifier= nullptr; 88 if (cursor->is('?')) { 89 } else if (cursor->peekAlpha()) { 90 identifier = cursor->getIdentifier(); 91 } else { 92 cursor->error(std::cerr, __FILE__, __LINE__, "expecting '?' or identifier for element"); 93 } 94 cursor->expect(':', "after name in array", __LINE__); 95 if (cursor->peekAlpha()) { 96 elementType = addChild(cursor, new FieldNode(this, identifier)); 97 } else if (cursor->is('{')) { 98 elementType = addChild(cursor, new StructNode(this, identifier)); 99 } else if (cursor->is('<')) { 100 elementType = addChild(cursor, new UnionNode(this, identifier)); 101 } else { 102 cursor->error(std::cerr, __FILE__, __LINE__, "expecting type for element"); 103 } 104 cursor->expect(']', "after array type", __LINE__); 105 cursor->out(); 106 return this; 107 } 108 109 Schema::AbstractStructOrUnionNode *Schema::AbstractStructOrUnionNode::parse(Cursor *cursor) { 110 cursor->in("StructUnion::parse"); 111 do { 112 char *identifier = nullptr; 113 if (cursor->is('?')) { 114 // no name name = null! 115 } else if (cursor->peekAlpha()) { 116 identifier = cursor->getIdentifier(); 117 } 118 cursor->expect(':', "after StrutOrUnion name", __LINE__); 119 if (cursor->peekAlpha()) { 120 typeNode = addChild(cursor, new FieldNode(this, identifier)); 121 } else if (cursor->is('[')) { 122 typeNode = addChild(cursor, new Array(this)); 123 } else if (cursor->is('{')) { 124 typeNode = addChild(cursor, new StructNode(this, identifier )); 125 } else if (cursor->is('<')) { 126 typeNode = addChild(cursor, new UnionNode(this, identifier)); 127 } else { 128 cursor->error(std::cerr, __FILE__, __LINE__, "expecting type"); 129 } 130 } while (cursor->is(separator)); 131 cursor->expect(terminator, "at end of struct or union ", __LINE__); 132 cursor->out(); 133 return this; 134 } 135 136 Schema::StructNode *Schema::StructNode::parse(Cursor *cursor) { 137 return dynamic_cast<StructNode *>(AbstractStructOrUnionNode::parse(cursor)); 138 } 139 140 Schema::UnionNode *Schema::UnionNode::parse(Cursor *cursor) { 141 return dynamic_cast<UnionNode *>(AbstractStructOrUnionNode::parse(cursor)); 142 } 143 144 Schema::ArgNode *Schema::ArgNode::parse(Cursor *cursor) { 145 cursor->in("ArgNode::parse"); 146 char actual; 147 cursor->expectEither('!', '?', &actual, __LINE__); 148 149 cursor->expect(':', __LINE__); 150 if (cursor->peekAlpha()) { 151 addChild(cursor, new FieldNode(this, nullptr)); 152 }else{ 153 cursor->expectDigit("long byteCount of buffer", __LINE__); 154 long bytes = cursor->getLong(); 155 if (cursor->isEither('#', '+', &actual)) { 156 bool complete = (actual == '#'); 157 cursor->expectAlpha("identifier", __LINE__); 158 char *identifier = cursor->getIdentifier(); 159 cursor->expect(':', "after identifier ", __LINE__); 160 cursor->expect('{', "top level arg struct", __LINE__); 161 addChild(cursor, new ArgStructNode(this, complete, identifier)); 162 } else if (cursor->peekAlpha()) { 163 addChild(cursor, new FieldNode(this, cursor->getIdentifier())); 164 } else { 165 cursor->error(std::cerr, __FILE__, __LINE__, "expecting '#' "); 166 } 167 } 168 cursor->expect(')', "at end of NamedStructOrUnion", __LINE__); 169 cursor->out(); 170 171 return this; 172 } 173 174 Schema::SchemaNode *Schema::SchemaNode::parse(Cursor *cursor) { 175 cursor->in("SchemaNode::parse"); 176 cursor->expectDigit("arg count", __LINE__); 177 int argc = cursor->getInt(); 178 for (int i = 0; i < argc; i++) { 179 cursor->expect('(', __LINE__); 180 addChild(cursor, new ArgNode(this, i)); 181 if (i < (argc - 1)) { 182 cursor->expect(',', __LINE__); 183 } 184 } 185 cursor->out(); 186 return this; 187 } 188 189