Pretty Writer

generic-observer
Selebrator 7 years ago
parent 2f34d55cfc
commit e2d8421cda

@ -1,5 +1,6 @@
package _8;
import _8.io.SonReader;
import _8.io.SonWriter;
import java.io.*;
@ -27,6 +28,8 @@ public class Lecture {
this.semester = semester;
}
public Lecture() {}
public String getNumber() {
return number;
}
@ -320,4 +323,90 @@ public class Lecture {
out.endObject();
}
public static Lecture loadText2(String filename) throws IOException {
Path file = Paths.get(filename);
try(SonReader in = new SonReader(Files.newBufferedReader(file))) {
return loadSon(in);
}
}
public static Lecture loadSon(SonReader in) throws IOException {
in.beginObject();
Lecture lecture = new Lecture();
while(in.hasNext()) {
switch(in.nextName()) {
case "number":
lecture.setNumber(in.nextValue());
break;
case "title":
lecture.setTitle(in.nextValue());
break;
case "shortTitle":
lecture.setShortTitle(in.nextValue());
break;
case "semester":
lecture.setSemester(in.nextValue());
break;
case "lecturers":
in.beginArray();
while(in.hasNext()) {
in.beginObject();
Lecturer lecturer = new Lecturer();
while(in.hasNext()) {
switch(in.nextName()) {
case "firstName":
lecturer.setFirstName(in.nextValue());
break;
case "lastName":
lecturer.setLastName(in.nextValue());
break;
default:
in.skipValue();
break;
}
}
in.endObject();
lecture.addLecturers(lecturer);
}
in.endArray();
break;
case "schedule":
in.beginArray();
while(in.hasNext()) {
in.beginObject();
Date scheduleEntry = new Date();
while(in.hasNext()) {
switch(in.nextName()) {
case "time":
applyDate(scheduleEntry, in.nextValue());
break;
case "lectureHall":
scheduleEntry.setLectureHall(in.nextValue());
break;
case "topics":
in.beginArray();
while(in.hasNext()) {
scheduleEntry.addTopics(in.nextValue());
}
in.endArray();
break;
default:
in.skipValue();
break;
}
}
in.endObject();
lecture.addSchedule(scheduleEntry);
}
in.endArray();
break;
default:
in.skipValue();
break;
}
}
in.endObject();
return lecture;
}
}

@ -0,0 +1,228 @@
package _8.io;
import java.io.Closeable;
import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import static _8.io.SonState.*;
public class SonReader implements Closeable {
private final Reader in;
private SonState[] stack = new SonState[32];
private int stackTop = 0;
private Integer rememberedChar;
public SonReader(Reader in) {
this.in = in;
this.pushState(EMPTY_DOCUMENT);
}
public void beginObject() throws IOException {
this.prepareValue();
if(this.nextNonWhitespace() == '{') {
this.pushState(EMPTY_OBJECT);
} else {
throw new IllegalStateException("Expected BEGIN_OBJECT");
}
}
public void endObject() throws IOException {
if(this.nextNonWhitespace() == '}') {
this.popState();
} else {
throw new IllegalStateException("Expected END_OBJECT");
}
}
public void beginArray() throws IOException {
this.prepareValue();
if(this.nextNonWhitespace() == '[') {
this.pushState(EMPTY_ARRAY);
} else {
throw new IllegalStateException("Expected BEGIN_ARRAY");
}
}
public void endArray() throws IOException {
if(this.nextNonWhitespace() == ']') {
this.popState();
} else {
throw new IllegalStateException("Expected END_ARRAY");
}
}
public boolean hasNext() throws IOException {
int c = this.nextNonWhitespace();
this.rememberChar(c);
switch(this.peekState()) {
case EMPTY_DOCUMENT:
case EMPTY_OBJECT:
case NONEMPTY_DOCUMENT:
case NONEMPTY_OBJECT:
return c != '}';
case EMPTY_ARRAY:
case NONEMPTY_ARRAY:
return c != ']';
case DANGLING_NAME:
default:
throw new IllegalStateException();
}
}
public String nextName() throws IOException {
return this.readName();
}
public String nextValue() throws IOException {
return this.readValue();
}
private String readName() throws IOException {
this.prepareName();
final StringBuilder name = new StringBuilder();
int c = this.nextNonWhitespace();
do {
name.append((char) c);
} while((c = this.eofRead()) != ':');
return name.toString();
}
private void prepareName() throws IOException {
SonState state = this.peekState();
if(state == NONEMPTY_OBJECT) { // not first in an object
this.nextChar(true);// remove , from previous value
} else if(state != EMPTY_OBJECT) { // not in an object
throw new IllegalStateException("Didn't expect this to be named");
}
this.replaceTopState(DANGLING_NAME);
}
private void prepareValue() throws IOException {
SonState state = this.peekState();
switch(state) {
case EMPTY_DOCUMENT:
this.replaceTopState(NONEMPTY_DOCUMENT);
break;
case EMPTY_ARRAY:
this.replaceTopState(NONEMPTY_ARRAY);
break;
case NONEMPTY_ARRAY:
case NONEMPTY_OBJECT:
this.nextChar(true); // remove , from previous element
break;
case DANGLING_NAME:
this.replaceTopState(NONEMPTY_OBJECT);
break;
default:
throw new IllegalStateException();
}
}
private String readValue() throws IOException {
this.prepareValue();
final StringBuilder value = new StringBuilder();
int c = this.nextNonWhitespace();
do {
value.append((char) c);
} while((c = this.eofRead()) != ',' && c != '}' && c != ']');
this.rememberChar(c);
return value.toString().trim();
}
public void skipValue() throws IOException {
this.prepareValue();
int count = 0;
int c;
do {
c = this.nextNonWhitespace();
if(c == '{') {
this.pushState(EMPTY_OBJECT);
count++;
} else if(c == '[') {
this.pushState(EMPTY_ARRAY);
count++;
} else if(c == '}') {
this.popState();
count--;
} else if(c == ']') {
this.popState();
count--;
} else {
this.nextValue();
}
} while(count != 0);
}
@Override
public void close() throws IOException {
this.in.close();
this.stackTop = 1;
this.stack[0] = CLOSED;
}
/* character stream management */
private int nextNonWhitespace() throws IOException {
int read;
do {
read = this.nextChar(true);
} while(read == ' ' || read == '\t' || read == '\n');
return read;
}
private int nextChar(boolean remembered) throws IOException {
if(this.rememberedChar != null) {
if(remembered) {
int top = this.rememberedChar;
this.rememberedChar = null;
return top;
} else {
this.rememberedChar = null;
}
}
return eofRead();
}
private int eofRead() throws IOException {
int read = this.in.read();
if(read == -1) {
throw new EOFException();
}
return read;
}
private void rememberChar(int c) {
if(this.rememberedChar != null) {
throw new IllegalStateException("Already remembering a char");
}
this.rememberedChar = c;
}
/* state management */
private SonState peekState() {
return this.stack[this.stackTop - 1];
}
private SonState popState() {
return this.stack[--this.stackTop];
}
private void pushState(SonState newTop) {
if(this.stackTop >= this.stack.length) {
this.stack = Arrays.copyOf(this.stack, this.stackTop * 2);
}
this.stack[this.stackTop++] = newTop;
}
private void replaceTopState(SonState newTop) {
this.stack[this.stackTop - 1] = newTop;
}
}

@ -7,5 +7,6 @@ public enum SonState {
NONEMPTY_ARRAY,
EMPTY_OBJECT,
NONEMPTY_OBJECT,
DANGLING_NAME
DANGLING_NAME,
CLOSED
}
Loading…
Cancel
Save