2008-07-14 01:15:55 +04:00
/* 2of5.c - Handles Code 2 of 5 barcodes */
/*
libzint - the open source barcode library
2017-08-27 11:31:02 +03:00
Copyright ( C ) 2008 - 2017 Robin Stuart < rstuart114 @ gmail . com >
2013-05-16 21:26:38 +04:00
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions
are met :
2017-10-23 22:37:52 +03:00
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2013-05-16 21:26:38 +04:00
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
2017-10-23 22:37:52 +03:00
documentation and / or other materials provided with the distribution .
2013-05-16 21:26:38 +04:00
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
2017-10-23 22:37:52 +03:00
without specific prior written permission .
2013-05-16 21:26:38 +04:00
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY
2017-10-23 22:37:52 +03:00
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
2013-05-16 21:26:38 +04:00
SUCH DAMAGE .
2016-02-20 12:38:03 +03:00
*/
2019-12-19 03:37:55 +03:00
/* vim: set ts=4 sw=4 et : */
2008-07-14 01:15:55 +04:00
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include "common.h"
2009-11-18 01:36:04 +03:00
# ifdef _MSC_VER
# include <malloc.h>
2015-08-18 14:50:42 +03:00
# define inline _inline
2009-11-18 01:36:04 +03:00
# endif
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
static const char * C25MatrixTable [ 10 ] = {
" 113311 " , " 311131 " , " 131131 " , " 331111 " , " 113131 " , " 313111 " ,
" 133111 " , " 111331 " , " 311311 " , " 131311 "
} ;
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
static const char * C25IndustTable [ 10 ] = {
" 1111313111 " , " 3111111131 " , " 1131111131 " , " 3131111111 " , " 1111311131 " ,
" 3111311111 " , " 1131311111 " , " 1111113131 " , " 3111113111 " , " 1131113111 "
} ;
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
static const char * C25InterTable [ 10 ] = {
" 11331 " , " 31113 " , " 13113 " , " 33111 " , " 11313 " , " 31311 " , " 13311 " , " 11133 " ,
" 31131 " , " 13131 "
} ;
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
static inline char check_digit ( unsigned int count ) {
return itoc ( ( 10 - ( count % 10 ) ) % 10 ) ;
2011-03-08 12:58:48 +03:00
}
2016-02-20 12:38:03 +03:00
/* Code 2 of 5 Standard (Code 2 of 5 Matrix) */
2019-12-19 03:37:55 +03:00
INTERNAL int matrix_two_of_five ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2016-02-20 12:38:03 +03:00
int i , error_number ;
char dest [ 512 ] ; /* 6 + 80 * 6 + 6 + 1 ~ 512*/
if ( length > 80 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 301: Input too long " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
error_number = is_sane ( NEON , source , length ) ;
if ( error_number = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 302: Invalid characters in data " ) ;
2016-02-20 12:38:03 +03:00
return error_number ;
}
/* start character */
strcpy ( dest , " 411111 " ) ;
for ( i = 0 ; i < length ; i + + ) {
lookup ( NEON , C25MatrixTable , source [ i ] , dest ) ;
}
/* Stop character */
2016-09-06 00:06:50 +03:00
strcat ( dest , " 41111 " ) ;
2016-02-20 12:38:03 +03:00
expand ( symbol , dest ) ;
ustrcpy ( symbol - > text , source ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}
2016-02-20 12:38:03 +03:00
/* Code 2 of 5 Industrial */
2019-12-19 03:37:55 +03:00
INTERNAL int industrial_two_of_five ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
int i , error_number ;
char dest [ 512 ] ; /* 6 + 40 * 10 + 6 + 1 */
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
if ( length > 45 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 303: Input too long " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
error_number = is_sane ( NEON , source , length ) ;
if ( error_number = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 304: Invalid character in data " ) ;
2016-02-20 12:38:03 +03:00
return error_number ;
}
2012-12-29 22:37:03 +04:00
2016-02-20 12:38:03 +03:00
/* start character */
strcpy ( dest , " 313111 " ) ;
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
for ( i = 0 ; i < length ; i + + ) {
lookup ( NEON , C25IndustTable , source [ i ] , dest ) ;
}
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
/* Stop character */
2016-09-06 00:06:50 +03:00
strcat ( dest , " 31113 " ) ;
2012-12-29 22:37:03 +04:00
2016-02-20 12:38:03 +03:00
expand ( symbol , dest ) ;
ustrcpy ( symbol - > text , source ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}
2016-02-20 12:38:03 +03:00
/* Code 2 of 5 IATA */
2019-12-19 03:37:55 +03:00
INTERNAL int iata_two_of_five ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2016-02-20 12:38:03 +03:00
int i , error_number ;
char dest [ 512 ] ; /* 4 + 45 * 10 + 3 + 1 */
if ( length > 45 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 305: Input too long " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
error_number = is_sane ( NEON , source , length ) ;
if ( error_number = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 306: Invalid characters in data " ) ;
2016-02-20 12:38:03 +03:00
return error_number ;
}
/* start */
strcpy ( dest , " 1111 " ) ;
for ( i = 0 ; i < length ; i + + ) {
lookup ( NEON , C25IndustTable , source [ i ] , dest ) ;
}
/* stop */
2016-09-06 00:06:50 +03:00
strcat ( dest , " 311 " ) ;
2016-02-20 12:38:03 +03:00
expand ( symbol , dest ) ;
ustrcpy ( symbol - > text , source ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}
2016-02-20 12:38:03 +03:00
/* Code 2 of 5 Data Logic */
2019-12-19 03:37:55 +03:00
INTERNAL int logic_two_of_five ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2016-02-20 12:38:03 +03:00
int i , error_number ;
char dest [ 512 ] ; /* 4 + 80 * 6 + 3 + 1 */
if ( length > 80 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 307: Input too long " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
error_number = is_sane ( NEON , source , length ) ;
if ( error_number = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 308: Invalid characters in data " ) ;
2016-02-20 12:38:03 +03:00
return error_number ;
}
/* start character */
strcpy ( dest , " 1111 " ) ;
for ( i = 0 ; i < length ; i + + ) {
lookup ( NEON , C25MatrixTable , source [ i ] , dest ) ;
}
/* Stop character */
2016-09-06 00:06:50 +03:00
strcat ( dest , " 311 " ) ;
2016-02-20 12:38:03 +03:00
expand ( symbol , dest ) ;
ustrcpy ( symbol - > text , source ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}
2016-02-20 12:38:03 +03:00
/* Code 2 of 5 Interleaved */
2019-12-19 03:37:55 +03:00
INTERNAL int interleaved_two_of_five ( struct zint_symbol * symbol , const unsigned char source [ ] , size_t length ) {
2008-07-14 01:15:55 +04:00
2017-09-10 18:03:09 +03:00
int i , j , error_number ;
2016-02-20 12:38:03 +03:00
char bars [ 7 ] , spaces [ 7 ] , mixed [ 14 ] , dest [ 1000 ] ;
2009-11-02 18:47:08 +03:00
# ifndef _MSC_VER
2016-02-20 12:38:03 +03:00
unsigned char temp [ length + 2 ] ;
2009-11-02 18:47:08 +03:00
# else
2016-02-20 12:38:03 +03:00
unsigned char * temp = ( unsigned char * ) _alloca ( ( length + 2 ) * sizeof ( unsigned char ) ) ;
2009-11-02 18:47:08 +03:00
# endif
2008-07-14 01:15:55 +04:00
2016-02-20 12:38:03 +03:00
if ( length > 89 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 309: Input too long " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
error_number = is_sane ( NEON , source , length ) ;
if ( error_number = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 310: Invalid characters in data " ) ;
2016-02-20 12:38:03 +03:00
return error_number ;
}
ustrcpy ( temp , ( unsigned char * ) " " ) ;
/* Input must be an even number of characters for Interlaced 2 of 5 to work:
if an odd number of characters has been entered then add a leading zero */
if ( length & 1 ) {
ustrcpy ( temp , ( unsigned char * ) " 0 " ) ;
length + + ;
}
2016-09-06 00:06:50 +03:00
strcat ( ( char * ) temp , ( char * ) source ) ;
2016-02-20 12:38:03 +03:00
/* start character */
strcpy ( dest , " 1111 " ) ;
for ( i = 0 ; i < length ; i + = 2 ) {
2017-10-23 22:34:31 +03:00
int k = 0 ;
2016-02-20 12:38:03 +03:00
/* look up the bars and the spaces and put them in two strings */
strcpy ( bars , " " ) ;
lookup ( NEON , C25InterTable , temp [ i ] , bars ) ;
strcpy ( spaces , " " ) ;
lookup ( NEON , C25InterTable , temp [ i + 1 ] , spaces ) ;
/* then merge (interlace) the strings together */
for ( j = 0 ; j < = 4 ; j + + ) {
mixed [ k ] = bars [ j ] ;
k + + ;
mixed [ k ] = spaces [ j ] ;
k + + ;
}
mixed [ k ] = ' \0 ' ;
2016-09-06 00:06:50 +03:00
strcat ( dest , mixed ) ;
2016-02-20 12:38:03 +03:00
}
/* Stop character */
2016-09-06 00:06:50 +03:00
strcat ( dest , " 311 " ) ;
2016-02-20 12:38:03 +03:00
expand ( symbol , dest ) ;
ustrcpy ( symbol - > text , temp ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}
2016-02-20 12:38:03 +03:00
/* Interleaved 2-of-5 (ITF) */
2019-12-19 03:37:55 +03:00
INTERNAL int itf14 ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2016-02-20 12:38:03 +03:00
int i , error_number , zeroes ;
unsigned int count ;
char localstr [ 16 ] ;
count = 0 ;
if ( length > 13 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 311: Input too long " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
error_number = is_sane ( NEON , source , length ) ;
if ( error_number = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 312: Invalid character in data " ) ;
2016-02-20 12:38:03 +03:00
return error_number ;
}
/* Add leading zeros as required */
zeroes = 13 - length ;
for ( i = 0 ; i < zeroes ; i + + ) {
localstr [ i ] = ' 0 ' ;
}
strcpy ( localstr + zeroes , ( char * ) source ) ;
/* Calculate the check digit - the same method used for EAN-13 */
for ( i = 12 ; i > = 0 ; i - - ) {
count + = ctoi ( localstr [ i ] ) ;
if ( ! ( i & 1 ) ) {
count + = 2 * ctoi ( localstr [ i ] ) ;
}
}
localstr [ 13 ] = check_digit ( count ) ;
localstr [ 14 ] = ' \0 ' ;
error_number = interleaved_two_of_five ( symbol , ( unsigned char * ) localstr , strlen ( localstr ) ) ;
ustrcpy ( symbol - > text , ( unsigned char * ) localstr ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}
2016-02-20 12:38:03 +03:00
/* Deutshe Post Leitcode */
2019-12-19 03:37:55 +03:00
INTERNAL int dpleit ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2016-02-20 12:38:03 +03:00
int i , error_number ;
unsigned int count ;
char localstr [ 16 ] ;
int zeroes ;
count = 0 ;
if ( length > 13 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 313: Input wrong length " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
error_number = is_sane ( NEON , source , length ) ;
if ( error_number = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 314: Invalid characters in data " ) ;
2016-02-20 12:38:03 +03:00
return error_number ;
}
zeroes = 13 - length ;
for ( i = 0 ; i < zeroes ; i + + )
localstr [ i ] = ' 0 ' ;
strcpy ( localstr + zeroes , ( char * ) source ) ;
for ( i = 12 ; i > = 0 ; i - - ) {
count + = 4 * ctoi ( localstr [ i ] ) ;
if ( i & 1 ) {
count + = 5 * ctoi ( localstr [ i ] ) ;
}
}
localstr [ 13 ] = check_digit ( count ) ;
localstr [ 14 ] = ' \0 ' ;
error_number = interleaved_two_of_five ( symbol , ( unsigned char * ) localstr , strlen ( localstr ) ) ;
ustrcpy ( symbol - > text , ( unsigned char * ) localstr ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}
2016-02-20 12:38:03 +03:00
/* Deutsche Post Identcode */
2019-12-19 03:37:55 +03:00
INTERNAL int dpident ( struct zint_symbol * symbol , unsigned char source [ ] , int length ) {
2016-02-20 12:38:03 +03:00
int i , error_number , zeroes ;
unsigned int count ;
char localstr [ 16 ] ;
count = 0 ;
if ( length > 11 ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 315: Input wrong length " ) ;
2016-02-20 12:38:03 +03:00
return ZINT_ERROR_TOO_LONG ;
}
error_number = is_sane ( NEON , source , length ) ;
if ( error_number = = ZINT_ERROR_INVALID_DATA ) {
2017-07-27 18:01:53 +03:00
strcpy ( symbol - > errtxt , " 316: Invalid characters in data " ) ;
2016-02-20 12:38:03 +03:00
return error_number ;
}
zeroes = 11 - length ;
for ( i = 0 ; i < zeroes ; i + + )
localstr [ i ] = ' 0 ' ;
strcpy ( localstr + zeroes , ( char * ) source ) ;
for ( i = 10 ; i > = 0 ; i - - ) {
count + = 4 * ctoi ( localstr [ i ] ) ;
if ( i & 1 ) {
count + = 5 * ctoi ( localstr [ i ] ) ;
}
}
localstr [ 11 ] = check_digit ( count ) ;
localstr [ 12 ] = ' \0 ' ;
error_number = interleaved_two_of_five ( symbol , ( unsigned char * ) localstr , strlen ( localstr ) ) ;
ustrcpy ( symbol - > text , ( unsigned char * ) localstr ) ;
return error_number ;
2008-07-14 01:15:55 +04:00
}