Skip to content

Commit

Permalink
Separate header and data parsing for sequential parsers
Browse files Browse the repository at this point in the history
This allows for only parsing the headers of files.

Fix #11
  • Loading branch information
io7m committed Nov 29, 2016
1 parent 6a31238 commit 9a001c6
Show file tree
Hide file tree
Showing 35 changed files with 1,332 additions and 810 deletions.
10 changes: 8 additions & 2 deletions io7m-smfj-cmdline/src/main/java/com/io7m/smfj/cmdline/Main.java
Expand Up @@ -303,7 +303,10 @@ public Unit call()
final SMFFCopierType copier = SMFFCopier.create(serializer);
try (final SMFParserSequentialType parser =
provider_parser.parserCreateSequential(copier, path_out, is)) {
parser.parse();
parser.parseHeader();
if (!parser.parserHasFailed()) {
parser.parseData();
}
}
if (!copier.errors().isEmpty()) {
Main.this.exit_code = 1;
Expand Down Expand Up @@ -351,7 +354,10 @@ public Unit call()
try (final InputStream is = Files.newInputStream(path)) {
final SMFParserSequentialType parser =
provider.parserCreateSequential(this, path, is);
parser.parse();
parser.parseHeader();
if (!parser.parserHasFailed()) {
parser.parseData();
}

if (Main.this.exit_code != 0) {
LOG.error("validation failed due to errors");
Expand Down
Expand Up @@ -79,6 +79,12 @@ protected final String failExpectedGot(
return this.onFailure(sb.toString());
}

@Override
public final boolean parserHasFailed()
{
return this.state.get() == ParserState.STATE_FAILED;
}

enum ParserState
{
STATE_INITIAL,
Expand Down
Expand Up @@ -43,6 +43,12 @@ abstract class SMFBAbstractParserSequential implements
this.state = NullCheck.notNull(in_state, "State");
}

@Override
public final boolean parserHasFailed()
{
return this.state.get() == ParserState.STATE_FAILED;
}

protected abstract Logger log();

protected final String onFailure(
Expand Down Expand Up @@ -83,6 +89,7 @@ enum ParserState
{
STATE_INITIAL,
STATE_PARSED_HEADER,
STATE_FAILED
STATE_FAILED,
STATE_FINISHED
}
}
Expand Up @@ -129,10 +129,11 @@ public void parseHeader()
this.parseHeaderAttributes();
this.checkHeaderAttributes();

if (super.state.get() != ParserState.STATE_FAILED) {
if (!this.parserHasFailed()) {
super.events.onHeaderParsed(this.header);
super.state.set(ParserState.STATE_PARSED_HEADER);
}

} catch (final IOException e) {
super.fail("I/O error: " + e.getMessage());
} catch (final Exception e) {
Expand Down Expand Up @@ -884,33 +885,31 @@ private void checkHeaderAttributes()
this.attributes_named = this.attributes_named.put(name, attribute);
});

if (this.state.get() == ParserState.STATE_FAILED) {
return;
if (!this.parserHasFailed()) {
final SMFBV1SchemaIDReadableType schema_id_view =
this.header_view.getSchemaReadable();

final SMFSchemaIdentifier.Builder vb =
SMFSchemaIdentifier.builder();
vb.setVendorID(schema_id_view.getVendorId());
vb.setSchemaID(schema_id_view.getSchemaId());
vb.setSchemaMajorVersion(schema_id_view.getSchemaVersionMajor());
vb.setSchemaMinorVersion(schema_id_view.getSchemaVersionMinor());

final SMFHeader.Builder hb = SMFHeader.builder();
hb.setVertexCount(this.header_view.getVertexCount());
hb.setTriangleCount(this.header_view.getTriangleCount());
hb.setTriangleIndexSizeBits((long) this.header_view.getTriangleIndexSizeBits());
hb.setAttributesInOrder(this.attributes);
hb.setAttributesByName(this.attributes_named);
hb.setSchemaIdentifier(vb.build());
hb.setCoordinateSystem(
SMFBCoordinateSystems.unpack(
this.header_view.getCoordinateSystemReadable()));

this.header = hb.build();
this.offsets = SMFBV1Offsets.fromHeader(this.header);
}

final SMFBV1SchemaIDReadableType schema_id_view =
this.header_view.getSchemaReadable();

final SMFSchemaIdentifier.Builder vb =
SMFSchemaIdentifier.builder();
vb.setVendorID(schema_id_view.getVendorId());
vb.setSchemaID(schema_id_view.getSchemaId());
vb.setSchemaMajorVersion(schema_id_view.getSchemaVersionMajor());
vb.setSchemaMinorVersion(schema_id_view.getSchemaVersionMinor());

final SMFHeader.Builder hb = SMFHeader.builder();
hb.setVertexCount(this.header_view.getVertexCount());
hb.setTriangleCount(this.header_view.getTriangleCount());
hb.setTriangleIndexSizeBits((long) this.header_view.getTriangleIndexSizeBits());
hb.setAttributesInOrder(this.attributes);
hb.setAttributesByName(this.attributes_named);
hb.setSchemaIdentifier(vb.build());
hb.setCoordinateSystem(
SMFBCoordinateSystems.unpack(
this.header_view.getCoordinateSystemReadable()));

this.header = hb.build();
this.offsets = SMFBV1Offsets.fromHeader(this.header);
}

private void parseHeaderAttributes()
Expand Down
Expand Up @@ -96,16 +96,16 @@ protected Logger log()
return LOG;
}

private void parseHeader()
private void parseHeaderActual()
{
LOG.debug("parsing header");

try {
super.reader.readBytes(Optional.of("header"), this.header_buffer);
this.header_cursor =
JPRACursor1DByteBufferedChecked.newCursor(
this.header_buffer_wrap,
SMFBV1HeaderByteBuffered::newValueWithOffset);
this.header_buffer_wrap,
SMFBV1HeaderByteBuffered::newValueWithOffset);
this.header_view =
this.header_cursor.getElementView();

Expand All @@ -119,16 +119,17 @@ private void parseHeader()
Long.toUnsignedString((long) this.header_view.getTriangleIndexSizeBits()));
LOG.debug(
"expecting {} attributes",
Long.toUnsignedString((long) this.header_view.getAttributeCount()));
Long.toUnsignedString(this.header_view.getAttributeCount()));
}

