/**
* Copyright 2014
* SMEdit https://github.com/StarMade/SMEdit
* SMTools https://github.com/StarMade/SMTools
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
**/
package jo.sm.plugins.ship.imp;
import java.io.IOException;
import java.io.PushbackReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* @Auther Jo Jaquinta for SMEdit Classic - version 1.0
**/
public class VRMLLogic {
private static final Logger log = Logger.getLogger(VRMLLogic.class.getName());
public static List<VRMLNode> read(Reader r) throws IOException {
PushbackReader rdr;
rdr = new PushbackReader(r);
List<VRMLNode> nodes;
nodes = new ArrayList<>();
for (;;) {
VRMLNode node = readNext(rdr);
if (node == null) {
break;
}
nodes.add(node);
}
return nodes;
}
private static VRMLNode readNext(PushbackReader rdr) throws IOException {
int c;
c = skipWhitespace(rdr);
if (c == -1) {
return null;
}
if (c == '}') {
return new VRMLNode("}");
}
rdr.unread(c);
String name = readValue(rdr, true);
if (name.equals("DEF")) {
name = readValue(rdr, true);
readValue(rdr, true);
}
c = skipWhitespace(rdr);
if (c == -1) {
return null;
}
log.log(Level.INFO, "Reading: ", name);
if (c == '{') { // map node
List<VRMLNode> value = new ArrayList<>();
for (;;) {
VRMLNode next = readNext(rdr);
if (next == null) {
return null;
}
if (next.getName().equals("}")) {
break;
}
value.add(next);
}
return new VRMLNode(name, value);
} else if (c == '[') { // array node
List<String> value;
value = new ArrayList<>();
for (;;) {
String next = readValue(rdr, true);
if (next == null) {
return null;
}
if (next.equals("]")) {
break;
}
value.add(next);
}
return new VRMLNode(name, value);
} else { // singleton
rdr.unread(c);
List<String> value = new ArrayList<>();
for (;;) {
String next;
next = readValue(rdr, false);
if (next == null) {
return null;
}
if (next.equals("\n")) {
break;
}
value.add(next);
}
return new VRMLNode(name, value);
}
}
private static String readValue(PushbackReader rdr, boolean skipEOLN) throws IOException {
StringBuilder value;
value = new StringBuilder();
int c;
c = skipWhitespace(rdr, skipEOLN);
if (c == -1) {
return null;
}
if (c == ']') {
return "]";
}
if (c == '\n') {
return "\n";
}
boolean inQuote = false;
if (c == '"') {
inQuote = true;
} else {
value.append((char) c);
}
for (;;) {
c = rdr.read();
if (c == -1) {
return null;
}
if (c == '\n') {
rdr.unread(c);
break;
}
if (inQuote) {
if (c == '"') {
break;
}
} else {
if (isWhitespace(c)) {
break;
}
if (c == ']') {
rdr.unread(c);
break;
}
}
value.append((char) c);
}
return value.toString();
}
private static int skipWhitespace(PushbackReader rdr) throws IOException {
return skipWhitespace(rdr, true);
}
private static int skipWhitespace(PushbackReader rdr, boolean includingEOLN) throws IOException {
boolean skipComment;
skipComment = false;
for (;;) {
int c = rdr.read();
if (c == -1) {
return -1;
}
if (skipComment) {
if (c == '\n') {
if (!includingEOLN) {
return c;
}
skipComment = false;
}
} else {
if (c == '#') {
skipComment = true;
} else if (c == '\n') {
if (!includingEOLN) {
return c;
}
} else if (!isWhitespace(c)) {
return c;
}
}
}
}
private static boolean isWhitespace(int ch) {
return ((ch == ',') || Character.isWhitespace(ch));
}
}