GS1 Syntax Dictionary: Linter reference
A reference to the AI component linter routines referred to by the GS1 Syntax Dictionary. Copyright (c) 2022-2024 GS1 AISBL.
lint_couponcode.c File Reference

Purpose

The couponcode linter ensures that the data conforms to the original North American Coupon Code (NACC) specification, as carried in AI (8110).

Remarks
Refer to the document "North American Coupon Application Guideline Using GS1 DataBar Expanded Symbols" for a description of the GS1 U.S. coupon code data content.

Functional Description

◆ gs1_lint_couponcode()

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

Used to ensure that an AI component conforms to the North American Coupon Code (NACC) specification, as carried in AI (8110).

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_COUPON_MISSING_GCP_VLI if the data is missing a primary GCP VLI.
GS1_LINTER_COUPON_INVALID_GCP_LENGTH if the data contains a primary GCP with an invalid length.
GS1_LINTER_COUPON_TRUNCATED_GCP if the data contains a primary GCP that is shorter than is indicated by its VLI.
GS1_LINTER_COUPON_MISSING_SAVE_VALUE_VLI if the data is missing a Save Value VLI.
GS1_LINTER_COUPON_INVALID_SAVE_VALUE_LENGTH if the data contains a Save Value VLI with an invalid length.
GS1_LINTER_COUPON_TRUNCATED_SAVE_VALUE if the data comtains a Save Value that is shorter than is indicated by its VLI.
GS1_LINTER_COUPON_MISSING_1ST_PURCHASE_REQUIREMENT_VLI if the data is missing a primary purchace Requirement VLI.
GS1_LINTER_COUPON_INVALID_1ST_PURCHASE_REQUIREMENT_LENGTH if the data contains a primary purchase Requirement VLI with an invalid length.
GS1_LINTER_COUPON_TRUNCATED_1ST_PURCHASE_REQUIREMENT if the data comtains a primary purchase Requirement that is shorter than is indicated by its VLI.
GS1_LINTER_COUPON_MISSING_1ST_PURCHASE_REQUIREMENT_CODE if the data is missing a primary purchase Requirement Code.
GS1_LINTER_COUPON_INVALID_1ST_PURCHASE_REQUIREMENT_CODE if the data contains a primary purchase Requirement Code that is too short.
GS1_LINTER_COUPON_TRUNCATED_1ST_PURCHASE_FAMILY_CODE if the data contains a primary purchase Family Code that is too short.
GS1_LINTER_COUPON_MISSING_ADDITIONAL_PURCHASE_RULES_CODE if the data contains an optional field 1 that is missing an Additional Purchase Rules Code.
GS1_LINTER_COUPON_INVALID_ADDITIONAL_PURCHASE_RULES_CODE if the data contains an optional field 1 whose Additional Purchase Rules Code is invalid.
GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_REQUIREMENT_VLI if the data contains an optional field 1 that is missing a second purchase Requirement VLI.
GS1_LINTER_COUPON_INVALID_2ND_PURCHASE_REQUIREMENT_LENGTH if the data contains an optional field 1 with a second purchase Requirement VLI with an invalid length.
GS1_LINTER_COUPON_TRUNCATED_2ND_PURCHASE_REQUIREMENT if the data contains an optional field 1 whose second purchase Requirement Code is shorter than is indicated by its VLI.
GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_REQUIREMENT_CODE if the data contains an optional field 1 that is missing a second purchase Requirement Code.
GS1_LINTER_COUPON_INVALID_2ND_PURCHASE_REQUIREMENT_CODE if the data contains an optional field 1 whose second purchase Requirement Code is invalid.
GS1_LINTER_COUPON_TRUNCATED_2ND_PURCHASE_FAMILY_CODE if the data contains an optional field 1 whose second purchase Family Code is too short.
GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_GCP_VLI if the data contains an optional field 1 that is missing a second purchase GCP VLI.
GS1_LINTER_COUPON_INVALID_2ND_PURCHASE_GCP_LENGTH if the data contains an optional field 1 with a second purchase GCP VLI with an invalid length.
GS1_LINTER_COUPON_TRUNCATED_2ND_PURCHASE_GCP if the data contains an optional field 1 with a second purchase GCP that is shorter than indicated by its VLI.
GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_REQUIREMENT_VLI if the data contains an optional field 2 that is missing a third purchase Requirement VLI.
GS1_LINTER_COUPON_INVALID_3RD_PURCHASE_REQUIREMENT_LENGTH if the data contains an optional field 2 with a third purchase Requirement VLI with an invalid length.
GS1_LINTER_COUPON_TRUNCATED_3RD_PURCHASE_REQUIREMENT if the data contains an optional field 2 whose third purchase Requirement Code is shorter than is indicated by its VLI.
GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_REQUIREMENT_CODE if the data contains an optional field 2 that is missing a third purchase Requirement Code.
GS1_LINTER_COUPON_INVALID_3RD_PURCHASE_REQUIREMENT_CODE if the data contains an optional field 2 whose third purchase Requirement Code is invalid.
GS1_LINTER_COUPON_TRUNCATED_3RD_PURCHASE_FAMILY_CODE if the data contains an optional field 2 whose third purchase Family Code is too short.
GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_GCP_VLI if the data contains an optional field 2 that is missing a third purchase GCP VLI.
GS1_LINTER_COUPON_INVALID_3RD_PURCHASE_GCP_LENGTH if the data contains an optional field 2 with a third purchase GCP VLI with an invalid length.
GS1_LINTER_COUPON_TRUNCATED_3RD_PURCHASE_GCP if the data contains an optional field 2 with a third purchase GCP that is shorter than indicated by its VLI.
GS1_LINTER_COUPON_TOO_SHORT_FOR_EXPIRATION_DATE if the data contains an optional field 3 whose expiration date is too short.
GS1_LINTER_COUPON_INVALID_EXIPIRATION_DATE if the data contains an optional field 3 whose expiration date is invalid.
GS1_LINTER_COUPON_TOO_SHORT_FOR_START_DATE if the data contains an optional field 4 whose start date is too short.
GS1_LINTER_COUPON_INVALID_START_DATE if the data contains an optional field 4 whose start date is invalid.
GS1_LINTER_COUPON_EXPIRATION_BEFORE_START if the data contains an optional field 3 and an optional field 4 where the expiration date is prior to the start date.
GS1_LINTER_COUPON_MISSING_SERIAL_NUMBER_VLI if the data contains an optional field 5 that is missing the Serial Number VLI.
GS1_LINTER_COUPON_TRUNCATED_SERIAL_NUMBER if the data contains an optional field 5 whose Serial Number is shorter than indicated by its VLI.
GS1_LINTER_COUPON_MISSING_RETAILER_GCP_OR_GLN_VLI f the data contains an optional field 6 that is missing the Retailer GCP/GLN VLI.
GS1_LINTER_COUPON_INVALID_RETAILER_GCP_OR_GLN_LENGTH if the data contains an optional field 6 with a Retailer GCP/GLN VLI with an invalid length.
GS1_LINTER_COUPON_TRUNCATED_RETAILER_GCP_OR_GLN if the data contains an optional field 6 whose Retailer GCP/GLN is shorter than indicated by its VLI.
GS1_LINTER_COUPON_MISSING_SAVE_VALUE_CODE if the data contains an optional field 9 that is missing the Save Value Code.
GS1_LINTER_COUPON_INVALID_SAVE_VALUE_CODE if the data contains an optional field 9 whose Save Value Code is invalid.
GS1_LINTER_COUPON_MISSING_SAVE_VALUE_APPLIES_TO_ITEM if the data contains an optional field 9 that is missing the Save Value Applies to Item value.
GS1_LINTER_COUPON_INVALID_SAVE_VALUE_APPLIES_TO_ITEM if the data contains an optional field 9 whose Save Value Applies to Item value is invalid.
GS1_LINTER_COUPON_MISSING_STORE_COUPON_FLAG if the data contains an optional field 9 that is missing the Store Coupon Flag.
GS1_LINTER_COUPON_MISSING_DONT_MULTIPLY_FLAG if the data contains an optional field 9 that is missing the Don't Multiply Flag.
GS1_LINTER_COUPON_INVALID_DONT_MULTIPLY_FLAG if the data contains an optional field 9 whose Don't Multiply Flag is invalid.
184{
185
186 gs1_lint_err_t ret;
187 size_t pos;
188 int vli;
189 const char *p, *q;
190 char expiry_date[7] = {0};
191 int expiry_set = 0;
192 char gcp[14] = {0};
193
194 assert(data);
195
196 /*
197 * Data must consist of all digits.
198 *
199 */
200 if ((pos = strspn(data, "0123456789")) != strlen(data)) {
201 if (err_pos) *err_pos = pos;
202 if (err_len) *err_len = 1;
204 }
205
206 p = data;
207 q = data + strlen(data);
208
209
210 /*
211 * Validate that the GCP follows its VLI and has the corresponding
212 * length (plus 6).
213 *
214 * Valid GCP VLIs are "0" to "6".
215 *
216 */
217 if (p == q) {
218 if (err_pos) *err_pos = 0;
219 if (err_len) *err_len = (size_t)(q - data);
221 }
222 if (*p > '6') {
223 if (err_pos) *err_pos = (size_t)(p - data);
224 if (err_len) *err_len = 1;
226 }
227 vli = *p - '0' + 6;
228
229 if (q - ++p < vli) {
230 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
231 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
233 }
234
235 /*
236 * Validate the GCP with the "key" linter.
237 *
238 */
239 strncpy(gcp, p, (size_t)vli);
240 ret = gs1_lint_key(gcp, err_pos, err_len);
241
242 assert (ret == GS1_LINTER_OK ||
245
246 if (ret != GS1_LINTER_OK) {
247 if (err_pos) *err_pos = (size_t)(p - data);
248 if (err_len) *err_len = (size_t)vli;
249 return ret;
250 }
251
252 p += vli;
253
254
255 /*
256 * Validate the existence of the six digit Offer Code.
257 *
258 */
259 if (q - p < 6) {
260 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
261 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
263 }
264
265 p += 6;
266
267
268 /*
269 * Validate that the Save Value follows its VLI and has the
270 * corresponding length.
271 *
272 * Valid Save Value VLIs are "1" to "5".
273 *
274 */
275 if (p == q) {
276 if (err_pos) *err_pos = 0;
277 if (err_len) *err_len = (size_t)(q - data);
279 }
280 if (*p < '1' || *p > '5') {
281 if (err_pos) *err_pos = (size_t)(p - data);
282 if (err_len) *err_len = 1;
284 }
285 vli = *p - '0';
286
287 if (q - ++p < vli) {
288 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
289 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
291 }
292
293 p += vli;
294
295
296 /*
297 * Validate 1st Purchase Requirement follows its VLI and has the
298 * corresponding length.
299 *
300 * Valid 1st Purchase Requirement VLIs are "1" to "5".
301 *
302 */
303 if (p == q) {
304 if (err_pos) *err_pos = 0;
305 if (err_len) *err_len = (size_t)(q - data);
307 }
308 if (*p < '1' || *p > '5') {
309 if (err_pos) *err_pos = (size_t)(p - data);
310 if (err_len) *err_len = 1;
312 }
313 vli = *p - '0';
314
315 if (q - ++p < vli) {
316 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
317 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
319 }
320
321 p += vli;
322
323
324 /*
325 * Validate the single-digit 1st Purchase Requirement Code.
326 *
327 * Valid values for 1st Purchase Requirement Code are "0" to "4" and
328 * "9".
329 *
330 */
331 if (p == q) {
332 if (err_pos) *err_pos = 0;
333 if (err_len) *err_len = (size_t)(q - data);
335 }
336
337 if (*p > '4' && *p != '9') {
338 if (err_pos) *err_pos = (size_t)(p - data);
339 if (err_len) *err_len = 1;
341 }
342
343
344 /*
345 * Validate the existence of the three-digit 1st Purchase Family Code.
346 *
347 */
348 if (q - ++p < 3) {
349 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
350 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
352 }
353
354 p += 3;
355
356
357 /*
358 * Optional field 1: Additional rules and 2nd purchase
359 * ===================================================
360 *
361 * This option field is indicated by the value "1".
362 *
363 */
364 if (p < q && *p == '1') {
365
366 /*
367 * Validate the single-digit Additional Purchase Rules Code.
368 *
369 * Valid values for the Additional Purchase Rules Code are "0"
370 * to "3".
371 *
372 */
373 if (++p == q) {
374 if (err_pos) *err_pos = 0;
375 if (err_len) *err_len = (size_t)(q - data);
377 }
378
379 if (*p > '3') {
380 if (err_pos) *err_pos = (size_t)(p - data);
381 if (err_len) *err_len = 1;
383 }
384
385
386 /*
387 * Validate 2nd Purchase Requirement follows its VLI and has
388 * the corresponding length.
389 *
390 * Valid values for the 2nd Purchase Requirement VLI are "1" to
391 * "5".
392 *
393 */
394 if (++p == q) {
395 if (err_pos) *err_pos = 0;
396 if (err_len) *err_len = (size_t)(q - data);
398 }
399 if (*p < '1' || *p > '5') {
400 if (err_pos) *err_pos = (size_t)(p - data);
401 if (err_len) *err_len = 1;
403 }
404 vli = *p - '0';
405
406 if (q - ++p < vli) {
407 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
408 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
410 }
411
412 p += vli;
413
414
415 /*
416 * Validate the single-digit 2nd Purchase Requirement Code.
417 *
418 * Valid values for the 2nd Purchase Requirement Code are "0"
419 * to "4" and "9".
420 *
421 */
422 if (p == q) {
423 if (err_pos) *err_pos = 0;
424 if (err_len) *err_len = (size_t)(q - data);
426 }
427
428 if (*p > '4' && *p != '9') {
429 if (err_pos) *err_pos = (size_t)(p - data);
430 if (err_len) *err_len = 1;
432 }
433
434
435 /*
436 * Validate the existence of the three-digit 2nd Purchase
437 * Family Code.
438 *
439 */
440 if (q - ++p < 3) {
441 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
442 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
444 }
445
446 p += 3;
447
448
449 /*
450 * Validate that the 2nd Purchase GCP follows its VLI and has
451 * the corresponding length (plus 6, unless VLI is "9").
452 *
453 * Valid values for the 2nd Purchase GCP VLI are "0" to "6" and
454 * "9".
455 *
456 */
457 if (p == q) {
458 if (err_pos) *err_pos = 0;
459 if (err_len) *err_len = (size_t)(q - data);
461 }
462 if (*p > '6' && *p != '9') {
463 if (err_pos) *err_pos = (size_t)(p - data);
464 if (err_len) *err_len = 1;
466 }
467 vli = (*p != '9') ? *p - '0' + 6 : 0;
468
469 if (q - ++p < vli) {
470 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
471 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
473 }
474
475 /*
476 * Validate the GCP with the "key" linter.
477 *
478 */
479 strncpy(gcp, p, (size_t)vli);
480 ret = gs1_lint_key(gcp, err_pos, err_len);
481
482 assert (ret == GS1_LINTER_OK ||
485
486 if (ret != GS1_LINTER_OK) {
487 if (err_pos) *err_pos = (size_t)(p - data);
488 if (err_len) *err_len = (size_t)vli;
489 return ret;
490 }
491
492 p += vli;
493
494 }
495
496
497 /*
498 * Optional field 2: 3rd purchase
499 * ==============================
500 *
501 * This option field is indicated by the value "2".
502 *
503 */
504 if (p < q && *p == '2') {
505
506 /*
507 * Validate 3rd Purchase Requirement follows its VLI and has
508 * the corresponding length.
509 *
510 * Valid values for the 3rd Purchase Requirement VLI are "1" to
511 * "5".
512 *
513 */
514 if (++p == q) {
515 if (err_pos) *err_pos = 0;
516 if (err_len) *err_len = (size_t)(q - data);
518 }
519 if (*p < '1' || *p > '5') {
520 if (err_pos) *err_pos = (size_t)(p - data);
521 if (err_len) *err_len = 1;
523 }
524 vli = *p - '0';
525
526 if (q - ++p < vli) {
527 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
528 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
530 }
531
532 p += vli;
533
534
535 /*
536 * Validate the single-digit 3nd Purchase Requirement Code.
537 *
538 * Valie values for the 3nd Purchase Requirement Code are "0"
539 * to "4" and "9".
540 *
541 */
542 if (p == q) {
543 if (err_pos) *err_pos = 0;
544 if (err_len) *err_len = (size_t)(q - data);
546 }
547
548 if (*p > '4' && *p != '9') {
549 if (err_pos) *err_pos = (size_t)(p - data);
550 if (err_len) *err_len = 1;
552 }
553
554
555 /*
556 * Validate that existence of the three digit 3rd Purchase
557 * Family Code.
558 *
559 */
560 if (q - ++p < 3) {
561 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
562 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
564 }
565
566 p += 3;
567
568
569 /*
570 * Validate that the 3rd Purchase GCP follows its VLI and has
571 * the corresponding length (plus 6, unless VLI is "9").
572 *
573 * Valid values for the 3rd Purchase GCP VLI are "0" to "6" and
574 * "9".
575 *
576 */
577 if (p == q) {
578 if (err_pos) *err_pos = 0;
579 if (err_len) *err_len = (size_t)(q - data);
581 }
582 if (*p > '6' && *p != '9') {
583 if (err_pos) *err_pos = (size_t)(p - data);
584 if (err_len) *err_len = 1;
586 }
587 vli = (*p != '9') ? *p - '0' + 6 : 0;
588
589 if (q - ++p < vli) {
590 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
591 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
593 }
594
595 /*
596 * Validate the GCP with the "key" linter.
597 *
598 */
599 strncpy(gcp, p, (size_t)vli);
600 ret = gs1_lint_key(gcp, err_pos, err_len);
601
602 assert (ret == GS1_LINTER_OK ||
605
606 if (ret != GS1_LINTER_OK) {
607 if (err_pos) *err_pos = (size_t)(p - data);
608 if (err_len) *err_len = (size_t)vli;
609 return ret;
610 }
611
612 p += vli;
613
614 }
615
616
617 /*
618 * Optional field 3: Expiration date
619 * =================================
620 *
621 * This option field is indicated by the value "3".
622 *
623 */
624 if (p < q && *p == '3') {
625
626 /*
627 * Validate that the expiration date is in YYMMDD format.
628 *
629 */
630 if (q - ++p < 6) {
631 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
632 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
634 }
635
636 memcpy(expiry_date, p, 6);
637 ret = gs1_lint_yymmdd(expiry_date, err_pos, err_len);
638
639 assert(ret == GS1_LINTER_OK ||
645
646 if (ret != GS1_LINTER_OK) {
647 if (err_pos) *err_pos = (size_t)(p - data);
648 if (err_len) *err_len = 6;
650 }
651
652 p += 6;
653
654 expiry_set = 1;
655
656 }
657
658
659 /*
660 * Optional field 4: Start date
661 * ============================
662 *
663 * This option field is indicated by the value "4".
664 *
665 */
666 if (p < q && *p == '4') {
667
668 char start_date[7] = {0};
669
670 /*
671 * Validate that the start date is in YYMMDD format.
672 *
673 */
674 if (q - ++p < 6) {
675 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
676 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
678 }
679
680 memcpy(start_date, p, 6);
681 ret = gs1_lint_yymmdd(start_date, err_pos, err_len);
682
683 assert(ret == GS1_LINTER_OK ||
689
690 if (ret != GS1_LINTER_OK) {
691 if (err_pos) *err_pos = (size_t)(p - data);
692 if (err_len) *err_len = 6;
694 }
695
696 /*
697 * If an expiration date has been set, then ensure that it does
698 * not preceed the start date.
699 *
700 */
701 if (expiry_set && strcmp(start_date, expiry_date) > 0) {
702 if (err_pos) *err_pos = (size_t)(p - data - 8);
703 if (err_len) *err_len = 14;
705 }
706
707 p += 6;
708
709 }
710
711
712 /*
713 * Optional field 5: Serial number
714 * ===============================
715 *
716 * This option field is indicated by the value "5".
717 *
718 */
719 if (p < q && *p == '5') {
720
721 /*
722 * Validate Serial Number follows its VLI and has the corresponding
723 * length (plus 6).
724 *
725 */
726 if (++p == q) {
727 if (err_pos) *err_pos = 0;
728 if (err_len) *err_len = (size_t)(q - data);
730 }
731 vli = *p - '0' + 6;
732
733 if (q - ++p < vli) {
734 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
735 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
737 }
738
739 p += vli;
740
741 }
742
743
744 /*
745 * Optional field 6: Retailer GCP/GLN
746 * ==================================
747 *
748 * This option field is indicated by the value "6".
749 *
750 */
751 if (p < q && *p == '6') {
752
753 /*
754 * Validate that the Retailer GCP/GLN follows its VLI and has
755 * the corresponding length (plus 6).
756 *
757 * Valid values for the Retailer GCP/GLN VLI are "1" to "7".
758 *
759 */
760 if (++p == q) {
761 if (err_pos) *err_pos = 0;
762 if (err_len) *err_len = (size_t)(q - data);
764 }
765 if (*p < '1' || *p > '7') {
766 if (err_pos) *err_pos = (size_t)(p - data);
767 if (err_len) *err_len = 1;
769 }
770 vli = *p - '0' + 6;
771
772 if (q - ++p < vli) {
773 if (err_pos) *err_pos = (p == q) ? 0 : (size_t)(p - data);
774 if (err_len) *err_len = (p == q) ? (size_t)(q - data) : (size_t)(q - p);
776 }
777
778 /*
779 * Validate the GCP/GLN with the "key" linter.
780 *
781 */
782 strncpy(gcp, p, (size_t)vli);
783 ret = gs1_lint_key(gcp, err_pos, err_len);
784
785 assert (ret == GS1_LINTER_OK ||
788
789 if (ret != GS1_LINTER_OK) {
790 if (err_pos) *err_pos = (size_t)(p - data);
791 if (err_len) *err_len = (size_t)vli;
792 return ret;
793 }
794
795 p += vli;
796
797 }
798
799
800 /*
801 * Optional field 9: Miscellaneous
802 * ===============================
803 *
804 * This option field is indicated by the value "9".
805 *
806 */
807 if (p < q && *p == '9') {
808
809 /*
810 * Validate the single-digit Save Value Code.
811 *
812 * Valid values for the Save Value Code are "0" to "2" and "5"
813 * to "6".
814 *
815 */
816 if (++p == q) {
817 if (err_pos) *err_pos = 0;
818 if (err_len) *err_len = (size_t)(q - data);
820 }
821 if (*p != '0' && *p != '1' && *p != '2' && *p != '5' && *p != '6') {
822 if (err_pos) *err_pos = (size_t)(p - data);
823 if (err_len) *err_len = 1;
825 }
826
827
828 /*
829 * Validate the single-digit Save Value Applies to Item value.
830 *
831 * Valid values for Save Value Applies to Item are "0" to "2".
832 *
833 */
834 if (++p == q) {
835 if (err_pos) *err_pos = 0;
836 if (err_len) *err_len = (size_t)(q - data);
838 }
839 if (*p > '2') {
840 if (err_pos) *err_pos = (size_t)(p - data);
841 if (err_len) *err_len = 1;
843 }
844
845
846 /*
847 * Validate the existence of the single-digit Store Coupon
848 * Flag.
849 *
850 */
851 if (++p == q) {
852 if (err_pos) *err_pos = 0;
853 if (err_len) *err_len = (size_t)(q - data);
855 }
856
857
858 /*
859 * Validate the single-digit Don't Multiply Flag.
860 *
861 * Valid values for the Don't Multiply Flag are "0" and "1".
862 *
863 */
864 if (++p == q) {
865 if (err_pos) *err_pos = 0;
866 if (err_len) *err_len = (size_t)(q - data);
868 }
869 if (*p != '0' && *p != '1') {
870 if (err_pos) *err_pos = (size_t)(p - data);
871 if (err_len) *err_len = 1;
873 }
874
875 p++;
876
877 }
878
879 /*
880 * Report excess data that has not been handled as an optional field.
881 *
882 */
883 if (p != q) {
884 if (err_pos) *err_pos = (size_t)(p - data);
885 if (err_len) *err_len = (size_t)(q - p);
887 }
888
889 return GS1_LINTER_OK;
890
891}
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_yymmdd(const char *data, size_t *err_pos, size_t *err_len)
Definition lint_yymmdd.c:52
gs1_lint_err_t
Linter return codes other than GS1_LINTER_OK indicate an error condition.
Definition gs1syntaxdictionary.h:65
@ GS1_LINTER_ILLEGAL_DAY
The date contains an illegal day of the month.
Definition gs1syntaxdictionary.h:102
@ GS1_LINTER_COUPON_TRUNCATED_2ND_PURCHASE_FAMILY_CODE
The coupon's second purchase Family Code is shorter than the required three digits.
Definition gs1syntaxdictionary.h:138
@ GS1_LINTER_COUPON_TRUNCATED_RETAILER_GCP_OR_GLN
The coupon's Retailer GCP/GLN is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:158
@ GS1_LINTER_COUPON_INVALID_2ND_PURCHASE_REQUIREMENT_LENGTH
The coupon's second purchase Requirement VLI must be "1" to "5".
Definition gs1syntaxdictionary.h:134
@ GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_REQUIREMENT_VLI
The coupon's third purchase Requirement VLI is missing.
Definition gs1syntaxdictionary.h:142
@ GS1_LINTER_COUPON_MISSING_RETAILER_GCP_OR_GLN_VLI
The coupon's Retailer GCP/GLN VLI is missing.
Definition gs1syntaxdictionary.h:156
@ GS1_LINTER_COUPON_INVALID_3RD_PURCHASE_REQUIREMENT_LENGTH
The coupon's third purchase Requirement VLI must be "1" to "5".
Definition gs1syntaxdictionary.h:143
@ GS1_LINTER_COUPON_MISSING_1ST_PURCHASE_REQUIREMENT_VLI
The coupon's primary purchase Requirement VLI is missing.
Definition gs1syntaxdictionary.h:125
@ GS1_LINTER_COUPON_INVALID_SAVE_VALUE_CODE
The coupon's Save Value Code must be "0", "1", "2", "5" or "6".
Definition gs1syntaxdictionary.h:160
@ GS1_LINTER_COUPON_INVALID_2ND_PURCHASE_GCP_LENGTH
The coupon's second purchase GS1 Company Prefix VLI must be "0" to "6" or "9".
Definition gs1syntaxdictionary.h:140
@ GS1_LINTER_COUPON_TRUNCATED_1ST_PURCHASE_FAMILY_CODE
The coupon's primary purchase Family Code is shorter than the required three digits.
Definition gs1syntaxdictionary.h:130
@ GS1_LINTER_COUPON_INVALID_SAVE_VALUE_APPLIES_TO_ITEM
The coupon's Save Value Applies to Item must be "0" to "2".
Definition gs1syntaxdictionary.h:162
@ GS1_LINTER_COUPON_MISSING_SAVE_VALUE_APPLIES_TO_ITEM
The coupon's Save Value Applies to Item is missing.
Definition gs1syntaxdictionary.h:161
@ GS1_LINTER_COUPON_TRUNCATED_GCP
The coupon's primary GS1 Company Prefix is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:121
@ GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_REQUIREMENT_CODE
The coupon's third purchase Requirement Code is missing.
Definition gs1syntaxdictionary.h:145
@ GS1_LINTER_COUPON_TRUNCATED_3RD_PURCHASE_REQUIREMENT
The coupon's third purchase Requirement is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:144
@ GS1_LINTER_DATE_TOO_LONG
The date is too long for YYMMDD format.
Definition gs1syntaxdictionary.h:95
@ GS1_LINTER_COUPON_TRUNCATED_SAVE_VALUE
The coupon's Save Value is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:124
@ GS1_LINTER_COUPON_INVALID_2ND_PURCHASE_REQUIREMENT_CODE
The coupon's second purchase Requirement Code must be "0" to "4" or "9".
Definition gs1syntaxdictionary.h:137
@ GS1_LINTER_GCP_DATASOURCE_OFFLINE
The data source for GCP lookups is offline.
Definition gs1syntaxdictionary.h:76
@ GS1_LINTER_COUPON_MISSING_SERIAL_NUMBER_VLI
The coupon's Serial Number VLI is missing.
Definition gs1syntaxdictionary.h:117
@ GS1_LINTER_COUPON_TRUNCATED_1ST_PURCHASE_REQUIREMENT
The coupon's primary purchase Requirement is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:127
@ GS1_LINTER_COUPON_MISSING_1ST_PURCHASE_REQUIREMENT_CODE
The coupon's primary purchase Requirement Code is missing.
Definition gs1syntaxdictionary.h:128
@ GS1_LINTER_ILLEGAL_MONTH
The date contains an illegal month of the year.
Definition gs1syntaxdictionary.h:101
@ GS1_LINTER_COUPON_MISSING_GCP_VLI
The coupon's primary GS1 Company Prefix VLI is missing.
Definition gs1syntaxdictionary.h:119
@ GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_REQUIREMENT_CODE
The coupon's second purchase Requirement Code is missing.
Definition gs1syntaxdictionary.h:136
@ GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_REQUIREMENT_VLI
The coupon's second purchase Requirement VLI is missing.
Definition gs1syntaxdictionary.h:133
@ GS1_LINTER_COUPON_TRUNCATED_3RD_PURCHASE_FAMILY_CODE
The coupon's third purchase Family Code is shorter than the required three digits.
Definition gs1syntaxdictionary.h:147
@ GS1_LINTER_COUPON_TRUNCATED_SERIAL_NUMBER
The coupon's Serial Number is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:118
@ GS1_LINTER_COUPON_TOO_SHORT_FOR_START_DATE
The coupon's start date is too short to YYMMDD format.
Definition gs1syntaxdictionary.h:153
@ GS1_LINTER_COUPON_INVALID_START_DATE
The coupon's start date is invalid.
Definition gs1syntaxdictionary.h:154
@ GS1_LINTER_COUPON_INVALID_SAVE_VALUE_LENGTH
The coupon's Save Value VLI must be "1" to "5".
Definition gs1syntaxdictionary.h:123
@ GS1_LINTER_COUPON_TRUNCATED_OFFER_CODE
The coupon's Offer Code is shorter than the required six digits.
Definition gs1syntaxdictionary.h:116
@ GS1_LINTER_COUPON_MISSING_ADDITIONAL_PURCHASE_RULES_CODE
The coupon's Additional Purchase Rules Code is missing.
Definition gs1syntaxdictionary.h:131
@ GS1_LINTER_COUPON_INVALID_DONT_MULTIPLY_FLAG
The coupon's Don't Multiply Flag must be "0" or "1".
Definition gs1syntaxdictionary.h:165
@ GS1_LINTER_COUPON_TRUNCATED_2ND_PURCHASE_GCP
The coupon's second purchase GS1 Company Prefix is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:141
@ GS1_LINTER_COUPON_MISSING_STORE_COUPON_FLAG
The coupon's Store Coupon Flag is missing.
Definition gs1syntaxdictionary.h:163
@ GS1_LINTER_COUPON_EXCESS_DATA
The coupon contains excess data after the recognised optional fields.
Definition gs1syntaxdictionary.h:166
@ GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_GCP_VLI
The coupon's third purchase GS1 Company Prefix VLI is missing.
Definition gs1syntaxdictionary.h:148
@ GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_GCP_VLI
The coupon's second purchase GS1 Company Prefix VLI is missing.
Definition gs1syntaxdictionary.h:139
@ GS1_LINTER_COUPON_TOO_SHORT_FOR_EXPIRATION_DATE
The coupon's expiration date is too short for YYMMDD format.
Definition gs1syntaxdictionary.h:151
@ GS1_LINTER_COUPON_INVALID_GCP_LENGTH
The coupon's primary GS1 Company Prefix VLI must be "0" to "6".
Definition gs1syntaxdictionary.h:120
@ GS1_LINTER_DATE_TOO_SHORT
The date is too short for YYMMDD format.
Definition gs1syntaxdictionary.h:94
@ GS1_LINTER_COUPON_INVALID_EXIPIRATION_DATE
The coupon's expiration date is invalid.
Definition gs1syntaxdictionary.h:152
@ GS1_LINTER_COUPON_MISSING_SAVE_VALUE_VLI
The coupon's Save Value VLI is missing.
Definition gs1syntaxdictionary.h:122
@ GS1_LINTER_COUPON_INVALID_1ST_PURCHASE_REQUIREMENT_CODE
The coupon's primary purchase Requirement Code must be "0" to "4" or "9".
Definition gs1syntaxdictionary.h:129
@ GS1_LINTER_COUPON_TRUNCATED_2ND_PURCHASE_REQUIREMENT
The coupon's second purchase Requirement is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:135
@ GS1_LINTER_OK
No issues were detected by the linter.
Definition gs1syntaxdictionary.h:66
@ GS1_LINTER_COUPON_INVALID_3RD_PURCHASE_REQUIREMENT_CODE
The coupon's third purchase Requirement Code must be "0" to "4" or "9".
Definition gs1syntaxdictionary.h:146
@ GS1_LINTER_COUPON_EXPIRATION_BEFORE_START
The coupon's expiration date preceed the start date.
Definition gs1syntaxdictionary.h:155
@ GS1_LINTER_COUPON_INVALID_ADDITIONAL_PURCHASE_RULES_CODE
The coupon's Additional Purchase Rules Code must be "0" to "3".
Definition gs1syntaxdictionary.h:132
@ GS1_LINTER_COUPON_INVALID_1ST_PURCHASE_REQUIREMENT_LENGTH
The coupon's primary purchase Requirement VLI must be "1" to "5".
Definition gs1syntaxdictionary.h:126
@ GS1_LINTER_INVALID_GCP_PREFIX
The GS1 Company Prefix is invalid.
Definition gs1syntaxdictionary.h:78
@ GS1_LINTER_COUPON_TRUNCATED_3RD_PURCHASE_GCP
The coupon's third purchase GS1 Company Prefix is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:150
@ GS1_LINTER_NON_DIGIT_CHARACTER
A non-digit character was found where a digit is expected.
Definition gs1syntaxdictionary.h:67
@ GS1_LINTER_COUPON_MISSING_DONT_MULTIPLY_FLAG
The coupon's Don't Multiply Flag is missing.
Definition gs1syntaxdictionary.h:164
@ GS1_LINTER_COUPON_MISSING_SAVE_VALUE_CODE
The coupon's Save Value Code is missing.
Definition gs1syntaxdictionary.h:159
@ GS1_LINTER_COUPON_INVALID_RETAILER_GCP_OR_GLN_LENGTH
The coupon's Retailer GCP/GLN VLI must be "1" to "7".
Definition gs1syntaxdictionary.h:157
@ GS1_LINTER_COUPON_INVALID_3RD_PURCHASE_GCP_LENGTH
The coupon's third purchase GS1 Company Prefix VLI must be "0" to "6" or "9".
Definition gs1syntaxdictionary.h:149
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_key(const char *data, size_t *err_pos, size_t *err_len)
Definition lint_key.c:95