this.parseHeaderAttributes();
this.checkHeaderAttributes();

if (super.state.get() != ParserState.STATE_FAILED) {
if (!this.parserHasFailed()) {
super.events.onHeaderParsed(this.header);
super.state.set(ParserState.STATE_PARSED_HEADER);
}

} catch (final IOException e) {
super.fail("I/O error: " + e.getMessage());
} catch (final Exception e) {
Expand Down Expand Up @@ -777,33 +778,31 @@ private void checkHeaderAttributes()
this.attributes_named = this.attributes_named.put(name, attribute);
});

if (this.state.get() == ParserState.STATE_FAILED) {
return;
if (!this.parserHasFailed()) {
final SMFBV1SchemaIDReadableType schema_id_view =
this.header_view.getSchemaReadable();

final SMFSchemaIdentifier.Builder vb =
SMFSchemaIdentifier.builder();
vb.setVendorID(schema_id_view.getVendorId());
vb.setSchemaID(schema_id_view.getSchemaId());
vb.setSchemaMajorVersion(schema_id_view.getSchemaVersionMajor());
vb.setSchemaMinorVersion(schema_id_view.getSchemaVersionMinor());

final SMFHeader.Builder hb = SMFHeader.builder();
hb.setVertexCount(this.header_view.getVertexCount());
hb.setTriangleCount(this.header_view.getTriangleCount());
hb.setTriangleIndexSizeBits((long) this.header_view.getTriangleIndexSizeBits());
hb.setAttributesInOrder(this.attributes);
hb.setAttributesByName(this.attributes_named);
hb.setSchemaIdentifier(vb.build());
hb.setCoordinateSystem(
SMFBCoordinateSystems.unpack(
this.header_view.getCoordinateSystemReadable()));

this.header = hb.build();
this.offsets = SMFBV1Offsets.fromHeader(this.header);
}

final SMFBV1SchemaIDReadableType schema_id_view =
this.header_view.getSchemaReadable();

final SMFSchemaIdentifier.Builder vb =
SMFSchemaIdentifier.builder();
vb.setVendorID(schema_id_view.getVendorId());
vb.setSchemaID(schema_id_view.getSchemaId());
vb.setSchemaMajorVersion(schema_id_view.getSchemaVersionMajor());
vb.setSchemaMinorVersion(schema_id_view.getSchemaVersionMinor());

final SMFHeader.Builder hb = SMFHeader.builder();
hb.setVertexCount(this.header_view.getVertexCount());
hb.setTriangleCount(this.header_view.getTriangleCount());
hb.setTriangleIndexSizeBits((long) this.header_view.getTriangleIndexSizeBits());
hb.setAttributesInOrder(this.attributes);
hb.setAttributesByName(this.attributes_named);
hb.setSchemaIdentifier(vb.build());
hb.setCoordinateSystem(
SMFBCoordinateSystems.unpack(
this.header_view.getCoordinateSystemReadable()));

this.header = hb.build();
this.offsets = SMFBV1Offsets.fromHeader(this.header);
}

