/** * Can we just receive a length to pad here? I don't like receiving * sizeIdxRequest (or sizeIdx) this late in the game */ static void PadRemainingInAscii(DmtxEncodeStream *stream, int sizeIdx) { int symbolRemaining; DmtxByte padValue; CHKSCHEME(DmtxSchemeAscii); CHKSIZE; symbolRemaining = GetRemainingSymbolCapacity(stream->output->length, sizeIdx); /* First pad character is not randomized */ if(symbolRemaining > 0) { padValue = DmtxValueAsciiPad; StreamOutputChainAppend(stream, padValue); CHKERR; symbolRemaining--; } /* All remaining pad characters are randomized based on character position */ while(symbolRemaining > 0) { padValue = Randomize253State(DmtxValueAsciiPad, stream->output->length + 1); StreamOutputChainAppend(stream, padValue); CHKERR; symbolRemaining--; } }
static void AppendValuesCTX(DmtxEncodeStream *stream, DmtxByteList *valueList) { int pairValue; DmtxByte cw0, cw1; if(!IsCTX(stream->currentScheme)) { StreamMarkFatal(stream, DmtxErrorUnexpectedScheme); return; } if(valueList->length < 3) { StreamMarkFatal(stream, DmtxErrorIncompleteValueList); return; } /* Build codewords from computed value */ pairValue = (1600 * valueList->b[0]) + (40 * valueList->b[1]) + valueList->b[2] + 1; cw0 = pairValue / 256; cw1 = pairValue % 256; /* Append 2 codewords */ StreamOutputChainAppend(stream, cw0); CHKERR; StreamOutputChainAppend(stream, cw1); CHKERR; /* Update count for 3 encoded values */ stream->outputChainValueCount += 3; }
/** * this code is separated from EncodeNextChunkAscii() because it needs to be * called directly elsewhere */ static void AppendValueAscii(DmtxEncodeStream *stream, DmtxByte value) { CHKSCHEME(DmtxSchemeAscii); StreamOutputChainAppend(stream, value); CHKERR; stream->outputChainValueCount++; }
static void AppendValueBase256(DmtxEncodeStream *stream, DmtxByte value) { CHKSCHEME(DmtxSchemeBase256); StreamOutputChainAppend(stream, Randomize255State(value, stream->output->length + 1)); CHKERR; stream->outputChainValueCount++; UpdateBase256ChainHeader(stream, DmtxUndefined); CHKERR; }
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++; }
static void UpdateBase256ChainHeader(DmtxEncodeStream *stream, int perfectSizeIdx) { int headerIndex; int outputLength; int headerByteCount; int symbolDataWords; DmtxBoolean perfectFit; DmtxByte headerValue0; DmtxByte headerValue1; outputLength = stream->outputChainValueCount; headerIndex = stream->output->length - stream->outputChainWordCount; headerByteCount = stream->outputChainWordCount - stream->outputChainValueCount; perfectFit = (perfectSizeIdx == DmtxUndefined) ? DmtxFalse : DmtxTrue; /* * If requested perfect fit verify symbol capacity against final length */ if(perfectFit) { symbolDataWords = dmtxGetSymbolAttribute(DmtxSymAttribSymbolDataWords, perfectSizeIdx); if(symbolDataWords != stream->output->length - 1) { StreamMarkFatal(stream, DmtxErrorUnknown); return; } } /* * Adjust header to hold correct number of bytes, not worrying about the * values held there until below. Note: Header bytes are not considered * scheme "values" so we can insert or remove them without updating the * outputChainValueCount. */ if(headerByteCount == 0 && stream->outputChainWordCount == 0) { /* No output words written yet -- insert single header byte */ StreamOutputChainAppend(stream, 0); CHKERR; headerByteCount++; } else if(!perfectFit && headerByteCount == 1 && outputLength > 249) { /* Beyond 249 bytes requires a second header byte */ Base256OutputChainInsertFirst(stream); CHKERR; headerByteCount++; } else if(perfectFit && headerByteCount == 2) { /* Encoding to exact end of symbol only requires single byte */ Base256OutputChainRemoveFirst(stream); CHKERR; headerByteCount--; } /* * Encode header byte(s) with current length */ if(!perfectFit && headerByteCount == 1 && outputLength <= 249) { /* Normal condition for chain length < 250 bytes */ headerValue0 = Randomize255State(outputLength, headerIndex + 1); StreamOutputSet(stream, headerIndex, headerValue0); CHKERR; } else if(!perfectFit && headerByteCount == 2 && outputLength > 249) { /* Normal condition for chain length >= 250 bytes */ headerValue0 = Randomize255State(outputLength/250 + 249, headerIndex + 1); StreamOutputSet(stream, headerIndex, headerValue0); CHKERR; headerValue1 = Randomize255State(outputLength%250, headerIndex + 2); StreamOutputSet(stream, headerIndex + 1, headerValue1); CHKERR; } else if(perfectFit && headerByteCount == 1) { /* Special condition when Base 256 stays in effect to end of symbol */ headerValue0 = Randomize255State(0, headerIndex + 1); /* XXX replace magic value 0? */ StreamOutputSet(stream, headerIndex, headerValue0); CHKERR; } else { StreamMarkFatal(stream, DmtxErrorUnknown); return; } }