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 *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.
185{
186
187 gs1_lint_err_t ret;
188 size_t pos;
189 int vli;
190 const char *p, *q;
191 char expiry_date[7] = {0};
192 int expiry_set = 0;
193 char gcp[14] = {0};
194
195 assert(data);
196
197 /*
198 * Data must consist of all digits.
199 *
200 */
201 for (pos = 0; data[pos] != '\0'; pos++) {
202 if (GS1_LINTER_UNLIKELY(data[pos] < '0' || data[pos] > '9'))
205 pos,
206 1
207 );
208 }
209
210 p = data;
211 q = data + pos;
212
213
214 /*
215 * Validate that the GCP follows its VLI and has the corresponding
216 * length (plus 6).
217 *
218 * Valid GCP VLIs are "0" to "6".
219 *
220 */
221 if (GS1_LINTER_UNLIKELY(p == q))
224 0,
225 (size_t)(q - data)
226 );
227 if (GS1_LINTER_UNLIKELY(*p > '6'))
230 (size_t)(p - data),
231 1
232 );
233 vli = *p - '0' + 6;
234
235 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
238 (p == q) ? 0 : (size_t)(p - data),
239 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
240 );
241
242 /*
243 * Validate the GCP with the "gcppos1" linter.
244 *
245 */
246 strncpy(gcp, p, (size_t)vli);
247 ret = gs1_lint_gcppos1(gcp, err_pos, err_len);
248
249 assert (ret == GS1_LINTER_OK ||
252
255 ret,
256 (size_t)(p - data),
257 (size_t)vli
258 );
259
260 p += vli;
261
262
263 /*
264 * Validate the existence of the six digit Offer Code.
265 *
266 */
267 if (GS1_LINTER_UNLIKELY(q - p < 6))
270 (p == q) ? 0 : (size_t)(p - data),
271 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
272 );
273
274 p += 6;
275
276
277 /*
278 * Validate that the Save Value follows its VLI and has the
279 * corresponding length.
280 *
281 * Valid Save Value VLIs are "1" to "5".
282 *
283 */
284 if (GS1_LINTER_UNLIKELY(p == q))
287 0,
288 (size_t)(q - data)
289 );
290 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '5'))
293 (size_t)(p - data),
294 1
295 );
296 vli = *p - '0';
297
298 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
301 (p == q) ? 0 : (size_t)(p - data),
302 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
303 );
304
305 p += vli;
306
307
308 /*
309 * Validate 1st Purchase Requirement follows its VLI and has the
310 * corresponding length.
311 *
312 * Valid 1st Purchase Requirement VLIs are "1" to "5".
313 *
314 */
315 if (GS1_LINTER_UNLIKELY(p == q))
318 0,
319 (size_t)(q - data)
320 );
321 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '5'))
324 (size_t)(p - data),
325 1
326 );
327 vli = *p - '0';
328
329 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
332 (p == q) ? 0 : (size_t)(p - data),
333 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
334 );
335
336 p += vli;
337
338
339 /*
340 * Validate the single-digit 1st Purchase Requirement Code.
341 *
342 * Valid values for 1st Purchase Requirement Code are "0" to "4" and
343 * "9".
344 *
345 */
346 if (GS1_LINTER_UNLIKELY(p == q))
349 0,
350 (size_t)(q - data)
351 );
352
353 if (GS1_LINTER_UNLIKELY(*p > '4' && *p != '9'))
356 (size_t)(p - data),
357 1
358 );
359
360
361 /*
362 * Validate the existence of the three-digit 1st Purchase Family Code.
363 *
364 */
365 if (GS1_LINTER_UNLIKELY(q - ++p < 3))
368 (p == q) ? 0 : (size_t)(p - data),
369 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
370 );
371
372 p += 3;
373
374
375 /*
376 * Optional field 1: Additional rules and 2nd purchase
377 * ===================================================
378 *
379 * This option field is indicated by the value "1".
380 *
381 */
382 if (p < q && *p == '1') {
383
384 /*
385 * Validate the single-digit Additional Purchase Rules Code.
386 *
387 * Valid values for the Additional Purchase Rules Code are "0"
388 * to "3".
389 *
390 */
391 if (GS1_LINTER_UNLIKELY(++p == q))
394 0,
395 (size_t)(q - data)
396 );
397
398 if (GS1_LINTER_UNLIKELY(*p > '3'))
401 (size_t)(p - data),
402 1
403 );
404
405
406 /*
407 * Validate 2nd Purchase Requirement follows its VLI and has
408 * the corresponding length.
409 *
410 * Valid values for the 2nd Purchase Requirement VLI are "1" to
411 * "5".
412 *
413 */
414 if (GS1_LINTER_UNLIKELY(++p == q))
417 0,
418 (size_t)(q - data)
419 );
420 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '5'))
423 (size_t)(p - data),
424 1
425 );
426 vli = *p - '0';
427
428 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
431 (p == q) ? 0 : (size_t)(p - data),
432 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
433 );
434
435 p += vli;
436
437
438 /*
439 * Validate the single-digit 2nd Purchase Requirement Code.
440 *
441 * Valid values for the 2nd Purchase Requirement Code are "0"
442 * to "4" and "9".
443 *
444 */
445 if (GS1_LINTER_UNLIKELY(p == q))
448 0,
449 (size_t)(q - data)
450 );
451
452 if (GS1_LINTER_UNLIKELY(*p > '4' && *p != '9'))
455 (size_t)(p - data),
456 1
457 );
458
459
460 /*
461 * Validate the existence of the three-digit 2nd Purchase
462 * Family Code.
463 *
464 */
465 if (GS1_LINTER_UNLIKELY(q - ++p < 3))
468 (p == q) ? 0 : (size_t)(p - data),
469 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
470 );
471
472 p += 3;
473
474
475 /*
476 * Validate that the 2nd Purchase GCP follows its VLI and has
477 * the corresponding length (plus 6, unless VLI is "9").
478 *
479 * Valid values for the 2nd Purchase GCP VLI are "0" to "6" and
480 * "9".
481 *
482 */
483 if (GS1_LINTER_UNLIKELY(p == q))
486 0,
487 (size_t)(q - data)
488 );
489 if (GS1_LINTER_UNLIKELY(*p > '6' && *p != '9'))
492 (size_t)(p - data),
493 1
494 );
495 vli = (*p != '9') ? *p - '0' + 6 : 0;
496
497 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
500 (p == q) ? 0 : (size_t)(p - data),
501 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
502 );
503
504 /*
505 * Validate the GCP with the "gcppos1" linter.
506 *
507 */
508 strncpy(gcp, p, (size_t)vli);
509 ret = gs1_lint_gcppos1(gcp, err_pos, err_len);
510
511 assert (ret == GS1_LINTER_OK ||
514
517 ret,
518 (size_t)(p - data),
519 (size_t)vli
520 );
521
522 p += vli;
523
524 }
525
526
527 /*
528 * Optional field 2: 3rd purchase
529 * ==============================
530 *
531 * This option field is indicated by the value "2".
532 *
533 */
534 if (p < q && *p == '2') {
535
536 /*
537 * Validate 3rd Purchase Requirement follows its VLI and has
538 * the corresponding length.
539 *
540 * Valid values for the 3rd Purchase Requirement VLI are "1" to
541 * "5".
542 *
543 */
544 if (GS1_LINTER_UNLIKELY(++p == q))
547 0,
548 (size_t)(q - data)
549 );
550 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '5'))
553 (size_t)(p - data),
554 1
555 );
556 vli = *p - '0';
557
558 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
561 (p == q) ? 0 : (size_t)(p - data),
562 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
563 );
564
565 p += vli;
566
567
568 /*
569 * Validate the single-digit 3nd Purchase Requirement Code.
570 *
571 * Valie values for the 3nd Purchase Requirement Code are "0"
572 * to "4" and "9".
573 *
574 */
575 if (GS1_LINTER_UNLIKELY(p == q))
578 0,
579 (size_t)(q - data)
580 );
581
582 if (GS1_LINTER_UNLIKELY(*p > '4' && *p != '9'))
585 (size_t)(p - data),
586 1
587 );
588
589
590 /*
591 * Validate that existence of the three digit 3rd Purchase
592 * Family Code.
593 *
594 */
595 if (GS1_LINTER_UNLIKELY(q - ++p < 3))
598 (p == q) ? 0 : (size_t)(p - data),
599 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
600 );
601
602 p += 3;
603
604
605 /*
606 * Validate that the 3rd Purchase GCP follows its VLI and has
607 * the corresponding length (plus 6, unless VLI is "9").
608 *
609 * Valid values for the 3rd Purchase GCP VLI are "0" to "6" and
610 * "9".
611 *
612 */
613 if (GS1_LINTER_UNLIKELY(p == q))
616 0,
617 (size_t)(q - data)
618 );
619 if (GS1_LINTER_UNLIKELY(*p > '6' && *p != '9'))
622 (size_t)(p - data),
623 1
624 );
625 vli = (*p != '9') ? *p - '0' + 6 : 0;
626
627 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
630 (p == q) ? 0 : (size_t)(p - data),
631 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
632 );
633
634 /*
635 * Validate the GCP with the "gcppos1" linter.
636 *
637 */
638 strncpy(gcp, p, (size_t)vli);
639 ret = gs1_lint_gcppos1(gcp, err_pos, err_len);
640
641 assert (ret == GS1_LINTER_OK ||
644
647 ret,
648 (size_t)(p - data),
649 (size_t)vli
650 );
651
652 p += vli;
653
654 }
655
656
657 /*
658 * Optional field 3: Expiration date
659 * =================================
660 *
661 * This option field is indicated by the value "3".
662 *
663 */
664 if (p < q && *p == '3') {
665
666 /*
667 * Validate that the expiration date is in YYMMDD format.
668 *
669 */
670 if (GS1_LINTER_UNLIKELY(q - ++p < 6))
673 (p == q) ? 0 : (size_t)(p - data),
674 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
675 );
676
677 memcpy(expiry_date, p, 6);
678 ret = gs1_lint_yymmdd(expiry_date, err_pos, err_len);
679
680 assert(ret == GS1_LINTER_OK ||
686
690 (size_t)(p - data),
691 6
692 );
693
694 p += 6;
695
696 expiry_set = 1;
697
698 }
699
700
701 /*
702 * Optional field 4: Start date
703 * ============================
704 *
705 * This option field is indicated by the value "4".
706 *
707 */
708 if (p < q && *p == '4') {
709
710 char start_date[7] = {0};
711
712 /*
713 * Validate that the start date is in YYMMDD format.
714 *
715 */
716 if (GS1_LINTER_UNLIKELY(q - ++p < 6))
719 (p == q) ? 0 : (size_t)(p - data),
720 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
721 );
722
723 memcpy(start_date, p, 6);
724 ret = gs1_lint_yymmdd(start_date, err_pos, err_len);
725
726 assert(ret == GS1_LINTER_OK ||
732
736 (size_t)(p - data),
737 6
738 );
739
740 /*
741 * If an expiration date has been set, then ensure that it does
742 * not preceed the start date.
743 *
744 */
745 if (GS1_LINTER_UNLIKELY(expiry_set && strcmp(start_date, expiry_date) > 0))
748 (size_t)(p - data - 8),
749 14
750 );
751
752 p += 6;
753
754 }
755
756
757 /*
758 * Optional field 5: Serial number
759 * ===============================
760 *
761 * This option field is indicated by the value "5".
762 *
763 */
764 if (p < q && *p == '5') {
765
766 /*
767 * Validate Serial Number follows its VLI and has the corresponding
768 * length (plus 6).
769 *
770 */
771 if (GS1_LINTER_UNLIKELY(++p == q))
774 0,
775 (size_t)(q - data)
776 );
777 vli = *p - '0' + 6;
778
779 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
782 (p == q) ? 0 : (size_t)(p - data),
783 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
784 );
785
786 p += vli;
787
788 }
789
790
791 /*
792 * Optional field 6: Retailer GCP/GLN
793 * ==================================
794 *
795 * This option field is indicated by the value "6".
796 *
797 */
798 if (p < q && *p == '6') {
799
800 /*
801 * Validate that the Retailer GCP/GLN follows its VLI and has
802 * the corresponding length (plus 6).
803 *
804 * Valid values for the Retailer GCP/GLN VLI are "1" to "7".
805 *
806 */
807 if (GS1_LINTER_UNLIKELY(++p == q))
810 0,
811 (size_t)(q - data)
812 );
813 if (GS1_LINTER_UNLIKELY(*p < '1' || *p > '7'))
816 (size_t)(p - data),
817 1
818 );
819 vli = *p - '0' + 6;
820
821 if (GS1_LINTER_UNLIKELY(q - ++p < vli))
824 (p == q) ? 0 : (size_t)(p - data),
825 (p == q) ? (size_t)(q - data) : (size_t)(q - p)
826 );
827
828 /*
829 * Validate the GCP/GLN with the "gcppos1" linter.
830 *
831 */
832 strncpy(gcp, p, (size_t)vli);
833 ret = gs1_lint_gcppos1(gcp, err_pos, err_len);
834
835 assert (ret == GS1_LINTER_OK ||
838
841 ret,
842 (size_t)(p - data),
843 (size_t)vli
844 );
845
846 p += vli;
847
848 }
849
850
851 /*
852 * Optional field 9: Miscellaneous
853 * ===============================
854 *
855 * This option field is indicated by the value "9".
856 *
857 */
858 if (p < q && *p == '9') {
859
860 /*
861 * Validate the single-digit Save Value Code.
862 *
863 * Valid values for the Save Value Code are "0" to "2" and "5"
864 * to "6".
865 *
866 */
867 if (GS1_LINTER_UNLIKELY(++p == q))
870 0,
871 (size_t)(q - data)
872 );
873 if (GS1_LINTER_UNLIKELY(*p != '0' && *p != '1' && *p != '2' && *p != '5' && *p != '6'))
876 (size_t)(p - data),
877 1
878 );
879
880
881 /*
882 * Validate the single-digit Save Value Applies to Item value.
883 *
884 * Valid values for Save Value Applies to Item are "0" to "2".
885 *
886 */
887 if (GS1_LINTER_UNLIKELY(++p == q))
890 0,
891 (size_t)(q - data)
892 );
893 if (GS1_LINTER_UNLIKELY(*p > '2'))
896 (size_t)(p - data),
897 1
898 );
899
900
901 /*
902 * Validate the existence of the single-digit Store Coupon
903 * Flag.
904 *
905 */
906 if (GS1_LINTER_UNLIKELY(++p == q))
909 0,
910 (size_t)(q - data)
911 );
912
913
914 /*
915 * Validate the single-digit Don't Multiply Flag.
916 *
917 * Valid values for the Don't Multiply Flag are "0" and "1".
918 *
919 */
920 if (GS1_LINTER_UNLIKELY(++p == q))
923 0,
924 (size_t)(q - data)
925 );
926 if (GS1_LINTER_UNLIKELY(*p != '0' && *p != '1'))
929 (size_t)(p - data),
930 1
931 );
932
933 p++;
934
935 }
936
937 /*
938 * Report excess data that has not been handled as an optional field.
939 *
940 */
941 if (GS1_LINTER_UNLIKELY(p != q))
944 (size_t)(p - data),
945 (size_t)(q - p)
946 );
947
949
950}
#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_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:53
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 preceed 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_gcppos1(const char *data, size_t *err_pos, size_t *err_len)
Definition lint_gcppos1.c:101