Ejemplo n.º 1
0
/**
 * Return DmtxTrue 1 or 2 X12 values remain, otherwise DmtxFalse
 */
static DmtxBoolean
PartialX12ChunkRemains(DmtxEncodeStream *stream)
{
   DmtxEncodeStream streamTmp;
   DmtxByte inputValue;
   DmtxByte valueListStorage[6];
   DmtxByteList valueList = dmtxByteListBuild(valueListStorage, sizeof(valueListStorage));
   DmtxPassFail passFail;

   /* Create temporary copy of stream to track test input progress */
   streamTmp = *stream;
   streamTmp.currentScheme = DmtxSchemeX12;
   streamTmp.outputChainValueCount = 0;
   streamTmp.outputChainWordCount = 0;
   streamTmp.reason = NULL;
   streamTmp.sizeIdx = DmtxUndefined;
   streamTmp.status = DmtxStatusEncoding;
   streamTmp.output = NULL;

   while(StreamInputHasNext(&streamTmp))
   {
      inputValue = StreamInputAdvanceNext(&streamTmp);
      if(stream->status != DmtxStatusEncoding)
      {
         StreamMarkInvalid(stream, DmtxErrorUnknown);
         return DmtxFalse;
      }

      /* Expand next input value into up to 4 CTX values and add to valueList */
      PushCTXValues(&valueList, inputValue, streamTmp.currentScheme, &passFail);
      if(passFail == DmtxFail)
      {
         StreamMarkInvalid(stream, DmtxErrorUnknown);
         return DmtxFalse;
      }

      /* Not a final partial chunk */
      if(valueList.length >= 3)
         return DmtxFalse;
   }

   return (valueList.length == 0) ? DmtxFalse : DmtxTrue;
}
Ejemplo n.º 2
0
/**
 * Simple single scheme encoding uses "Normal"
 * The optimizer needs to track "Expanded" and "Compact" streams separately, so they
 * are called explicitly.
 *
 *   Normal:   Automatically collapses 2 consecutive digits into one codeword
 *   Expanded: Uses a whole codeword to represent a digit (never collapses)
 *   Compact:  Collapses 2 digits into a single codeword or marks the stream
 *             invalid if either values are not digits
 *
 * \param stream
 * \param option [Expanded|Compact|Normal]
 */
