void
FieldInstructionStaticTemplateRef::encodeNop(
  Codecs::DataDestination & destination,
  Codecs::PresenceMap & pmap,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & accessor) const
{
  // static templateRef
  // static
  TemplateCPtr target;
  if(!encoder.findTemplate(templateName_, templateNamespace_, target))
  {
    encoder.reportFatal("[ERR D9]", "Unknown template name for static templateref.", *identity_);
  }

  // retrieve the field corresponding to this templateRef
  // which if it exists should be a FieldGroup
  const QuickFAST::Messages::MessageAccessor * group;
  if(accessor.getGroup(*identity_, group))
  {
    encoder.encodeSegmentBody(
      destination,
      pmap,
      target,
      *group);
  }
  else
  {
    encoder.encodeSegmentBody(
      destination,
      pmap,
      target,
      accessor);
  }
}
void
FieldInstructionDecimal::encodeDelta(
  Codecs::DataDestination & destination,
  Codecs::PresenceMap & /*pmap*/,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & accessor) const
{
  // assume default
  Decimal previousValue;

  // ... then initialize them from the dictionary
  Context::DictionaryStatus previousStatus = fieldOp_->getDictionaryValue(encoder, previousValue);
  if(previousStatus != Context::OK_VALUE && fieldOp_->hasValue())
  {
    previousValue = typedValue_;
    fieldOp_->setDictionaryValue(encoder, previousValue);
  }

  // get the value from the application data
  Decimal value;
  if(accessor.getDecimal(*identity_, ValueType::DECIMAL, value))
  {
    int32 exponentDelta = static_cast<int32>(value.getExponent()) - int64(previousValue.getExponent());
    if(!isMandatory())
    {
      if(exponentDelta >= 0)
      {
        exponentDelta += 1;
      }
    }
    encodeSignedInteger(destination, encoder.getWorkingBuffer(), exponentDelta);

    int64 mantissaDelta = int64(value.getMantissa()) - int64(previousValue.getMantissa());
    encodeSignedInteger(destination, encoder.getWorkingBuffer(), mantissaDelta);

    if(previousStatus != Context::OK_VALUE  || value != previousValue)
    {
      fieldOp_->setDictionaryValue(encoder, value);
    }
  }
  else // not defined by accessor
  {
    if(isMandatory())
    {
      encoder.reportFatal("[ERR U01]", "Missing mandatory field.", *identity_);
    }
    destination.putByte(nullInteger);
  }
}
void
FieldInstructionDecimal::encodeDefault(
  Codecs::DataDestination & destination,
  Codecs::PresenceMap & pmap,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & accessor) const
{
  // get the value from the application data
  Decimal value;
  if(accessor.getDecimal(*identity_, ValueType::DECIMAL, value))
  {
    if(typedValueIsDefined_ &&
      value == typedValue_)
    {
      pmap.setNextField(false); // not in stream. use default
    }
    else
    {
      pmap.setNextField(true); // != default.  Send value

      if(isMandatory())
      {
        encodeDecimal(destination, encoder.getWorkingBuffer(), value.getExponent(), value.getMantissa());
      }
      else
      {
        encodeNullableDecimal(destination, encoder.getWorkingBuffer(), value.getExponent(), value.getMantissa());
      }
    }
  }
  else // not defined by accessor
  {
    if(isMandatory())
    {
      encoder.reportFatal("[ERR U01]", "Missing mandatory field.", *identity_);
    }
    // if there is a default value
    // you have to cancel this by sending a null.
    if(fieldOp_->hasValue())
    {
      pmap.setNextField(true);
      destination.putByte(nullDecimal);
    }
    else
    {
      pmap.setNextField(false);
    }
  }
}
void
FieldInstructionDecimal::encodeConstant(
  Codecs::DataDestination & /*destination*/,
  Codecs::PresenceMap & pmap,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & accessor) const
{
  if(!isMandatory())
  {
    // get the value from the application data
    Decimal value;
    if(accessor.getDecimal(*identity_, ValueType::DECIMAL, value))
    {
      if(value != typedValue_)
      {
        encoder.reportFatal("[ERR U10]", "Constant value does not match application data.", *identity_);
      }

      pmap.setNextField(true);
    }
    else // not defined by accessor
    {
      pmap.setNextField(false);
    }
  }
}
void
FieldInstructionDynamicTemplateRef::encodeNop(
  Codecs::DataDestination & destination,
  Codecs::PresenceMap & pmap,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & accessor) const
{
  encoder.reportFatal("[ERR I1]", "Encoding dynamic templates is not supported.");
}
void
FieldInstruction::encodeTail(
  Codecs::DataDestination & /*destination*/,
  Codecs::PresenceMap & /*pmap*/,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & /*fieldSet*/) const
{
  encoder.reportFatal("[ERR S2]", "Tail Field Operator not supported for this data type.", identity_);
}
void
FieldInstructionGroup::encodeNop(
  Codecs::DataDestination & destination,
  Codecs::PresenceMap & pmap,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & messageAccessor) const
{
  if(!segmentBody_)
  {
    encoder.reportFatal("[ERR U08}", "Segment not defined for Group instruction.");
  }
  // retrieve the field corresponding to this group
  // Note that applications may support merging groups
  // by returning true from getGroup but using the same accessor.
  const Messages::MessageAccessor * group;
  if(messageAccessor.getGroup(*identity_, group))
  {
    if(! isMandatory())
    {
      pmap.setNextField(true);
    }
    encoder.encodeGroup(destination, segmentBody_, *group);
    messageAccessor.endGroup(*identity_, group);
  }
  else
  {
    if(isMandatory())
    {
      encoder.reportFatal("[ERR U01]", "Missing mandatory group.");
      encoder.encodeGroup(destination, segmentBody_, messageAccessor);
    }
    else
    {
      pmap.setNextField(false);
    }
  }
}
void
FieldInstructionDecimal::encodeCopy(
  Codecs::DataDestination & destination,
  Codecs::PresenceMap & pmap,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & accessor) const
{
  Decimal previousValue(0,0);
  Context::DictionaryStatus previousStatus = fieldOp_->getDictionaryValue(encoder, previousValue);
  if(previousStatus == Context::UNDEFINED_VALUE)
  {
    if(fieldOp_->hasValue())
    {
      previousValue = typedValue_;
      fieldOp_->setDictionaryValue(encoder, previousValue);
      // pretend we got the data from the dictionary
      previousStatus = Context::OK_VALUE;
    }
    else
    {
      // pretend we got a null from the dictionary
      fieldOp_->setDictionaryValueNull(encoder);
      previousStatus = Context::NULL_VALUE;
    }
  }

  // get the value from the application data
  Decimal value;
  if(accessor.getDecimal(*identity_, ValueType::DECIMAL, value))
  {
    if(previousStatus == Context::OK_VALUE && previousValue == value)
    {
      pmap.setNextField(false); // not in stream, use copy
    }
    else
    {
      pmap.setNextField(true);// value in stream
      if(isMandatory())
      {
        encodeDecimal(destination, encoder.getWorkingBuffer(), value.getExponent(), value.getMantissa());
      }
      else
      {
        encodeNullableDecimal(destination, encoder.getWorkingBuffer(), value.getExponent(), value.getMantissa());
      }
      fieldOp_->setDictionaryValue(encoder, value);
    }
  }
  else // not defined by accessor
  {
    if(isMandatory())
    {
      encoder.reportFatal("[ERR U01]", "Missing mandatory decimal field.", *identity_);
      // if reportFatal returns we're being lax about encoding rules
      // let the copy happen.
      pmap.setNextField(false);
    }
    else
    {
      // Missing optional field.  If we have a previous, non-null value
      // we need to explicitly null it out.  Otherwise just don't send it.
      if(previousValue != Context::NULL_VALUE)
      {
        pmap.setNextField(true);// value in stream
        destination.putByte(nullDecimal);
        fieldOp_->setDictionaryValueNull(encoder);
      }
      else
      {
        pmap.setNextField(false);
      }
    }
  }
}
void
FieldInstructionDecimal::encodeNop(
  Codecs::DataDestination & destination,
  Codecs::PresenceMap & pmap,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & accessor) const
{
  // get the value from the application data
  Decimal value;
  if(accessor.getDecimal(*identity_, ValueType::DECIMAL, value))
  {
    exponent_t exponent = value.getExponent();
    mantissa_t mantissa = value.getMantissa();

    if(bool(exponentInstruction_))
    {
      Messages::FieldCPtr exponentField(Messages::FieldInt32::create(exponent));
      Messages::SingleFieldAccessor exponentAccessor(exponentInstruction_->getIdentity(), exponentField);

      exponentInstruction_->encode(
        destination,
        pmap,
        encoder,
        exponentAccessor);

      Messages::FieldCPtr mantissaField(Messages::FieldInt64::create(mantissa));
      Messages::SingleFieldAccessor mantissaAccessor(mantissaInstruction_->getIdentity(), mantissaField);

      mantissaInstruction_->encode(
        destination,
        pmap,
        encoder,
        mantissaAccessor);

    }
    else
    {
      if(!isMandatory())
      {
        encodeNullableDecimal(
          destination,
          encoder.getWorkingBuffer(),
          value.getExponent(),
          value.getMantissa());
      }
      else
      {
        encodeDecimal(
          destination,
          encoder.getWorkingBuffer(),
          value.getExponent(),
          value.getMantissa());
      }
    }
  }
  else // not defined by accessor
  {
    if(isMandatory())
    {
      encoder.reportFatal("[ERR U01]", "Missing mandatory field.", *identity_);
    }
    if(exponentInstruction_)
    {
      Messages::EmptyAccessor empty;
      exponentInstruction_->encode(
        destination,
        pmap,
        encoder,
        empty);
    }
    else
    {
      destination.putByte(nullInteger);
    }
  }
}
void
FieldInstructionSequence::encodeNop(
  Codecs::DataDestination & destination,
  Codecs::PresenceMap & pmap,
  Codecs::Encoder & encoder,
  const Messages::MessageAccessor & accessor) const
{
  if(!segment_)
  {
    encoder.reportFatal("[ERR U07]", "SegmentBody not defined for Sequence instruction.");
  }

  size_t length = 0;
  if(accessor.getSequenceLength(*identity_, length))
  {
    Messages::FieldCPtr lengthField(Messages::FieldUInt32::create(QuickFAST::uint32(length)));

    Codecs::FieldInstructionCPtr lengthInstruction;
    if(segment_->getLengthInstruction(lengthInstruction))
    {
      Messages::SingleFieldAccessor accessor(lengthInstruction->getIdentity(), lengthField);
      lengthInstruction->encode(destination, pmap, encoder, accessor);
    }
    else
    {
       FieldInstructionUInt32 defaultLengthInstruction;
       defaultLengthInstruction.setPresence(isMandatory());
       Messages::SingleFieldAccessor accessor(defaultLengthInstruction.getIdentity(), lengthField);
       defaultLengthInstruction.encode(destination, pmap, encoder, accessor);
    }

    for(size_t pos = 0; pos < length; ++pos)
    {
      const Messages::MessageAccessor * entry;
      if(accessor.getSequenceEntry(*identity_, pos, entry))
      {
        encoder.encodeGroup(destination, segment_, *entry);
      }
      else
      {
        std::stringstream msg;
        msg << "Sequence entry " << pos << " of " << length << " missing.";
        encoder.reportError("Uxx", msg.str(), *identity_);
      }
      accessor.endSequenceEntry(*identity_, pos, entry);
    }
    accessor.endSequence(*identity_);
  }
  else
  {
    // The sequence is not present in the application record
    if(isMandatory())
    {
      encoder.reportFatal("[ERR U01]", "Missing mandatory sequence.");
      // if reportFail returns, we're being lax about encoding rules
      // Send a sequence with no entries.
      Codecs::FieldInstructionCPtr lengthInstruction;
      if(segment_->getLengthInstruction(lengthInstruction))
      {
         Messages::SingleFieldAccessor accessor(lengthInstruction->getIdentity(), 0);
        lengthInstruction->encode(destination, pmap, encoder, accessor);
      }
      else
      {
        destination.putByte(zeroIntegerNonnullable);
      }
    }
    else
    {
      Codecs::FieldInstructionCPtr lengthInstruction;
      if(segment_->getLengthInstruction(lengthInstruction))
      {
        // let the length instruction encode the fact that it's missing
        Messages::EmptyAccessor accessor;
        lengthInstruction->encode(destination, pmap, encoder, accessor);
      }
      else
      {
        // implicit length instruction: nullable uint32 with no field operator
        destination.putByte(nullInteger);
      }
    }
  }
}