static private GetExpectedTag ( byte tag, ISchema schema ) : Tag | ||
tag | byte | The input context tag |
schema | ISchema | The schema |
return | Tag |
/// <summary> /// Determines whether an option has a value /// </summary> /// <returns>True if the option has a value, false otherwise</returns> public bool OptionHasValue() { _require(StreamOp.Option); // get the expected tag for an option of this type var option = (OptionSchema)_state.Schema; var expected = Utils.GetExpectedTag(_state.Tag, option.ElementType); bool hasValue = _reader.AtTag(expected.ContextTag, expected.ApplicationTag); if (hasValue) { _stack.Push(_state); _state = new SchemaState(option.ElementType, _state.Tag, -1); } else { _moveNext(); } return(hasValue); }
/// <summary> /// Enters a choice value /// </summary> /// <returns>The index of the active choice</returns> public byte EnterChoice() { _require(StreamOp.EnterChoice); _reader.ReadOpenTag(_state.Tag); var choice = ((ChoiceSchema)_state.Schema); for (int i = 0; i < choice.Fields.Length; i++) { var field = choice.Fields[i]; var expected = Utils.GetExpectedTag(field.Tag, field.Type); if (_reader.AtTag(expected.ContextTag, expected.ApplicationTag)) { _stack.Push(new SchemaState(choice, _state.Tag, (byte)i)); _state = new SchemaState(field.Type, field.Tag, -1); return((byte)i); } } throw new UnexpectedTagException(); }
/// <summary> /// Moves the current state to the next value to read /// </summary> private void _moveNext() { if (_stack.Count == 0) { _state = new SchemaState(PrimitiveSchema.EOF, 255, -1); return; } var parent = _stack.Pop(); if (parent.Schema.Type == Types.ValueType.Option) { // we skip option states on the way back up _moveNext(); } else if (parent.Schema.Type == Types.ValueType.Sequence) { var sequence = (SequenceSchema)parent.Schema; var newParent = new SchemaState(sequence, parent.Tag, parent.Index + 1); if (newParent.Index == sequence.Fields.Length) { // we have read all of fields _state = newParent; } else { // we still have at least 1 field to read _stack.Push(newParent); var field = sequence.Fields[newParent.Index]; _state = new SchemaState(field.Type, field.Tag, -1); } } else if (parent.Schema.Type == Types.ValueType.Choice) { var choice = (ChoiceSchema)parent.Schema; _state = new SchemaState(choice, parent.Tag, choice.Fields.Length); } else if (parent.Schema.Type == Types.ValueType.Array) { var array = (ArraySchema)parent.Schema; // TODO: Might still need better logic for detecting // whether we are at the end of the array if (_reader.EOF()) { _state = new SchemaState(array, parent.Tag, parent.Index + 1); } else if (array.ElementType == PrimitiveSchema.GenericSchema) { if (_reader.AtTag(parent.Tag, ApplicationTag.Null)) { _state = new SchemaState(array, parent.Tag, parent.Index + 1); } else { var newParent = new SchemaState(array, parent.Tag, parent.Index + 1); _stack.Push(newParent); _state = new SchemaState(array.ElementType, 255, -1); } } else { var elementExpected = Utils.GetExpectedTag(255, array.ElementType); if (_reader.AtTag(elementExpected.ContextTag, elementExpected.ApplicationTag)) { var newParent = new SchemaState(array, parent.Tag, parent.Index + 1); _stack.Push(newParent); _state = new SchemaState(array.ElementType, 255, -1); } else { _state = new SchemaState(array, parent.Tag, parent.Index + 1); } } } else { throw new Exception("unknown parent schema state, can't move next"); } }