static void
EncodeNextChunkAscii(DmtxEncodeStream *stream, int option)
{
   DmtxByte v0, v1;
   DmtxBoolean compactDigits;

   if(StreamInputHasNext(stream))
   {
      v0 = StreamInputAdvanceNext(stream); CHKERR;

      if((option == DmtxEncodeCompact || option == DmtxEncodeNormal) &&
            StreamInputHasNext(stream))
      {
         v1 = StreamInputPeekNext(stream); CHKERR;
         compactDigits = (ISDIGIT(v0) && ISDIGIT(v1)) ? DmtxTrue : DmtxFalse;
      }
      else /* option == DmtxEncodeFull */
      {
         v1 = 0;
         compactDigits = DmtxFalse;
      }

      if(compactDigits == DmtxTrue)
      {
         /* Two adjacent digit chars: Make peek progress official and encode */
         StreamInputAdvanceNext(stream); CHKERR;
         AppendValueAscii(stream, 10 * (v0-'0') + (v1-'0') + 130); CHKERR;
      }
      else if(option == DmtxEncodeCompact)
      {
         /* Can't compact non-digits */
         StreamMarkInvalid(stream, DmtxErrorCantCompactNonDigits);
      }
      else
      {
         /* Encode single ASCII value */
         if(v0 < 128)
         {
            /* Regular ASCII */
            AppendValueAscii(stream, v0 + 1); CHKERR;
         }
         else
         {
            /* Extended ASCII */
            AppendValueAscii(stream, DmtxValueAsciiUpperShift); CHKERR;
            AppendValueAscii(stream, v0 - 127); CHKERR;
         }
      }
   }
}
Ejemplo n.º 3
0
static void
EncodeNextChunkCTX(DmtxEncodeStream *stream, int sizeIdxRequest)
{
   DmtxPassFail passFail;
   DmtxByte inputValue;
   DmtxByte valueListStorage[6];
   DmtxByteList valueList = dmtxByteListBuild(valueListStorage, sizeof(valueListStorage));

   while(StreamInputHasNext(stream))
   {
      inputValue = StreamInputAdvanceNext(stream); CHKERR;

      /* Expand next input value into up to 4 CTX values and add to valueList */
      PushCTXValues(&valueList, inputValue, stream->currentScheme, &passFail);
      if(passFail == DmtxFail)
      {
         /* XXX Perhaps PushCTXValues should return this error code */
         StreamMarkInvalid(stream, DmtxErrorUnsupportedCharacter);
         return;
      }

      /* If there at least 3 CTX values available encode them to output */
      while(valueList.length >= 3)
      {
         AppendValuesCTX(stream, &valueList); CHKERR;
         ShiftValueListBy3(&valueList, &passFail); CHKPASS;
      }

      /* Finished on byte boundary -- done with current chunk */
      if(valueList.length == 0)
         break;
   }

   /*
    * Special case: If all input values have been consumed and 1 or 2 unwritten
    * C40/Text/X12 values remain, finish encoding the symbol according to the
    * established end-of-symbol conditions.
    */
   if(!StreamInputHasNext(stream) && valueList.length > 0)
   {
      if(stream->currentScheme == DmtxSchemeX12)
      {
         CompletePartialX12(stream, &valueList, sizeIdxRequest); CHKERR;
      }
      else
      {
         CompletePartialC40Text(stream, &valueList, sizeIdxRequest); CHKERR;
      }
   }
}
Ejemplo n.º 4
0
static void
AdvanceCTX(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest,
      int targetState, int inputNext, int ctxValueCount, int sizeIdxRequest)
{
   DmtxEncodeStream *currentStream = &(streamsBest[targetState]);
   DmtxEncodeStream *targetStream = &(streamsNext[targetState]);
   DmtxBoolean isStartState;

   /* we won't actually use inputNext here */
   switch(targetState)
   {
      case C40Offset0:
      case TextOffset0:
      case X12Offset0:
         isStartState = (ctxValueCount % 3 == 0) ? DmtxTrue : DmtxFalse;
         break;

      case C40Offset1:
      case TextOffset1:
      case X12Offset1:
         isStartState = (ctxValueCount % 3 == 1) ? DmtxTrue : DmtxFalse;
         break;

      case C40Offset2:
      case TextOffset2:
      case X12Offset2:
         isStartState = (ctxValueCount % 3 == 2) ? DmtxTrue : DmtxFalse;
         break;

      default:
         StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue);
         return;
   }

   if(inputNext < currentStream->inputNext)
   {
      StreamCopy(targetStream, currentStream);
   }
   else if(isStartState == DmtxTrue)
   {
      StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest);
   }
   else
   {
      StreamCopy(targetStream, currentStream);
      StreamMarkInvalid(targetStream, DmtxErrorUnknown);
   }
}
Ejemplo n.º 5
0
static void
AdvanceEdifact(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest,
      int targetState, int inputNext, int sizeIdxRequest)
{
   DmtxEncodeStream *currentStream = &(streamsBest[targetState]);
   DmtxEncodeStream *targetStream = &(streamsNext[targetState]);
   DmtxBoolean isStartState;

   switch(targetState)
   {
      case EdifactOffset0:
         isStartState = (inputNext % 4 == 0) ? DmtxTrue : DmtxFalse;
         break;

      case EdifactOffset1:
         isStartState = (inputNext % 4 == 1) ? DmtxTrue : DmtxFalse;
         break;

      case EdifactOffset2:
         isStartState = (inputNext % 4 == 2) ? DmtxTrue : DmtxFalse;
         break;

      case EdifactOffset3:
         isStartState = (inputNext % 4 == 3) ? DmtxTrue : DmtxFalse;
         break;

      default:
         StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue);
         return;
   }

   if(isStartState == DmtxTrue)
   {
      StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest);
   }
   else
   {
      StreamCopy(targetStream, currentStream);
      if(currentStream->status == DmtxStatusEncoding && currentStream->currentScheme == DmtxSchemeEdifact)
         EncodeNextChunk(targetStream, DmtxSchemeEdifact, DmtxEncodeNormal, sizeIdxRequest);
      else
         StreamMarkInvalid(targetStream, DmtxErrorUnknown);
   }
}
Ejemplo n.º 6
0
static void
AppendUnlatchCTX(DmtxEncodeStream *stream)
{
   if(!IsCTX(stream->currentScheme))
   {
      StreamMarkFatal(stream, DmtxErrorUnexpectedScheme);
      return;
   }

   /* Verify we are on byte boundary */
   if(stream->outputChainValueCount % 3 != 0)
   {
      StreamMarkInvalid(stream, DmtxErrorNotOnByteBoundary);
      return;
   }

   StreamOutputChainAppend(stream, DmtxValueCTXUnlatch); CHKERR;

   stream->outputChainValueCount++;
}
Ejemplo n.º 7
0
static void
AdvanceAsciiCompact(DmtxEncodeStream *streamsNext, DmtxEncodeStream *streamsBest,
      int targetState, int inputNext, int sizeIdxRequest)
{
   DmtxEncodeStream *currentStream = &(streamsBest[targetState]);
   DmtxEncodeStream *targetStream = &(streamsNext[targetState]);
   DmtxBoolean isStartState;

   switch(targetState)
   {
      case AsciiCompactOffset0:
         isStartState = (inputNext % 2 == 0) ? DmtxTrue : DmtxFalse;
         break;

      case AsciiCompactOffset1:
         isStartState = (inputNext % 2 == 1) ? DmtxTrue : DmtxFalse;
         break;

      default:
         StreamMarkFatal(targetStream, DmtxErrorIllegalParameterValue);
         return;
   }

   if(inputNext < currentStream->inputNext)
   {
      StreamCopy(targetStream, currentStream);
   }
   else if(isStartState == DmtxTrue)
   {
      StreamAdvanceFromBest(streamsNext, streamsBest, targetState, sizeIdxRequest);
   }
   else
   {
      StreamCopy(targetStream, currentStream);
      StreamMarkInvalid(targetStream, DmtxErrorUnknown);
   }
}