Skip to content

Commit 9e5af96

Browse files
committed
Align with Syntax Dictionary release 2025-01-30
1 parent 0bd7b04 commit 9e5af96

10 files changed

+228
-26
lines changed

src/c-lib/gs1-syntax-dictionary.txt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# GS1 Barcode Syntax Dictionary
22
# -----------------------------
33
#
4-
# Release: UNSET
4+
# Release: 2025-01-30
55
#
66
# This is the GS1 Barcode Syntax Dictionary.
77
#
@@ -100,7 +100,7 @@
100100
#
101101
# Copyright (c) 2020-2021 BWIPP project. https://bwipp.terryburton.co.uk/
102102
# Copyright (c) 2020-2021 Zint Project. https://zint.org.uk/
103-
# Copyright (c) 2021-2024 GS1 AISBL
103+
# Copyright (c) 2021-2025 GS1 AISBL
104104
#
105105
# Licensed under the Apache License, Version 2.0 (the "License");
106106
# you may not use this file except in compliance with the License.
@@ -118,10 +118,10 @@
118118

119119
# AI Flags Specification Attributes Title
120120

121-
00 *? N18,csum,key dlpkey # SSCC
122-
01 *? N14,csum,key ex=255,37 dlpkey=22,10,21|235 # GTIN
123-
02 *? N14,csum,key ex=01,03 req=37 # CONTENT
124-
03 * N14,csum,key ex=01,02,37 # MTO GTIN
121+
00 *? N18,csum,keyoff1 dlpkey # SSCC
122+
01 *? N14,csum,keyoff1 ex=255,37 dlpkey=22,10,21|235 # GTIN
123+
02 *? N14,csum,keyoff1 ex=01,03 req=37 # CONTENT
124+
03 * N14,csum,keyoff1 ex=01,02,37 # MTO GTIN
125125
10 ? X..20 req=01,02,03,8006,8026 # BATCH/LOT
126126
11 *? N6,yymmd0 req=01,02,8006,8026 # PROD DATE
127127
12 *? N6,yymmd0 req=8020 # DUE DATE
@@ -301,16 +301,16 @@
301301
7240 ? X..20 req=01,8006 # PROTOCOL
302302
7241 ? N2,mediatype req=8017,8018 # AIDC MEDIA TYPE
303303
7242 ? X..25 req=8017,8018 # VCN
304-
7250 N8,yyyymmdd req=8018 ex=7251 # DOB
305-
7251 N8,yyyymmdd N4,hhmi req=8018 ex=7250 # DOB TIME
306-
7252 N1,iso5218 req=8018 # BIO SEX
307-
7253 X..40,pcenc req=8017,8018 ex=7256,7259 # FAMILY NAME
308-
7254 X..40,pcenc req=8017,8018 ex=7256,7259 # GIVEN NAME
309-
7255 X..10 req=8017,8018 ex=7256,7259 # SUFFIX
310-
7256 X..90,pcenc req=8017,8018 # FULL NAME
311-
7257 X..70,pcenc req=8018 # PERSON ADDR
312-
7258 X3,posinseqslash req=8018+7259 # BIRTH SEQUENCE
313-
7259 X..40,pcenc req=8018 ex=7256 # BABY
304+
7250 ? N8,yyyymmdd req=8018 ex=7251 # DOB
305+
7251 ? N8,yyyymmdd N4,hhmi req=8018 ex=7250 # DOB TIME
306+
7252 ? N1,iso5218 req=8018 # BIO SEX
307+
7253 ? X..40,pcenc req=8017,8018 ex=7256,7259 # FAMILY NAME
308+
7254 ? X..40,pcenc req=8017,8018 ex=7256,7259 # GIVEN NAME
309+
7255 ? X..10 req=8017,8018 ex=7256,7259 # SUFFIX
310+
7256 ? X..90,pcenc req=8017,8018 # FULL NAME
311+
7257 ? X..70,pcenc req=8018 # PERSON ADDR
312+
7258 ? X3,posinseqslash req=8018+7259 # BIRTH SEQUENCE
313+
7259 ? X..40,pcenc req=8018 ex=7256 # BABY
314314
8001 ? N4,nonzero N5,nonzero N3,nonzero N1,winding N1 req=01 # DIMENSIONS
315315
8002 ? X..20 # CMT No.
316316
8003 ? N1,zero N13,csum,key [X..16] dlpkey # GRAI

