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

Purpose

The csum linter ensures that the data has a valid numeric check digit.

Remarks
The process for validating the standard GS1 numeric check digit is described in the GS1 General Specifications section "Standard check digit calculations for GS1 data structures".

Functional Description

◆ gs1_lint_csum()

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

Use to ensure that the AI component has a valid numeric check digit.

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_INCORRECT_CHECK_DIGIT if the check digit is incorrect.
GS1_LINTER_TOO_SHORT_FOR_CHECK_DIGIT if the data is too short.
GS1_LINTER_NON_DIGIT_CHARACTER if the data contains a non-digit character.
57{
58
59 int weight;
60 int parity = 0;
61 const char *p;
62 size_t len;
63
64 assert(data);
65
66 len = strlen(data);
67
68 /*
69 * Data must include at least the check digit.
70 *
71 */
72 if (GS1_LINTER_UNLIKELY(*data == '\0'))
75 0,
76 0
77 );
78
79 /*
80 * Calculate the sum of the numeric values of the data, excluding the
81 * check digit, weighted by alternating ...3:1:3 values, from right to
82 * left.
83 *
84 * The check digit is valid if its value, when added to the data
85 * checksum, makes the overall sum a multiple of 10.
86 *
87 */
88 weight = len % 2 == 0 ? 3 : 1;
89 p = data;
90 while (*(p+1)) {
91
92 /*
93 * Data must consist of all digits.
94 *
95 */
96 if (GS1_LINTER_UNLIKELY(*p < '0' || *p > '9'))
99 (size_t)(p - data),
100 1
101 );
102
103 parity += weight * (*p++ - '0');
104 weight = 4 - weight;
105 }
106
107 /*
108 * Check character must also be a digit.
109 *
110 */
111 if (GS1_LINTER_UNLIKELY(*p < '0' || *p > '9'))
114 len - 1,
115 1
116 );
117 parity = (10 - parity % 10) % 10;
118
119 if (GS1_LINTER_UNLIKELY(parity + '0' != *p))
122 len - 1,
123 1
124 );
125
127
128}
#define GS1_LINTER_UNLIKELY(x)
Implemention 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_TOO_SHORT_FOR_CHECK_DIGIT
The component is too short to perform a numeric check digit calculation.
Definition gs1syntaxdictionary.h:83
@ GS1_LINTER_INCORRECT_CHECK_DIGIT
The numeric check digit is incorrect.
Definition gs1syntaxdictionary.h:82
@ GS1_LINTER_NON_DIGIT_CHARACTER
A non-digit character was found where a digit is expected.
Definition gs1syntaxdictionary.h:78