libdmtx 0.7.8.7
libdmtx is a software library that enables programs to read and write Data Matrix barcodes of the modern ECC200 variety.
Loading...
Searching...
No Matches
dmtxencodeascii.c
Go to the documentation of this file.
1
17#include <assert.h>
18
19#include "dmtx.h"
20#include "dmtxstatic.h"
21
35static void encodeNextChunkAscii(DmtxEncodeStream *stream, int option)
36{
37 DmtxByte v0, v1;
38 DmtxBoolean compactDigits;
39
40 if (streamInputHasNext(stream)) {
41 v0 = streamInputAdvanceNext(stream);
42 CHKERR;
43
44 if ((option == DmtxEncodeCompact || option == DmtxEncodeNormal) && streamInputHasNext(stream)) {
45 v1 = streamInputPeekNext(stream);
46 CHKERR;
47
48 /* Check for FNC1 character */
49 if (stream->fnc1 != DmtxUndefined && (int)v1 == stream->fnc1) {
50 v1 = 0;
51 compactDigits = DmtxFalse;
52 } else {
53 compactDigits = (ISDIGIT(v0) && ISDIGIT(v1)) ? DmtxTrue : DmtxFalse;
54 }
55 } else /* option == DmtxEncodeFull */
56 {
57 v1 = 0;
58 compactDigits = DmtxFalse;
59 }
60
61 if (compactDigits == DmtxTrue) {
62 /* Two adjacent digit chars: Make peek progress official and encode */
64 CHKERR;
65 appendValueAscii(stream, 10 * (v0 - '0') + (v1 - '0') + 130);
66 CHKERR;
67 } else if (option == DmtxEncodeCompact) {
68 /* Can't compact non-digits */
70 } else {
71 /* Encode single ASCII value */
72 if (stream->fnc1 != DmtxUndefined && (int)v0 == stream->fnc1) {
73 /* FNC1 */
75 CHKERR;
76 } else if (v0 < 128) {
77 /* Regular ASCII */
78 appendValueAscii(stream, v0 + 1);
79 CHKERR;
80 } else {
81 /* Extended ASCII */
83 CHKERR;
84 appendValueAscii(stream, v0 - 127);
85 CHKERR;
86 }
87 }
88 }
89}
90
95static void appendValueAscii(DmtxEncodeStream *stream, DmtxByte value)
96{
98
99 streamOutputChainAppend(stream, value);
100 CHKERR;
101 stream->outputChainValueCount++;
102}
103
108static void completeIfDoneAscii(DmtxEncodeStream *stream, int sizeIdxRequest)
109{
110 int sizeIdx;
111
112 if (stream->status == DmtxStatusComplete) {
113 return;
114 }
115
116 if (!streamInputHasNext(stream)) {
117 sizeIdx = findSymbolSize(stream->output->length, sizeIdxRequest);
118 CHKSIZE;
119 padRemainingInAscii(stream, sizeIdx);
120 CHKERR;
121 streamMarkComplete(stream, sizeIdx);
122 }
123}
124
129static void padRemainingInAscii(DmtxEncodeStream *stream, int sizeIdx)
130{
131 int symbolRemaining;
132 DmtxByte padValue;
133
135 CHKSIZE;
136
137 symbolRemaining = getRemainingSymbolCapacity(stream->output->length, sizeIdx);
138
139 /* First pad character is not randomized */
140 if (symbolRemaining > 0) {
141 padValue = DmtxValueAsciiPad;
142 streamOutputChainAppend(stream, padValue);
143 CHKERR;
144 symbolRemaining--;
145 }
146
147 /* All remaining pad characters are randomized based on character position */
148 while (symbolRemaining > 0) {
149 padValue = randomize253State(DmtxValueAsciiPad, stream->output->length + 1);
150 streamOutputChainAppend(stream, padValue);
151 CHKERR;
152 symbolRemaining--;
153 }
154}
155
160 DmtxPassFail *passFail)
161{
162 DmtxEncodeStream streamAscii;
163 DmtxByteList output = dmtxByteListBuild(storage, capacity);
164
165 /* Create temporary copy of stream that writes to storage */
166 streamAscii = *stream;
167 streamAscii.currentScheme = DmtxSchemeAscii;
168 streamAscii.outputChainValueCount = 0;
169 streamAscii.outputChainWordCount = 0;
170 streamAscii.reason = NULL;
171 streamAscii.sizeIdx = DmtxUndefined;
172 streamAscii.status = DmtxStatusEncoding;
173 streamAscii.output = &output;
174
175 while (dmtxByteListHasCapacity(streamAscii.output)) {
176 if (streamInputHasNext(&streamAscii)) {
177 encodeNextChunkAscii(&streamAscii, DmtxEncodeNormal); /* No CHKERR */
178 } else {
179 break;
180 }
181 }
182
183 /*
184 * We stopped encoding before attempting to write beyond output boundary so
185 * any stream errors are truly unexpected. The passFail status indicates
186 * whether output.length can be trusted by the calling function.
187 */
188
189 if (streamAscii.status == DmtxStatusInvalid || streamAscii.status == DmtxStatusFatal) {
190 *passFail = DmtxFail;
191 } else {
192 *passFail = DmtxPass;
193 }
194
195 return output;
196}
197
204static DmtxByte randomize253State(DmtxByte cwValue, int cwPosition)
205{
206 int pseudoRandom, tmp;
207
208 pseudoRandom = ((149 * cwPosition) % 253) + 1;
209 tmp = cwValue + pseudoRandom;
210 if (tmp > 254) {
211 tmp -= 254;
212 }
213
214 DmtxAssert(tmp >= 0 && tmp < 256);
215
216 return (DmtxByte)tmp;
217}
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
#define DmtxPassFail
Definition dmtx.h:42
DmtxBoolean dmtxByteListHasCapacity(DmtxByteList *list)
#define DmtxTrue
Definition dmtx.h:47
DmtxByteList dmtxByteListBuild(DmtxByte *storage, int capacity)
#define DmtxBoolean
Definition dmtx.h:46
#define DmtxPass
Definition dmtx.h:43
#define DmtxUndefined
Definition dmtx.h:40
@ DmtxSchemeAscii
Definition dmtx.h:90
#define DmtxFalse
Definition dmtx.h:48
unsigned char DmtxByte
Definition dmtx.h:293
#define DmtxFail
Definition dmtx.h:44
@ DmtxStatusComplete
Definition dmtx.h:81
@ DmtxStatusEncoding
Definition dmtx.h:80
@ DmtxStatusInvalid
Definition dmtx.h:82
@ DmtxStatusFatal
Definition dmtx.h:83
static void completeIfDoneAscii(DmtxEncodeStream *stream, int sizeIdxRequest)
static DmtxByte randomize253State(DmtxByte cwValue, int cwPosition)
Randomize 253 state.
static void padRemainingInAscii(DmtxEncodeStream *stream, int sizeIdx)
Can we just receive a length to pad here? I don't like receiving sizeIdxRequest (or sizeIdx) this lat...
static void encodeNextChunkAscii(DmtxEncodeStream *stream, int option)
Simple single scheme encoding uses "Normal" The optimizer needs to track "Expanded" and "Compact" str...
static DmtxByteList encodeTmpRemainingInAscii(DmtxEncodeStream *stream, DmtxByte *storage, int capacity, DmtxPassFail *passFail)
consider receiving instantiated DmtxByteList instead of the output components
static void appendValueAscii(DmtxEncodeStream *stream, DmtxByte value)
this code is separated from encodeNextChunkAscii() because it needs to be called directly elsewhere
libdmtx - Data Matrix Encoding/Decoding Library Copyright 2008, 2009 Mike Laughton.
static DmtxByte streamInputAdvanceNext(DmtxEncodeStream *stream)
#define CHKSIZE
Definition dmtxstatic.h:88
#define CHKSCHEME(s)
Definition dmtxstatic.h:71
static void streamOutputChainAppend(DmtxEncodeStream *stream, DmtxByte value)
@ DmtxEncodeNormal
Definition dmtxstatic.h:107
@ DmtxEncodeCompact
Definition dmtxstatic.h:108
#define DmtxValueAsciiPad
Definition dmtxstatic.h:37
@ DmtxErrorCantCompactNonDigits
Definition dmtxstatic.h:401
static void streamMarkInvalid(DmtxEncodeStream *stream, int reasonIdx)
#define ISDIGIT(n)
Definition dmtxstatic.h:68
#define DmtxAssert(expr)
Definition dmtxstatic.h:96
static DmtxByte streamInputPeekNext(DmtxEncodeStream *stream)
static int findSymbolSize(int dataWords, int sizeIdxRequest)
static void streamMarkComplete(DmtxEncodeStream *stream, int sizeIdx)
static int getRemainingSymbolCapacity(int outputLength, int sizeIdx)
#define DmtxValueFNC1
Definition dmtxstatic.h:42
#define DmtxValueAsciiUpperShift
Definition dmtxstatic.h:38
#define CHKERR
Definition dmtxstatic.h:80
static DmtxBoolean streamInputHasNext(DmtxEncodeStream *stream)
DmtxByteList Use signed int for length fields instead of size_t to play nicely with RS arithmetic.
DmtxByteList * output
Definition dmtx.h:319
DmtxStatus status
Definition dmtx.h:317