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