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_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  data_len,
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 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_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 contains 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 purchase 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 contains 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.
185{
186
187 gs1_lint_err_t ret;
188 size_t pos;
189 int vli;
190 const char *p, *q;
191 const char *expiry_date_p = NULL;
192 int expiry_set = 0;
193
194 assert(data);
195
196 /*
197 * Data must consist of all digits.
198 *
199 */
200 for (pos = 0; pos < data_len; pos++) {
201 if (GS1_LINTER_UNLIKELY(data[pos] < '0' || data[pos] > '9'))
204 pos,
205 1
206 );
207 }
208
209 p = data;
210 q = data + data_len;
211
212 /*
213 * Validate that the GCP follows its VLI and has the corresponding
214 * length (plus 6).
215 *
216 * Valid GCP VLIs are "0" to "6".
217 *
218 */
219 if (GS1_LINTER_UNLIKELY(p == q))
222 0,
223 (size_t)(q - data)
224 );
225 if (GS1_LINTER_UNLIKELY(*p > '6'))
228 (size_t)(p - data),
229 1
230 );
231 vli = *p - '0' + 6;
232
233 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
236 (p == q) ? 0 : (size_t)(p - data),
237 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
238 );
239
240 /*
241 * Validate the GCP with the "gcppos1" linter.
242 *
243 */
244 ret = gs1_lint_gcppos1(p, (size_t)vli, err_pos, err_len);
245
246 assert (ret == GS1_LINTER_OK ||
249
252 ret,
253 (size_t)(p - data),
254 (size_t)vli
255 );
256
257 p += vli;
258
259
260 /*
261 * Validate the existence of the six digit Offer Code.
262 *
263 */
264 if (GS1_LINTER_UNLIKELY(q - p < 6))
267 (p == q) ? 0 : (size_t)(p - data),
268 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
269 );
270
271 p += 6;
272
273
274 /*
275 * Validate that the Save Value follows its VLI and has the
276 * corresponding length.
277 *
278 * Valid Save Value VLIs are "1" to "5".
279 *
280 */
281 if (GS1_LINTER_UNLIKELY(p == q))
284 0,
285 (size_t)(q - data)
286 );
287 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '5'))
290 (size_t)(p - data),
291 1
292 );
293 vli = *p - '0';
294
295 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
298 (p == q) ? 0 : (size_t)(p - data),
299 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
300 );
301
302 p += vli;
303
304
305 /*
306 * Validate 1st Purchase Requirement follows its VLI and has the
307 * corresponding length.
308 *
309 * Valid 1st Purchase Requirement VLIs are "1" to "5".
310 *
311 */
312 if (GS1_LINTER_UNLIKELY(p == q))
315 0,
316 (size_t)(q - data)
317 );
318 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '5'))
321 (size_t)(p - data),
322 1
323 );
324 vli = *p - '0';
325
326 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
329 (p == q) ? 0 : (size_t)(p - data),
330 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
331 );
332
333 p += vli;
334
335
336 /*
337 * Validate the single-digit 1st Purchase Requirement Code.
338 *
339 * Valid values for 1st Purchase Requirement Code are "0" to "4" and
340 * "9".
341 *
342 */
343 if (GS1_LINTER_UNLIKELY(p == q))
346 0,
347 (size_t)(q - data)
348 );
349
350 if (GS1_LINTER_UNLIKELY(*p > '4' && *p != '9'))
353 (size_t)(p - data),
354 1
355 );
356
357
358 /*
359 * Validate the existence of the three-digit 1st Purchase Family Code.
360 *
361 */
362 if (GS1_LINTER_UNLIKELY(q - ++p < 3))
365 (p == q) ? 0 : (size_t)(p - data),
366 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
367 );
368
369 p += 3;
370
371
372 /*
373 * Optional field 1: Additional rules and 2nd purchase
374 * ===================================================
375 *
376 * This option field is indicated by the value "1".
377 *
378 */
379 if (p < q && *p == '1') {
380
381 /*
382 * Validate the single-digit Additional Purchase Rules Code.
383 *
384 * Valid values for the Additional Purchase Rules Code are "0"
385 * to "3".
386 *
387 */
388 if (GS1_LINTER_UNLIKELY(++p == q))
391 0,
392 (size_t)(q - data)
393 );
394
395 if (GS1_LINTER_UNLIKELY(*p > '3'))
398 (size_t)(p - data),
399 1
400 );
401
402
403 /*
404 * Validate 2nd Purchase Requirement follows its VLI and has
405 * the corresponding length.
406 *
407 * Valid values for the 2nd Purchase Requirement VLI are "1" to
408 * "5".
409 *
410 */
411 if (GS1_LINTER_UNLIKELY(++p == q))
414 0,
415 (size_t)(q - data)
416 );
417 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '5'))
420 (size_t)(p - data),
421 1
422 );
423 vli = *p - '0';
424
425 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
428 (p == q) ? 0 : (size_t)(p - data),
429 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
430 );
431
432 p += vli;
433
434
435 /*
436 * Validate the single-digit 2nd Purchase Requirement Code.
437 *
438 * Valid values for the 2nd Purchase Requirement Code are "0"
439 * to "4" and "9".
440 *
441 */
442 if (GS1_LINTER_UNLIKELY(p == q))
445 0,
446 (size_t)(q - data)
447 );
448
449 if (GS1_LINTER_UNLIKELY(*p > '4' && *p != '9'))
452 (size_t)(p - data),
453 1
454 );
455
456
457 /*
458 * Validate the existence of the three-digit 2nd Purchase
459 * Family Code.
460 *
461 */
462 if (GS1_LINTER_UNLIKELY(q - ++p < 3))
465 (p == q) ? 0 : (size_t)(p - data),
466 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
467 );
468
469 p += 3;
470
471
472 /*
473 * Validate that the 2nd Purchase GCP follows its VLI and has
474 * the corresponding length (plus 6, unless VLI is "9").
475 *
476 * Valid values for the 2nd Purchase GCP VLI are "0" to "6" and
477 * "9".
478 *
479 */
480 if (GS1_LINTER_UNLIKELY(p == q))
483 0,
484 (size_t)(q - data)
485 );
486 if (GS1_LINTER_UNLIKELY(*p > '6' && *p != '9'))
489 (size_t)(p - data),
490 1
491 );
492 vli = (*p != '9') ? *p - '0' + 6 : 0;
493
494 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
497 (p == q) ? 0 : (size_t)(p - data),
498 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
499 );
500
501 /*
502 * Validate the GCP with the "gcppos1" linter.
503 *
504 */
505 if (vli > 0) {
506 ret = gs1_lint_gcppos1(p, (size_t)vli, err_pos, err_len);
507
508 assert (ret == GS1_LINTER_OK ||
511
514 ret,
515 (size_t)(p - data),
516 (size_t)vli
517 );
518
519 p += vli;
520 }
521
522 }
523
524
525 /*
526 * Optional field 2: 3rd purchase
527 * ==============================
528 *
529 * This option field is indicated by the value "2".
530 *
531 */
532 if (p < q && *p == '2') {
533
534 /*
535 * Validate 3rd Purchase Requirement follows its VLI and has
536 * the corresponding length.
537 *
538 * Valid values for the 3rd Purchase Requirement VLI are "1" to
539 * "5".
540 *
541 */
542 if (GS1_LINTER_UNLIKELY(++p == q))
545 0,
546 (size_t)(q - data)
547 );
548 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '5'))
551 (size_t)(p - data),
552 1
553 );
554 vli = *p - '0';
555
556 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
559 (p == q) ? 0 : (size_t)(p - data),
560 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
561 );
562
563 p += vli;
564
565
566 /*
567 * Validate the single-digit 3nd Purchase Requirement Code.
568 *
569 * Valie values for the 3nd Purchase Requirement Code are "0"
570 * to "4" and "9".
571 *
572 */
573 if (GS1_LINTER_UNLIKELY(p == q))
576 0,
577 (size_t)(q - data)
578 );
579
580 if (GS1_LINTER_UNLIKELY(*p > '4' && *p != '9'))
583 (size_t)(p - data),
584 1
585 );
586
587
588 /*
589 * Validate that existence of the three digit 3rd Purchase
590 * Family Code.
591 *
592 */
593 if (GS1_LINTER_UNLIKELY(q - ++p < 3))
596 (p == q) ? 0 : (size_t)(p - data),
597 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
598 );
599
600 p += 3;
601
602
603 /*
604 * Validate that the 3rd Purchase GCP follows its VLI and has
605 * the corresponding length (plus 6, unless VLI is "9").
606 *
607 * Valid values for the 3rd Purchase GCP VLI are "0" to "6" and
608 * "9".
609 *
610 */
611 if (GS1_LINTER_UNLIKELY(p == q))
614 0,
615 (size_t)(q - data)
616 );
617 if (GS1_LINTER_UNLIKELY(*p > '6' && *p != '9'))
620 (size_t)(p - data),
621 1
622 );
623 vli = (*p != '9') ? *p - '0' + 6 : 0;
624
625 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
628 (p == q) ? 0 : (size_t)(p - data),
629 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
630 );
631
632 /*
633 * Validate the GCP with the "gcppos1" linter.
634 *
635 */
636 if (vli > 0) {
637 ret = gs1_lint_gcppos1(p, (size_t)vli, err_pos, err_len);
638
639 assert (ret == GS1_LINTER_OK ||
642
645 ret,
646 (size_t)(p - data),
647 (size_t)vli
648 );
649
650 p += vli;
651 }
652
653 }
654
655
656 /*
657 * Optional field 3: Expiration date
658 * =================================
659 *
660 * This option field is indicated by the value "3".
661 *
662 */
663 if (p < q && *p == '3') {
664
665 /*
666 * Validate that the expiration date is in YYMMDD format.
667 *
668 */
669 if (GS1_LINTER_UNLIKELY(q - ++p < 6))
672 (p == q) ? 0 : (size_t)(p - data),
673 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
674 );
675
676 expiry_date_p = p;
677 ret = gs1_lint_yymmdd(p, 6, err_pos, err_len);
678
679 assert(ret == GS1_LINTER_OK ||
685
689 (size_t)(p - data),
690 6
691 );
692
693 p += 6;
694
695 expiry_set = 1;
696
697 }
698
699
700 /*
701 * Optional field 4: Start date
702 * ============================
703 *
704 * This option field is indicated by the value "4".
705 *
706 */
707 if (p < q && *p == '4') {
708
709 const char *start_date_p;
710
711 /*
712 * Validate that the start date is in YYMMDD format.
713 *
714 */
715 if (GS1_LINTER_UNLIKELY(q - ++p < 6))
718 (p == q) ? 0 : (size_t)(p - data),
719 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
720 );
721
722 start_date_p = p;
723 ret = gs1_lint_yymmdd(p, 6, err_pos, err_len);
724
725 assert(ret == GS1_LINTER_OK ||
731
735 (size_t)(p - data),
736 6
737 );
738
739 /*
740 * If an expiration date has been set, then ensure that it does
741 * not precede the start date.
742 *
743 */
744 if (GS1_LINTER_UNLIKELY(expiry_set && memcmp(start_date_p, expiry_date_p, 6) > 0))
747 (size_t)(p - data - 8),
748 14
749 );
750
751 p += 6;
752
753 }
754
755
756 /*
757 * Optional field 5: Serial number
758 * ===============================
759 *
760 * This option field is indicated by the value "5".
761 *
762 */
763 if (p < q && *p == '5') {
764
765 /*
766 * Validate Serial Number follows its VLI and has the corresponding
767 * length (plus 6).
768 *
769 */
770 if (GS1_LINTER_UNLIKELY(++p == q))
773 0,
774 (size_t)(q - data)
775 );
776 vli = *p - '0' + 6;
777
778 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
781 (p == q) ? 0 : (size_t)(p - data),
782 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
783 );
784
785 p += vli;
786
787 }
788
789
790 /*
791 * Optional field 6: Retailer GCP/GLN
792 * ==================================
793 *
794 * This option field is indicated by the value "6".
795 *
796 */
797 if (p < q && *p == '6') {
798
799 /*
800 * Validate that the Retailer GCP/GLN follows its VLI and has
801 * the corresponding length (plus 6).
802 *
803 * Valid values for the Retailer GCP/GLN VLI are "1" to "7".
804 *
805 */
806 if (GS1_LINTER_UNLIKELY(++p == q))
809 0,
810 (size_t)(q - data)
811 );
812 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '7'))
815 (size_t)(p - data),
816 1
817 );
818 vli = *p - '0' + 6;
819
820 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
823 (p == q) ? 0 : (size_t)(p - data),
824 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
825 );
826
827 /*
828 * Validate the GCP/GLN with the "gcppos1" linter.
829 *
830 */
831 ret = gs1_lint_gcppos1(p, (size_t)vli, err_pos, err_len);
832
833 assert (ret == GS1_LINTER_OK ||
836
839 ret,
840 (size_t)(p - data),
841 (size_t)vli
842 );
843
844 p += vli;
845
846 }
847
848
849 /*
850 * Optional field 9: Miscellaneous
851 * ===============================
852 *
853 * This option field is indicated by the value "9".
854 *
855 */
856 if (p < q && *p == '9') {
857
858 /*
859 * Validate the single-digit Save Value Code.
860 *
861 * Valid values for the Save Value Code are "0" to "2" and "5"
862 * to "6".
863 *
864 */
865 if (GS1_LINTER_UNLIKELY(++p == q))
868 0,
869 (size_t)(q - data)
870 );
871 if (GS1_LINTER_UNLIKELY(*p != '0' && *p != '1' && *p != '2' && *p != '5' && *p != '6'))
874 (size_t)(p - data),
875 1
876 );
877
878
879 /*
880 * Validate the single-digit Save Value Applies to Item value.
881 *
882 * Valid values for Save Value Applies to Item are "0" to "2".
883 *
884 */
885 if (GS1_LINTER_UNLIKELY(++p == q))
888 0,
889 (size_t)(q - data)
890 );
891 if (GS1_LINTER_UNLIKELY(*p > '2'))
894 (size_t)(p - data),
895 1
896 );
897
898
899 /*
900 * Validate the existence of the single-digit Store Coupon
901 * Flag.
902 *
903 */
904 if (GS1_LINTER_UNLIKELY(++p == q))
907 0,
908 (size_t)(q - data)
909 );
910
911
912 /*
913 * Validate the single-digit Don't Multiply Flag.
914 *
915 * Valid values for the Don't Multiply Flag are "0" and "1".
916 *
917 */
918 if (GS1_LINTER_UNLIKELY(++p == q))
921 0,
922 (size_t)(q - data)
923 );
924 if (GS1_LINTER_UNLIKELY(*p != '0' && *p != '1'))
927 (size_t)(p - data),
928 1
929 );
930
931 p++;
932
933 }
934
935 /*
936 * Report excess data that has not been handled as an optional field.
937 *
938 */
939 if (GS1_LINTER_UNLIKELY(p != q))
942 (size_t)(p - data),
943 (size_t)(q - p)
944 );
945
947
948}
#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_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_gcppos1(const char *data, size_t data_len, size_t *err_pos, size_t *err_len)
Definition lint_gcppos1.c:102
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_COUPON_TRUNCATED_2ND_PURCHASE_FAMILY_CODE
The coupon's second purchase Family Code is shorter than the required three digits.
Definition gs1syntaxdictionary.h:150
@ 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:170
@ GS1_LINTER_COUPON_INVALID_2ND_PURCHASE_REQUIREMENT_LENGTH
The coupon's second purchase Requirement VLI must be "1" to "5".
Definition gs1syntaxdictionary.h:146
@ GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_REQUIREMENT_VLI
The coupon's third purchase Requirement VLI is missing.
Definition gs1syntaxdictionary.h:154
@ GS1_LINTER_COUPON_MISSING_RETAILER_GCP_OR_GLN_VLI
The coupon's Retailer GCP/GLN VLI is missing.
Definition gs1syntaxdictionary.h:168
@ GS1_LINTER_COUPON_INVALID_3RD_PURCHASE_REQUIREMENT_LENGTH
The coupon's third purchase Requirement VLI must be "1" to "5".
Definition gs1syntaxdictionary.h:155
@ GS1_LINTER_COUPON_MISSING_1ST_PURCHASE_REQUIREMENT_VLI
The coupon's primary purchase Requirement VLI is missing.
Definition gs1syntaxdictionary.h:137
@ GS1_LINTER_COUPON_INVALID_SAVE_VALUE_CODE
The coupon's Save Value Code must be "0", "1", "2", "5" or "6".
Definition gs1syntaxdictionary.h:172
@ 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:152
@ 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:142
@ 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:174
@ GS1_LINTER_COUPON_MISSING_SAVE_VALUE_APPLIES_TO_ITEM
The coupon's Save Value Applies to Item is missing.
Definition gs1syntaxdictionary.h:173
@ GS1_LINTER_COUPON_TRUNCATED_GCP
The coupon's primary GS1 Company Prefix is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:133
@ GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_REQUIREMENT_CODE
The coupon's third purchase Requirement Code is missing.
Definition gs1syntaxdictionary.h:157
@ 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:156
@ GS1_LINTER_DATE_TOO_LONG
The date is too long for YYMMDD format.
Definition gs1syntaxdictionary.h:106
@ GS1_LINTER_COUPON_TRUNCATED_SAVE_VALUE
The coupon's Save Value is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:136
@ 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:149
@ GS1_LINTER_GCP_DATASOURCE_OFFLINE
The data source for GCP lookups is offline.
Definition gs1syntaxdictionary.h:87
@ GS1_LINTER_COUPON_MISSING_SERIAL_NUMBER_VLI
The coupon's Serial Number VLI is missing.
Definition gs1syntaxdictionary.h:129
@ 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:139
@ GS1_LINTER_COUPON_MISSING_1ST_PURCHASE_REQUIREMENT_CODE
The coupon's primary purchase Requirement Code is missing.
Definition gs1syntaxdictionary.h:140
@ GS1_LINTER_ILLEGAL_MONTH
The date contains an illegal month of the year.
Definition gs1syntaxdictionary.h:113
@ GS1_LINTER_COUPON_MISSING_GCP_VLI
The coupon's primary GS1 Company Prefix VLI is missing.
Definition gs1syntaxdictionary.h:131
@ GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_REQUIREMENT_CODE
The coupon's second purchase Requirement Code is missing.
Definition gs1syntaxdictionary.h:148
@ GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_REQUIREMENT_VLI
The coupon's second purchase Requirement VLI is missing.
Definition gs1syntaxdictionary.h:145
@ 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:159
@ GS1_LINTER_COUPON_TRUNCATED_SERIAL_NUMBER
The coupon's Serial Number is shorter than what is indicated by its VLI.
Definition gs1syntaxdictionary.h:130
@ GS1_LINTER_COUPON_TOO_SHORT_FOR_START_DATE
The coupon's start date is too short to YYMMDD format.
Definition gs1syntaxdictionary.h:165
@ GS1_LINTER_COUPON_INVALID_START_DATE
The coupon's start date is invalid.
Definition gs1syntaxdictionary.h:166
@ GS1_LINTER_COUPON_INVALID_SAVE_VALUE_LENGTH
The coupon's Save Value VLI must be "1" to "5".
Definition gs1syntaxdictionary.h:135
@ GS1_LINTER_COUPON_TRUNCATED_OFFER_CODE
The coupon's Offer Code is shorter than the required six digits.
Definition gs1syntaxdictionary.h:128
@ GS1_LINTER_COUPON_MISSING_ADDITIONAL_PURCHASE_RULES_CODE
The coupon's Additional Purchase Rules Code is missing.
Definition gs1syntaxdictionary.h:143
@ GS1_LINTER_COUPON_INVALID_DONT_MULTIPLY_FLAG
The coupon's Don't Multiply Flag must be "0" or "1".
Definition gs1syntaxdictionary.h:177
@ 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:153
@ GS1_LINTER_COUPON_MISSING_STORE_COUPON_FLAG
The coupon's Store Coupon Flag is missing.
Definition gs1syntaxdictionary.h:175
@ GS1_LINTER_COUPON_EXCESS_DATA
The coupon contains excess data after the recognised optional fields.
Definition gs1syntaxdictionary.h:178
@ GS1_LINTER_COUPON_MISSING_3RD_PURCHASE_GCP_VLI
The coupon's third purchase GS1 Company Prefix VLI is missing.
Definition gs1syntaxdictionary.h:160
@ GS1_LINTER_COUPON_MISSING_2ND_PURCHASE_GCP_VLI
The coupon's second purchase GS1 Company Prefix VLI is missing.
Definition gs1syntaxdictionary.h:151
@ GS1_LINTER_COUPON_TOO_SHORT_FOR_EXPIRATION_DATE
The coupon's expiration date is too short for YYMMDD format.
Definition gs1syntaxdictionary.h:163
@ GS1_LINTER_COUPON_INVALID_GCP_LENGTH
The coupon's primary GS1 Company Prefix VLI must be "0" to "6".
Definition gs1syntaxdictionary.h:132
@ GS1_LINTER_DATE_TOO_SHORT
The date is too short for YYMMDD format.
Definition gs1syntaxdictionary.h:105
@ GS1_LINTER_COUPON_INVALID_EXIPIRATION_DATE
The coupon's expiration date is invalid.
Definition gs1syntaxdictionary.h:164
@ GS1_LINTER_COUPON_MISSING_SAVE_VALUE_VLI
The coupon's Save Value VLI is missing.
Definition gs1syntaxdictionary.h:134
@ 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:141
@ 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:147
@ GS1_LINTER_OK
No issues were detected by the linter.
Definition gs1syntaxdictionary.h:77
@ 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:158
@ GS1_LINTER_COUPON_EXPIRATION_BEFORE_START
The coupon's expiration date precede the start date.
Definition gs1syntaxdictionary.h:167
@ GS1_LINTER_COUPON_INVALID_ADDITIONAL_PURCHASE_RULES_CODE
The coupon's Additional Purchase Rules Code must be "0" to "3".
Definition gs1syntaxdictionary.h:144
@ GS1_LINTER_COUPON_INVALID_1ST_PURCHASE_REQUIREMENT_LENGTH
The coupon's primary purchase Requirement VLI must be "1" to "5".
Definition gs1syntaxdictionary.h:138
@ GS1_LINTER_INVALID_GCP_PREFIX
The GS1 Company Prefix is invalid.
Definition gs1syntaxdictionary.h:89
@ 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:162
@ GS1_LINTER_NON_DIGIT_CHARACTER
A non-digit character was found where a digit is expected.
Definition gs1syntaxdictionary.h:78
@ GS1_LINTER_COUPON_MISSING_DONT_MULTIPLY_FLAG
The coupon's Don't Multiply Flag is missing.
Definition gs1syntaxdictionary.h:176
@ GS1_LINTER_COUPON_MISSING_SAVE_VALUE_CODE
The coupon's Save Value Code is missing.
Definition gs1syntaxdictionary.h:171
@ GS1_LINTER_COUPON_INVALID_RETAILER_GCP_OR_GLN_LENGTH
The coupon's Retailer GCP/GLN VLI must be "1" to "7".
Definition gs1syntaxdictionary.h:169
@ 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:161
GS1_SYNTAX_DICTIONARY_API gs1_lint_err_t gs1_lint_yymmdd(const char *data, size_t data_len, size_t *err_pos, size_t *err_len)
Definition lint_yymmdd.c:53