src/c-lib/gs1encoders-test.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@
195195
<ClCompile Include="syntax\lint_iso4217.c" />
196196
<ClCompile Include="syntax\lint_iso5218.c" />
197197
<ClCompile Include="syntax\lint_key.c" />
198+
<ClCompile Include="syntax\lint_keyoff1.c" />
198199
<ClCompile Include="syntax\lint_latitude.c" />
199200
<ClCompile Include="syntax\lint_longitude.c" />
200201
<ClCompile Include="syntax\lint_mediatype.c" />

src/c-lib/gs1encoders-test.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@
140140
<ClCompile Include="syntax\lint_key.c">
141141
<Filter>Source Files</Filter>
142142
</ClCompile>
143+
<ClCompile Include="syntax\lint_keyoff1.c">
144+
<Filter>Source Files</Filter>
145+
</ClCompile>
143146
<ClCompile Include="syntax\lint_latitude.c">
144147
<Filter>Source Files</Filter>
145148
</ClCompile>

src/c-lib/gs1encoders.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@
162162
<ClCompile Include="syntax\lint_iso4217.c" />
163163
<ClCompile Include="syntax\lint_iso5218.c" />
164164
<ClCompile Include="syntax\lint_key.c" />
165+
<ClCompile Include="syntax\lint_keyoff1.c" />
165166
<ClCompile Include="syntax\lint_latitude.c" />
166167
<ClCompile Include="syntax\lint_longitude.c" />
167168
<ClCompile Include="syntax\lint_mediatype.c" />

src/c-lib/gs1encoders.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@
9393
<ClCompile Include="syntax\lint_key.c">
9494
<Filter>Source Files</Filter>
9595
</ClCompile>
96+
<ClCompile Include="syntax\lint_keyoff1.c">
97+
<Filter>Source Files</Filter>
98+
</ClCompile>
9699
<ClCompile Include="syntax\lint_latitude.c">
97100
<Filter>Source Files</Filter>
98101
</ClCompile>