private void parseHeaderAttributes()
Expand All @@ -830,7 +829,7 @@ private void parseHeaderAttributes()

for (long index = 0L;
Long.compareUnsigned(
index, (long) this.header_view.getAttributeCount()) < 0;
index, this.header_view.getAttributeCount()) < 0;
index = Math.addExact(index, 1L)) {

if (LOG.isDebugEnabled()) {
Expand Down Expand Up @@ -890,24 +889,38 @@ public void close()
}

@Override
public void parse()
public void parseHeader()
{
this.parseHeader();
if (this.state.get() == ParserState.STATE_FAILED) {
return;
}
this.parseHeaderActual();
}

for (final SMFAttribute attribute : this.attributes) {
this.parseAttributeData(attribute);
if (this.state.get() == ParserState.STATE_FAILED) {
return;
}
}
@Override
public void parseData()
throws IllegalStateException
{
switch (super.state.get()) {
case STATE_INITIAL: {
throw new IllegalStateException("Header has not been parsed");
}
case STATE_PARSED_HEADER: {
for (final SMFAttribute attribute : this.attributes) {
this.parseAttributeData(attribute);
if (this.parserHasFailed()) {
return;
}
}

if (this.state.get() == ParserState.STATE_FAILED) {
return;
if (!this.parserHasFailed()) {
this.parseTriangles();
}
break;
}
case STATE_FAILED: {
throw new IllegalStateException("Parser has already failed");
}
case STATE_FINISHED: {
throw new IllegalStateException("Parser has already completed");
}
}

this.parseTriangles();
}
}
Expand Up @@ -365,7 +365,6 @@ protected Logger log()
return LOG;
}


private Optional<SMFBAbstractParserSequential> parseMagicNumberAndVersion()
{
try {
Expand Down Expand Up @@ -426,7 +425,7 @@ private Optional<SMFBAbstractParserSequential> parseVersion()
}

@Override
public void parse()
public void parseHeader()
{
switch (super.state.get()) {
case STATE_INITIAL: {
Expand All @@ -436,7 +435,7 @@ public void parse()
this.parser = this.parseMagicNumberAndVersion();

if (this.parser.isPresent()) {
this.parser.get().parse();
this.parser.get().parseHeader();
} else {
Invariants.checkInvariant(
super.state.get(),
Expand All @@ -450,9 +449,39 @@ public void parse()
}
break;
}

case STATE_PARSED_HEADER: {
throw new IllegalStateException("Header has already been parsed");
}

case STATE_FAILED: {
throw new IllegalStateException("Parser has already failed");
}
}
}

@Override
public void parseData()
throws IllegalStateException
{
switch (super.state.get()) {
case STATE_INITIAL: {
throw new IllegalStateException("Header has not been parsed");
}

case STATE_PARSED_HEADER: {
if (this.parser.isPresent()) {
this.parser.get().parseData();
} else {
Invariants.checkInvariant(
super.state.get(),
super.state.get() == ParserState.STATE_FAILED,
s -> String.format(
"State %s must be %s", s, ParserState.STATE_FAILED));
}
break;
}

case STATE_FAILED: {
throw new IllegalStateException("Parser has already failed");
}
Expand Down

0 comments on commit 9a001c6

Please sign in to comment.