Skip to content

Commit

Permalink
[#163] Move ZscriptExpression towards using ZscriptField
Browse files Browse the repository at this point in the history
  • Loading branch information
susanw1 committed Sep 9, 2024
1 parent 56f6694 commit f56d678
Show file tree
Hide file tree
Showing 12 changed files with 122 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public boolean isValid() {
}

@Override
public OptionalInt getField(char key) {
public OptionalInt getField(byte key) {
return expression.getField(key);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ public interface ZscriptResponse {
*/
boolean isValid();

OptionalInt getField(char key);
OptionalInt getField(byte key);

default boolean succeeded() {
OptionalInt status = getField((char) Zchars.Z_STATUS);
OptionalInt status = getField(Zchars.Z_STATUS);
return status.isEmpty() || status.getAsInt() == ZscriptStatus.SUCCESS;
}

default boolean failed() {
OptionalInt status = getField((char) Zchars.Z_STATUS);
OptionalInt status = getField(Zchars.Z_STATUS);
return status.isPresent() && ZscriptStatus.isFailure(status.getAsInt());
}

default boolean error() {
OptionalInt status = getField((char) Zchars.Z_STATUS);
OptionalInt status = getField(Zchars.Z_STATUS);
return status.isPresent() && ZscriptStatus.isError(status.getAsInt());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ public boolean isValid() {
}

@Override
public OptionalInt getField(char key) {
public OptionalInt getField(byte key) {
return expression.getField(key);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package net.zscript.javaclient.commandPaths;

import net.zscript.model.components.Zchars;
import net.zscript.model.components.ZscriptStatus;
import net.zscript.util.ByteString;
import net.zscript.util.ByteString.ByteAppendable;

Expand Down Expand Up @@ -33,20 +35,23 @@ public boolean isEmpty() {
}

public boolean canFail() {
// can't fail if it's the trivial empty command
if (isEmpty()) {
return false;
}
if (fieldSet.getFieldValue('Z') == 1) {
int sVal = fieldSet.getFieldValue('S');
return sVal > 0x00 && sVal < 0x10;
// special case: "Z1 S{status}" command, where {status} is a failure code (esp COMMAND_FAIL_CONTROL)
if (fieldSet.getFieldVal(Zchars.Z_CMD) == 1) {
int sVal = fieldSet.getFieldVal(Zchars.Z_STATUS);
return ZscriptStatus.isFailure(sVal);
}
return true;
}

public boolean canSucceed() {
if (fieldSet.getFieldValue('Z') == 1) {
int sVal = fieldSet.getFieldValue('S');
return sVal == 0 || sVal == -1;
// special case: "Z1" command, where 'S' is missing, or has a zero (success) code
if (fieldSet.getFieldVal(Zchars.Z_CMD) == 1) {
int sVal = fieldSet.getFieldVal(Zchars.Z_STATUS);
return sVal == -1 || ZscriptStatus.isSuccess(sVal);
}
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import net.zscript.tokenizer.TokenBuffer;
import net.zscript.tokenizer.TokenBufferIterator;
import net.zscript.tokenizer.ZscriptExpression;
import net.zscript.tokenizer.ZscriptField;
import net.zscript.util.ByteString;
import net.zscript.util.ByteString.ByteAppendable;
import net.zscript.util.ByteString.ByteStringBuilder;
Expand Down Expand Up @@ -83,6 +84,9 @@ private ZscriptFieldSet(List<BigField> bigFields, int[] fields, boolean hasClash
this.hasClash = hasClash;
}

/**
* @return true if this expression has no numeric fields and no big-fields; false otherwise
*/
public boolean isEmpty() {
if (!bigFields.isEmpty()) {
return false;
Expand All @@ -95,11 +99,11 @@ public boolean isEmpty() {
return true;
}

public int getFieldValue(byte key) {
public int getFieldVal(byte key) {
return fields[key - 'A'];
}

public int getFieldValue(char key) {
public int getFieldVal(char key) {
return fields[key - 'A'];
}

Expand All @@ -122,7 +126,6 @@ public void appendTo(ByteStringBuilder builder) {
if (i != 'Z' - 'A' && fields[i] != -1) {
builder.appendByte((byte) (i + 'A')).appendNumeric16(fields[i]);
}

}
for (BigField big : bigFields) {
big.appendTo(builder);
Expand All @@ -148,18 +151,49 @@ public int getBufferLength() {
return length;
}

@Override
public OptionalInt getField(byte key) {
return fields[key - 'A'] == -1 ? OptionalInt.empty() : OptionalInt.of(fields[key - 'A']);
}

// FIXME - this needs externalizing
@Override
public Optional<? extends ZscriptField> getField2(byte key) {
int v = fields[key - 'A'];
return Optional.ofNullable(v != -1 ? new ZscriptField() {
@Override
public byte getKey() {
return key;
}

@Override
public int getValue() {
return v;
}

@Override
public boolean isBigField() {
return false;
}

@Override
public BlockIterator iterator() {
return null;
}
} : null);
}

@Override
public int getFieldCount() {
return (int) Arrays.stream(fields).filter(f -> f != 0).count();
return (int) Arrays.stream(fields).filter(f -> f != -1).count();
}

@Override
public boolean hasBigField() {
return !bigFields.isEmpty();
}

@Override
public int getBigFieldSize() {
return bigFields.stream()
.mapToInt(BigField::getDataLength)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private void explainField(TextBox box, ZscriptDataModel.GenericField field, bool
explainBigField(box, field, fieldSet, settings);
} else {
doneFields[key - 'A'] = true;
int value = fieldSet.getFieldValue(key);
int value = fieldSet.getFieldVal(key);
if (value == -1) {
if (field.isRequired()) {
box.setStyle(new CharacterStyle(TextColor.RED, TextColor.DEFAULT, true))
Expand Down Expand Up @@ -161,7 +161,7 @@ private void explainStatus(ZscriptModel model, CommandPrintSettings settings, Zs
box.append(upperFirst(field.getName()));
box.append(" (").append(key).append("): ");
doneFields[key - 'A'] = true;
int value = fieldSet.getFieldValue(key);
int value = fieldSet.getFieldVal(key);
if (value == -1) {
if (field.isRequired()) {
box.setStyle(new CharacterStyle(TextColor.RED, TextColor.DEFAULT, true));
Expand Down Expand Up @@ -209,13 +209,13 @@ private void explainStatus(ZscriptModel model, CommandPrintSettings settings, Zs

private void explainUnknownFields(TextBox box, CommandPrintSettings settings, ZscriptFieldSet fieldSet, boolean[] doneFields) {
for (int i = 0; i < 26; i++) {
if (!doneFields[i] && fieldSet.getFieldValue((byte) ('A' + i)) != -1) {
if (!doneFields[i] && fieldSet.getFieldVal((byte) ('A' + i)) != -1) {
box.startNewLine(1);
box.append("Unknown Field ");
box.append((char) ('A' + i));
box.append(" with value: ");
box.append("0x");
box.appendHex(fieldSet.getFieldValue((byte) ('A' + i)), 1);
box.appendHex(fieldSet.getFieldVal((byte) ('A' + i)), 1);
}
}
}
Expand All @@ -226,7 +226,7 @@ public AsciiFrame explainCommand(Command target, ZscriptModel model, CommandPrin

ZscriptFieldSet fieldSet = target.getFields();

int commandValue = fieldSet.getFieldValue('Z');
int commandValue = fieldSet.getFieldVal('Z');
box.startNewLine(0);
if (fieldSet.isEmpty()) {
box.append("Empty Command");
Expand Down Expand Up @@ -273,7 +273,7 @@ public AsciiFrame explainCommand(Command target, ZscriptModel model, CommandPrin
}

public AsciiFrame explainResponse(Command source, Response target, ZscriptModel model, CommandPrintSettings settings) {
int commandValue = source.getFields().getFieldValue('Z');
int commandValue = source.getFields().getFieldVal('Z');
ZscriptFieldSet fieldSet = target.getFields();

TextBox box = new TextBox(settings.indentString);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
import net.zscript.javaclient.commandPaths.Command;
import net.zscript.javaclient.commandPaths.MatchedCommandResponse;
import net.zscript.javaclient.commandPaths.Response;
import net.zscript.javaclient.commandbuilder.ZscriptResponse;
import net.zscript.javaclient.commandbuilder.commandnodes.ResponseCaptor;
import net.zscript.javaclient.commandbuilder.commandnodes.ZscriptCommandNode;
import net.zscript.javaclient.commandbuilder.ZscriptResponse;
import net.zscript.model.components.Zchars;

public class ResponseSequenceCallback {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import net.zscript.tokenizer.BlockIterator;
import net.zscript.tokenizer.TokenBuffer.TokenReader.ReadToken;
import net.zscript.tokenizer.ZscriptExpression;
import net.zscript.tokenizer.ZscriptField;
import net.zscript.tokenizer.ZscriptTokenExpression;
import net.zscript.tokenizer.ZscriptTokenField;
import net.zscript.util.ByteString;
Expand Down Expand Up @@ -43,6 +44,11 @@ public OptionalInt getField(final byte key) {
return expression.getField(key);
}

@Override
public Optional<? extends ZscriptField> getField2(byte key) {
return expression.getField2(key);
}

@Override
public int getFieldCount() {
return expression.getFieldCount();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

import java.util.Iterator;

public interface BlockIterator extends Iterator<Byte> {
import net.zscript.util.ByteString;

/**
* Defines an iterator that works over buffers of bytes, revealing them byte at a time, or in contiguous blocks.
*/
public interface BlockIterator extends Iterator<Byte>, ByteString.ByteAppendable {
/**
* Returns as many bytes in the iteration as are contiguous in memory (would give a pointer into the iterated structure in C++).
*
Expand All @@ -16,4 +21,22 @@ public interface BlockIterator extends Iterator<Byte> {
* @return an array of as many bytes (up to maxLength) as are contiguous in the structure.
*/
byte[] nextContiguous(int maxLength);

/**
* Defines how to append the (remaining) bytes from this iterator to make a ByteString, in efficient contiguous blocks. Note that if iteration has already started, the bytes
* already read will be absent. The iterator will be fully consumed.
* </p>
* As an ByteAppendable, it may be used like this:
* <pre>{@code
* BlockIterator iter = ...
* ByteString b = ByteString.from(iter);
* }</pre>
*
* @param builder the builder to append to
*/
default void appendTo(ByteString.ByteStringBuilder builder) {
while (hasNext()) {
builder.appendRaw(nextContiguous());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.zscript.tokenizer;

import java.util.Optional;
import java.util.OptionalInt;

import net.zscript.util.ByteString;
Expand All @@ -9,13 +10,36 @@
* sequence.
*/
public interface ZscriptExpression {
/**
* Gets the ZscriptField representing the specified numeric field (key, value), if it exists.
*
* @param key the key of the required field
* @return the field, or empty if the field isn't defined
*/
Optional<? extends ZscriptField> getField2(byte key);

/**
* Gets the ZscriptField representing the specified numeric field (key, value), if it exists.
*
* @param key the key of the required field
* @return the field, or empty if the field isn't defined
*/
default Optional<? extends ZscriptField> getField2(char key) {
return getField2((byte) key);
}

/**
* Gets the value of the specified field.
*
* @param key the key of the required field
* @return the value of that field, or empty if the field isn't defined
*/
OptionalInt getField(byte key);
default OptionalInt getField(byte key) {
// I thought there would be a super-cool way to do this that wasn't basically an if-statement...OptionalInt makes it messy.
return getField2(key)
.map(f -> OptionalInt.of(f.getValue()))
.orElseGet(OptionalInt::empty);
}

/**
* Gets the value of the specified field.
Expand Down Expand Up @@ -86,7 +110,7 @@ default int getField(final char key, final int def) {
/**
* Determines the total number of bytes in the big-field (or fields, concatenated, if there are several).
*
* @return the big-field size, in bytes
* @return the big-field size, in bytes (zero if no big-field is found)
*/
int getBigFieldSize();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.function.Supplier;

import net.zscript.model.components.Zchars;
Expand Down Expand Up @@ -42,11 +41,11 @@ public Optional<ReadToken> next() {
}

@Override
public OptionalInt getField(byte key) {
public Optional<? extends ZscriptField> getField2(byte key) {
return iteratorToMarker().stream()
.filter(tok -> tok.getKey() == key)
.mapToInt(ReadToken::getData16)
.findFirst();
.findFirst()
.map(ZscriptTokenField::new);
}

@Override
Expand Down Expand Up @@ -95,6 +94,7 @@ public boolean hasNext() {
for (Optional<ReadToken> opt = it.next(); opt.isPresent(); opt = it.next()) {
ReadToken token = opt.get();
if (Zchars.isBigField(token.getKey())) {
// note that the token's blockIterator handles continuation blocks
internal = token.blockIterator();
if (internal.hasNext()) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,4 @@ public boolean isBigField() {
public BlockIterator iterator() {
return token.blockIterator();
}

}

0 comments on commit f56d678

Please sign in to comment.