src/c-lib/syntax/gs1syntaxdictionary.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* GS1 Barcode Syntax Dictionary. Copyright (c) 2022-2024 GS1 AISBL.
2+
* GS1 Barcode Syntax Dictionary. Copyright (c) 2022-2025 GS1 AISBL.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -66,6 +66,7 @@ const struct name_function_s name_function_map[] = {
6666
ENT(iso4217),
6767
ENT(iso5218),
6868
ENT(key),
69+
ENT(keyoff1),
6970
ENT(latitude),
7071
ENT(longitude),
7172
ENT(mediatype),

src/c-lib/syntax/gs1syntaxdictionary.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* GS1 Barcode Syntax Dictionary. Copyright (c) 2022-2024 GS1 AISBL.
2+
* GS1 Barcode Syntax Dictionary. Copyright (c) 2022-2025 GS1 AISBL.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -243,6 +243,7 @@ GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_iso3166alpha2(const char *data
243243
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_iso4217(const char *data, size_t *err_pos, size_t *err_len);
244244
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_iso5218(const char *data, size_t *err_pos, size_t *err_len);
245245
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_key(const char *data, size_t *err_pos, size_t *err_len);
246+
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_keyoff1(const char *data, size_t *err_pos, size_t *err_len);
246247
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_latitude(const char *data, size_t *err_pos, size_t *err_len);
247248
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_longitude(const char *data, size_t *err_pos, size_t *err_len);
248249
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_mediatype(const char *data, size_t *err_pos, size_t *err_len);

src/c-lib/syntax/lint_key.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,20 @@
8282
* source is unavailable and this should result in the linting failing.
8383
* [IMPLEMENTATION SPECIFIC]
8484
*
85+
* @note When GCP lookup service is provided by the user, it will be called
86+
* with strings whose prefix may be one of (1) a regular GCP, (2) a UPC
87+
* Company Code normalised to a regular GCP (by prefixing "0"), or (3) a
88+
* GS1-8 Prefix normalised to a regular GCP by prefixing "00000".
8589
* @note The choice of whether or not to assign `offline = 1` in order to
86-
* return #GS1_LINTER_GCP_DATASOURCE_OFFLINE when a user-provided GCP lookup
87-
* service is unavailable is implementation specific. It depends on whether the
88-
* desired behaviour is to fail open (return #GS1_LINTER_OK) or to fail closed
89-
* (return #GS1_LINTER_GCP_DATASOURCE_OFFLINE). In the case that it is
90-
* desirable to fail open then in addition to assigning `offline = 0` it is
91-
* necessary to assign `valid = 1` to avoid returning
92-
* #GS1_LINTER_INVALID_GCP_PREFIX, which would be misleading in the event of
93-
* service outage.
90+
* return #GS1_LINTER_GCP_DATASOURCE_OFFLINE when a user-provided GCP
91+
* lookup service is unavailable is implementation specific. It depends
92+
* on whether the desired behaviour is to fail open (return
93+
* #GS1_LINTER_OK) or to fail closed (return
94+
* #GS1_LINTER_GCP_DATASOURCE_OFFLINE). In the case that it is desirable
95+
* to fail open then in addition to assigning `offline = 0` it is
96+
* necessary to assign `valid = 1` to avoid returning
97+
* #GS1_LINTER_INVALID_GCP_PREFIX, which would be misleading in the event
98+
* of service outage.
9499
*
95100
*/
96101
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_key(const char* const data, size_t* const err_pos, size_t* const err_len)

src/c-lib/syntax/lint_keyoff1.c

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* GS1 Barcode Syntax Dictionary. Copyright (c) 2022-2025 GS1 AISBL
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
*
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
/**
20+
* @file lint_keyoff1.c
21+
*
22+
* @brief The `keyoff` linter checks whether an input starts with a GS1 Company
23+
* Prefix ("GCP") from its second character position.
24+
*
25+
* @remark The GCP is defined in the [GS1 General
26+
* Specifications](https://www.gs1.org/genspecs) section "GS1 Company Prefix".
27+
*
28+
*/
29+
30+
#include <assert.h>
31+
#include <string.h>
32+
33+
#include "gs1syntaxdictionary.h"
34+
#include "gs1syntaxdictionary-utils.h"
35+
36+
37+
/**
38+
* Used to ensure that an AI component starts with a GCP from its second
39+
* position.
40+
*
41+
* @param [in] data Pointer to the null-terminated data to be linted. Must not
42+
* be `NULL`.
43+
* @param [out] err_pos To facilitate error highlighting, the start position of
44+
* the bad data is written to this pointer, if not `NULL`.
45+
* @param [out] err_len The length of the bad data is written to this pointer, if
46+
* not `NULL`.
47+
*
48+
* @return #GS1_LINTER_OK if okay.
49+
* @return #GS1_LINTER_INVALID_GCP_PREFIX if the data does not start with a GCP.
50+
* @return #GS1_LINTER_TOO_SHORT_FOR_KEY if the data is too short to start
51+
* with a GCP.
52+
* @return #GS1_LINTER_GCP_DATASOURCE_OFFLINE if the user-provided GCP lookup
53+
* source is unavailable and this should result in the linting failing.
54+
* [IMPLEMENTATION SPECIFIC]
55+
*
56+
*/
57+
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_keyoff1(const char* const data, size_t* const err_pos, size_t* const err_len)
58+
{
59+
60+
size_t len;
61+
gs1_lint_err_t ret;
62+
63+
assert(data);
64+
65+
len = strlen(data);
66+
67+
if (len < 2)
68+
GS1_LINTER_RETURN_ERROR(
69+
GS1_LINTER_TOO_SHORT_FOR_KEY,
70+
0,
71+
len
72+
);
73+
74+
ret = gs1_lint_key(data + 1, err_pos, err_len);
75+
76+
assert(ret == GS1_LINTER_OK ||
77+
ret == GS1_LINTER_TOO_SHORT_FOR_KEY ||
78+
ret == GS1_LINTER_INVALID_GCP_PREFIX ||
79+
ret == GS1_LINTER_GCP_DATASOURCE_OFFLINE);
80+
81+
if (ret != GS1_LINTER_OK)
82+
GS1_LINTER_RETURN_ERROR(
83+
ret,
84+
*err_pos + 1,
85+
*err_len
86+
);
87+
88+
GS1_LINTER_RETURN_OK;
89+
90+
}
91+
92+
93+
#ifdef UNIT_TESTS
94+
95+
#include "unittest.h"
96+
97+
#ifndef GCP_MIN_LENGTH
98+
#define GCP_MIN_LENGTH 4 // Keep aligned with instance in lint_key.c
99+
#endif
100+
101+
void test_lint_keyoff1(void)
102+
{
103+
104+
char data[GCP_MIN_LENGTH + 3], expect[GCP_MIN_LENGTH + 5];
105+
int i;
106+
107+
/*
108+
* |----- Indicates end of minimum-length GCP
109+
* v
110+
* I0...45|6 => Good
111+
* I0...45| => Good
112+
*/
113+
data[0] = 'I';
114+
for (i = 1; i < GCP_MIN_LENGTH + 2; i++)
115+
data[i] = (char)('0' + (i-1)%10);
116+
data[i--] = '\0';
117+
UNIT_TEST_PASS(gs1_lint_keyoff1, data); // One more than minimum length
118+
data[i--] = '\0';
119+
UNIT_TEST_PASS(gs1_lint_keyoff1, data); // Minimum length
120+
121+
/*
122+
* |----- Indicates end of minimum-length GCP
123+
* v
124+
* I01234 | => Short; I*01234*
125+
* I0123 | => Short; I*0123*
126+
* I012 | => Short; I*012*
127+
* I01 | => Short; I*01*
128+
* I0 | => Short; I*0*
129+
*/
130+
while (i >= 2) {
131+
data[i--] = '\0';
132+
strcpy(expect, "I*");
133+
strcat(expect, data+1);
134+
strcat(expect, "*");
135+
UNIT_TEST_FAIL(gs1_lint_keyoff1, data, GS1_LINTER_TOO_SHORT_FOR_KEY, expect);
136+
}
137+
138+
/*
139+
* |----- Indicates end of minimum-length GCP
140+
* v
141+
* I | => Short; *I*
142+
* "" | => Short; **
143+
*/
144+
while (i >= 0) {
145+
data[i--] = '\0';
146+
strcpy(expect, "*");
147+
strcat(expect, data);
148+
strcat(expect, "*");
149+
UNIT_TEST_FAIL(gs1_lint_keyoff1, data, GS1_LINTER_TOO_SHORT_FOR_KEY, expect);
150+
}
151+
152+
/*
153+
* I012345|A => Good
154+
*/
155+
data[0] = 'I';
156+
for (i = 1; i < GCP_MIN_LENGTH + 1; i++)
157+
data[i] = (char)('0' + (i-1)%10);
158+
data[i++] = 'A';
159+
data[i] = '\0';
160+
UNIT_TEST_PASS(gs1_lint_keyoff1, data); // Minimum-length GCP is all numeric
161+
162+
/*
163+
* |----- Indicates end of minimum-length GCP
164+
* v
165+
* I01234A|A => Bad; I01234*A*A
166+
* I0123AA|A => Bad; I0123*A*AA
167+
* I012AAA|A => Bad; I012*A*AAA
168+
* I01AAAA|A => Bad; I01*A*AAAA
169+
* I0AAAAA|A => Bad; I0*A*AAAAA
170+
* IAAAAAA|A => Bad; I*A*AAAAAA
171+
*/
172+
strcpy(expect, data);
173+
expect[i+2] = '\0';
174+
i -= 2;
175+
while (i >= 1) {
176+
data[i] = 'A';
177+
memcpy(&expect[i--], "*A*A", 4);
178+
UNIT_TEST_FAIL(gs1_lint_keyoff1, data, GS1_LINTER_INVALID_GCP_PREFIX, expect);
179+
}
180+
181+
}
182+
183+
#endif /* UNIT_TESTS */

src/ios/GS1 Encoders App.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
F79827902909D35500F00DDA /* syn.c in Sources */ = {isa = PBXBuildFile; fileRef = F798275B2909D35400F00DDA /* syn.c */; };
5656
F79827912909D35500F00DDA /* gs1-syntax-dictionary.txt in Resources */ = {isa = PBXBuildFile; fileRef = F798275C2909D35400F00DDA /* gs1-syntax-dictionary.txt */; };
5757
F79827DD2909E3AE00F00DDA /* GS1Encoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F79827DC2909E3AE00F00DDA /* GS1Encoder.swift */; };
58+
F7A4673F2D4C7B5400A72510 /* lint_keyoff1.c in Sources */ = {isa = PBXBuildFile; fileRef = F7A4673E2D4C7B5400A72510 /* lint_keyoff1.c */; };
5859
F7A662AC2A50A95200638051 /* lint_longitude.c in Sources */ = {isa = PBXBuildFile; fileRef = F7A662A92A50A95200638051 /* lint_longitude.c */; };
5960
F7A662AD2A50A95200638051 /* lint_latitude.c in Sources */ = {isa = PBXBuildFile; fileRef = F7A662AA2A50A95200638051 /* lint_latitude.c */; };
6061
F7A662AE2A50A95200638051 /* lint_cset64.c in Sources */ = {isa = PBXBuildFile; fileRef = F7A662AB2A50A95200638051 /* lint_cset64.c */; };
@@ -128,6 +129,7 @@
128129
F798275C2909D35400F00DDA /* gs1-syntax-dictionary.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "gs1-syntax-dictionary.txt"; sourceTree = "<group>"; };
129130
F79827DB2909DC2600F00DDA /* GS1 Encoders App-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "GS1 Encoders App-Bridging-Header.h"; sourceTree = "<group>"; };
130131
F79827DC2909E3AE00F00DDA /* GS1Encoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GS1Encoder.swift; sourceTree = "<group>"; };
132+
F7A4673E2D4C7B5400A72510 /* lint_keyoff1.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = lint_keyoff1.c; sourceTree = "<group>"; };
131133
F7A662A92A50A95200638051 /* lint_longitude.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lint_longitude.c; sourceTree = "<group>"; };
132134
F7A662AA2A50A95200638051 /* lint_latitude.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lint_latitude.c; sourceTree = "<group>"; };
133135
F7A662AB2A50A95200638051 /* lint_cset64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lint_cset64.c; sourceTree = "<group>"; };
@@ -237,6 +239,7 @@
237239
F79827392909D35400F00DDA /* syntax */ = {
238240
isa = PBXGroup;
239241
children = (
242+
F7A4673E2D4C7B5400A72510 /* lint_keyoff1.c */,
240243
F7CAA00A2CBC58E00066147A /* lint__stubs.c */,
241244
F754C8492CB6A7FA00ACC93D /* lint_hhmi.c */,
242245
F754C8472CB6A7EB00ACC93D /* lint_mi.c */,
@@ -441,6 +444,7 @@
441444
F79827812909D35500F00DDA /* lint_iso3166alpha2.c in Sources */,
442445
F79827612909D35500F00DDA /* ai.c in Sources */,
443446
F798278C2909D35500F00DDA /* lint_iso3166999.c in Sources */,
447+
F7A4673F2D4C7B5400A72510 /* lint_keyoff1.c in Sources */,
444448
F798278D2909D35500F00DDA /* gs1syntaxdictionary.c in Sources */,
445449
F798277F2909D35500F00DDA /* lint_cset82.c in Sources */,
446450
F798278E2909D35500F00DDA /* lint_yymmd0.c in Sources */,

0 commit comments

Comments
 (0)