GS1 Barcode Syntax Tests reference
A reference to the AI component "linter" routines referred to by the GS1 Barcode Syntax Dictionary. Copyright (c) 2022-2024 GS1 AISBL.
lint_posinseqslash.c File Reference

Purpose

The posinseqslash linter ensures that the data represents a meaningful position in a sequence in the format "`<pos>/<end>`".

Functional Description

◆ gs1_lint_posinseqslash()

GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_posinseqslash ( const char *const  data,
size_t  data_len,
size_t *const  err_pos,
size_t *const  err_len 
)

Used to ensure that an AI component conforms to a "`<pos>/<end>`" format for variable width <pos> and <end>.

Parameters
[in]dataPointer to the data to be linted. Must not be NULL.
[in]data_lenLength of the data to be linted.
[out]err_posTo facilitate error highlighting, the start position of the bad data is written to this pointer, if not NULL.
[out]err_lenThe length of the bad data is written to this pointer, if not NULL.
Returns
GS1_LINTER_OK if okay.
GS1_LINTER_POSITION_IN_SEQUENCE_MALFORMED if the data does not conform to "`<pos>/<end>`" format.
GS1_LINTER_ILLEGAL_ZERO_PREFIX if either the position number or the end number are zero or contain a zero prefix.
GS1_LINTER_POSITION_EXCEEDS_END if the data contains a position number that is larger than the end position.
53{
54
55/// \cond
56#define P(i) data[i]
57#define E(i) data[i + pos + 1]
58/// \endcond
59
60 size_t pos, slash_pos;
61
62 assert(data);
63
64 /*
65 * First non-digit should be '/'
66 *
67 */
68 for (pos = 0; pos < data_len && data[pos] >= '0' && data[pos] <= '9'; pos++);
69
70 /*
71 * Format so far must be digits + '/'
72 *
73 */
74 if (GS1_LINTER_UNLIKELY(pos == 0 || pos >= data_len || data[pos] != '/')) {
77 0,
78 data_len
79 );
80 }
81
82 slash_pos = pos;
83
84 /*
85 * Validate that remaining characters are digits and measure length
86 *
87 */
88 for (pos++; pos < data_len; pos++)
89 if (GS1_LINTER_UNLIKELY(data[pos] < '0' || data[pos] > '9')) {
92 0,
93 data_len
94 );
95 }
96
97 /*
98 * Must have digits after slash
99 */
100 if (GS1_LINTER_UNLIKELY(slash_pos >= data_len - 1))
103 0,
104 data_len
105 );
106
107 pos = slash_pos;
108
109 /*
110 * Ensure position number is non-zero and does not have zero prefix.
111 *
112 */
113 if (GS1_LINTER_UNLIKELY(P(0) == '0'))
116 0,
117 pos
118 );
119
120 /*
121 * Ensure end number is non-zero and does not have zero prefix.
122 *
123 */
124 if (GS1_LINTER_UNLIKELY(E(0) == '0'))
127 pos + 1,
128 data_len - pos - 1
129 );
130
131 /*
132 * Determine whether the position exceeds the end.
133 *
134 */
135 if (pos == data_len - pos - 1) {
136 size_t i;
137 int compare = 0; /* -1:P<E ; 0:P==E ; 1:P>E */
138 for (i = 0; i < pos && !compare; i++)
139 if (P(i) != E(i))
140 compare = P(i) < E(i) ? -1 : 1;
141 if (GS1_LINTER_UNLIKELY(compare == 1))
144 0,
145 data_len
146 );
147 } else if (GS1_LINTER_UNLIKELY(pos > data_len - pos - 1))
148 /* Non-zero prefix, so a length check is sufficient. */
151 0,
152 data_len
153 );
154
156
157}
#define GS1_LINTER_UNLIKELY(x)
Implementation may provide hint to the compiler that the expression is likely to be false.
Definition gs1syntaxdictionary-utils.h:76
#define GS1_LINTER_RETURN_ERROR(error, position, length)
Return from a linter indicating that a problem was detected with the given data.
Definition gs1syntaxdictionary-utils.h:103
#define GS1_LINTER_RETURN_OK
Return from a linter indicating that no problem was detected with the given data.
Definition gs1syntaxdictionary-utils.h:88
@ GS1_LINTER_ILLEGAL_ZERO_PREFIX
A zero prefix is not permitted.
Definition gs1syntaxdictionary.h:94
@ GS1_LINTER_POSITION_IN_SEQUENCE_MALFORMED
The data must have the format "<pos>/<end>".
Definition gs1syntaxdictionary.h:189
@ GS1_LINTER_POSITION_EXCEEDS_END
The position number must not exceed the end number.
Definition gs1syntaxdictionary.h:190