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.
Macros
lint_yymmd0.c File Reference

Macros

#define CURRENT_YEAR   21
 20YY: For converting YY to 19YY, 20YY, 21YY, etc. for leap year validation
 

Purpose

The yymmd0 linter ensures that the data represents a meaningful date, in YYMMDD format, additionally permitting YYMM00 format indicating an unspecified day.

Functional Description

◆ gs1_lint_yymmd0()

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

Used to ensure that an AI component conforms to the YYMMDD or YYMM00 formats.

Parameters
[in]dataPointer to the null-terminated data to be linted. Must not be NULL.
[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_DATE_TOO_SHORT if the data is too short for YYMMDD format.
GS1_LINTER_DATE_TOO_LONG if the data is too long for YYMMDD format.
GS1_LINTER_NON_DIGIT_CHARACTER if the data contains a non-digit character.
GS1_LINTER_ILLEGAL_MONTH if the data contains an invalid month.
GS1_LINTER_ILLEGAL_DAY if the data contains an invalid day of the month.
62{
63
64/// \cond
65#define YY ( (data[0] - '0') * 10 + (data[1] - '0') )
66/// \endcond
67
68 size_t len, pos;
69 char yyyymmdd[9] = {0};
71
72 assert(data);
73
74 len = strlen(data);
75
76 /*
77 * Data must be six characters.
78 *
79 */
80 if (len != 6)
83 0,
84 len
85 );
86
87 /*
88 * Data must consist of all digits.
89 *
90 */
91 if ((pos = strspn(data, "0123456789")) != len)
94 pos,
95 1
96 );
97
98 memcpy(yyyymmdd + 2, data, 6);
99
100 /*
101 * Convert YY to a year using a horizon based on CURRENT_YEAR.
102 *
103 */
104 if (YY - CURRENT_YEAR >= 51) {
105 yyyymmdd[0] = '1'; yyyymmdd[1] = '9';
106 } else if (YY - CURRENT_YEAR > -50) {
107 yyyymmdd[0] = '2'; yyyymmdd[1] = '0';
108 } else {
109 yyyymmdd[0] = '2'; yyyymmdd[1] = '1';
110 }
111
112 ret = gs1_lint_yyyymmd0(yyyymmdd, err_pos, err_len);
113
114 assert(ret == GS1_LINTER_OK ||
117
118 assert(!err_pos || ret == GS1_LINTER_OK || (*err_pos >= 2));
119 assert(!err_pos || !err_len || ret == GS1_LINTER_OK || (*err_pos + *err_len <= len + 2));
120
121 if (ret != GS1_LINTER_OK)
123 ret,
124 *err_pos - 2,
125 *err_len
126 );
127
129
130}
#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:77
#define GS1_LINTER_RETURN_OK
Return from a linter indicating that no problem was detected with the given data.
Definition gs1syntaxdictionary-utils.h:62
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_yyyymmd0(const char *data, size_t *err_pos, size_t *err_len)
Definition lint_yyyymmd0.c:55
gs1_lint_err_t
Linter return codes other than GS1_LINTER_OK indicate an error condition.
Definition gs1syntaxdictionary.h:76
@ GS1_LINTER_ILLEGAL_DAY
The date contains an illegal day of the month.
Definition gs1syntaxdictionary.h:114
@ GS1_LINTER_DATE_TOO_LONG
The date is too long for YYMMDD format.
Definition gs1syntaxdictionary.h:106
@ GS1_LINTER_ILLEGAL_MONTH
The date contains an illegal month of the year.
Definition gs1syntaxdictionary.h:113
@ GS1_LINTER_DATE_TOO_SHORT
The date is too short for YYMMDD format.
Definition gs1syntaxdictionary.h:105
@ GS1_LINTER_OK
No issues were detected by the linter.
Definition gs1syntaxdictionary.h:77
@ GS1_LINTER_NON_DIGIT_CHARACTER
A non-digit character was found where a digit is expected.
Definition gs1syntaxdictionary.h:78
#define CURRENT_YEAR
20YY: For converting YY to 19YY, 20YY, 21YY, etc. for leap year validation
Definition lint_yymmd0.c:38