1 /**
2 * libdmtx - Data Matrix Encoding/Decoding Library
3 * Copyright 2011 Mike Laughton. All rights reserved.
4 * Copyright 2012-2016 Vadim A. Misbakh-Soloviov. All rights reserved.
5 *
6 * See LICENSE file in the main project directory for full
7 * terms of use and distribution.
8 *
9 * Contact:
10 * Vadim A. Misbakh-Soloviov <dmtx@mva.name>
11 * Mike Laughton <mike@dragonflylogic.com>
12 *
13 * \file dmtxencodestream.c
14 * \brief DmtxEncodeStream implementation
15 */
16
17 /**
18 *
19 *
20 */
21 static DmtxEncodeStream
StreamInit(DmtxByteList * input,DmtxByteList * output)22 StreamInit(DmtxByteList *input, DmtxByteList *output)
23 {
24 DmtxEncodeStream stream;
25
26 stream.input = input;
27 stream.output = output;
28
29 stream.currentScheme = DmtxSchemeAscii;
30 stream.inputNext = 0;
31 stream.outputChainValueCount = 0;
32 stream.outputChainWordCount = 0;
33 stream.reason = NULL;
34 stream.sizeIdx = DmtxUndefined;
35 stream.status = DmtxStatusEncoding;
36
37 return stream;
38 }
39
40 /**
41 *
42 *
43 */
44 static void
StreamCopy(DmtxEncodeStream * dst,DmtxEncodeStream * src)45 StreamCopy(DmtxEncodeStream *dst, DmtxEncodeStream *src)
46 {
47 DmtxPassFail passFail;
48
49 dst->currentScheme = src->currentScheme;
50 dst->inputNext = src->inputNext;
51 dst->outputChainValueCount = src->outputChainValueCount;
52 dst->outputChainWordCount = src->outputChainWordCount;
53 dst->reason = src->reason;
54 dst->sizeIdx = src->sizeIdx;
55 dst->status = src->status;
56 dst->input = src->input;
57 dst->fnc1 = src->fnc1;
58
59 dmtxByteListCopy(dst->output, src->output, &passFail);
60 }
61
62 /**
63 *
64 *
65 */
66 static void
StreamMarkComplete(DmtxEncodeStream * stream,int sizeIdx)67 StreamMarkComplete(DmtxEncodeStream *stream, int sizeIdx)
68 {
69 if(stream->status == DmtxStatusEncoding)
70 {
71 stream->sizeIdx = sizeIdx;
72 stream->status = DmtxStatusComplete;
73 assert(stream->reason == NULL);
74 }
75 }
76
77 /**
78 *
79 *
80 */
81 static void
StreamMarkInvalid(DmtxEncodeStream * stream,int reasonIdx)82 StreamMarkInvalid(DmtxEncodeStream *stream, int reasonIdx)
83 {
84 stream->status = DmtxStatusInvalid;
85 stream->reason = dmtxErrorMessage[reasonIdx];
86 }
87
88 /**
89 *
90 *
91 */
92 static void
StreamMarkFatal(DmtxEncodeStream * stream,int reasonIdx)93 StreamMarkFatal(DmtxEncodeStream *stream, int reasonIdx)
94 {
95 stream->status = DmtxStatusFatal;
96 stream->reason = dmtxErrorMessage[reasonIdx];
97 }
98
99 /**
100 * push on newest/last append
101 * used for encoding each output cw
102 */
103 static void
StreamOutputChainAppend(DmtxEncodeStream * stream,DmtxByte value)104 StreamOutputChainAppend(DmtxEncodeStream *stream, DmtxByte value)
105 {
106 DmtxPassFail passFail;
107
108 dmtxByteListPush(stream->output, value, &passFail);
109
110 if(passFail == DmtxPass)
111 stream->outputChainWordCount++;
112 else
113 StreamMarkFatal(stream, DmtxErrorOutOfBounds);
114 }
115
116 /**
117 * pop off newest/last
118 * used for edifact
119 */
120 static DmtxByte
StreamOutputChainRemoveLast(DmtxEncodeStream * stream)121 StreamOutputChainRemoveLast(DmtxEncodeStream *stream)
122 {
123 DmtxByte value;
124 DmtxPassFail passFail;
125
126 if(stream->outputChainWordCount > 0)
127 {
128 value = dmtxByteListPop(stream->output, &passFail);
129 stream->outputChainWordCount--;
130 }
131 else
132 {
133 value = 0;
134 StreamMarkFatal(stream, DmtxErrorEmptyList);
135 }
136
137 return value;
138 }
139
140 /**
141 * overwrite arbitrary element
142 * used for binary length changes
143 */
144 static void
StreamOutputSet(DmtxEncodeStream * stream,int index,DmtxByte value)145 StreamOutputSet(DmtxEncodeStream *stream, int index, DmtxByte value)
146 {
147 if(index < 0 || index >= stream->output->length)
148 StreamMarkFatal(stream, DmtxErrorOutOfBounds);
149 else
150 stream->output->b[index] = value;
151 }
152
153 /**
154 *
155 *
156 */
157 static DmtxBoolean
StreamInputHasNext(DmtxEncodeStream * stream)158 StreamInputHasNext(DmtxEncodeStream *stream)
159 {
160 return (stream->inputNext < stream->input->length) ? DmtxTrue : DmtxFalse;
161 }
162
163 /**
164 * peek at first/oldest
165 * used for ascii double digit
166 */
167 static DmtxByte
StreamInputPeekNext(DmtxEncodeStream * stream)168 StreamInputPeekNext(DmtxEncodeStream *stream)
169 {
170 DmtxByte value = 0;
171
172 if(StreamInputHasNext(stream))
173 value = stream->input->b[stream->inputNext];
174 else
175 StreamMarkFatal(stream, DmtxErrorOutOfBounds);
176
177 return value;
178 }
179
180 /**
181 * used as each input cw is processed
182 *
183 * \param value Value to populate, can be null (for blind dequeues)
184 * \param stream
185 */
186 static DmtxByte
StreamInputAdvanceNext(DmtxEncodeStream * stream)187 StreamInputAdvanceNext(DmtxEncodeStream *stream)
188 {
189 DmtxByte value;
190
191 value = StreamInputPeekNext(stream);
192
193 if(stream->status == DmtxStatusEncoding)
194 stream->inputNext++; /* XXX is this what we really mean here? */
195
196 return value;
197 }
198
199 /**
200 * used as each input cw is processed
201 *
202 * \param value Value to populate, can be null (for blind dequeues)
203 * \param stream
204 */
205 static void
StreamInputAdvancePrev(DmtxEncodeStream * stream)206 StreamInputAdvancePrev(DmtxEncodeStream *stream)
207 {
208 if(stream->inputNext > 0)
209 stream->inputNext--;
210 else
211 StreamMarkFatal(stream, DmtxErrorOutOfBounds);
212 }
213