2008-07-14 01:15:55 +04:00
/* auspost.c - Handles Australia Post 4-State Barcode */
/*
libzint - the open source barcode library
2008-11-17 11:47:42 +03:00
Copyright ( C ) 2008 Robin Stuart < robin @ zint . org . uk >
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 :
1. Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright
notice , this list of conditions and the following disclaimer in the
documentation and / or other materials provided with the distribution .
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
without specific prior written permission .
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
OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE .
2008-07-14 01:15:55 +04:00
*/
# define GDSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #"
2012-12-29 22:37:03 +04:00
static const char * AusNTable [ 10 ] = { " 00 " , " 01 " , " 02 " , " 10 " , " 11 " , " 12 " , " 20 " , " 21 " , " 22 " , " 30 " } ;
2008-07-14 01:15:55 +04:00
2012-12-29 22:37:03 +04:00
static const char * AusCTable [ 64 ] = { " 222 " , " 300 " , " 301 " , " 302 " , " 310 " , " 311 " , " 312 " , " 320 " , " 321 " , " 322 " ,
2008-07-14 01:15:55 +04:00
" 000 " , " 001 " , " 002 " , " 010 " , " 011 " , " 012 " , " 020 " , " 021 " , " 022 " , " 100 " , " 101 " , " 102 " , " 110 " ,
" 111 " , " 112 " , " 120 " , " 121 " , " 122 " , " 200 " , " 201 " , " 202 " , " 210 " , " 211 " , " 212 " , " 220 " , " 221 " ,
" 023 " , " 030 " , " 031 " , " 032 " , " 033 " , " 103 " , " 113 " , " 123 " , " 130 " , " 131 " , " 132 " , " 133 " , " 203 " ,
" 213 " , " 223 " , " 230 " , " 231 " , " 232 " , " 233 " , " 303 " , " 313 " , " 323 " , " 330 " , " 331 " , " 332 " , " 333 " ,
" 003 " , " 013 " } ;
2012-12-29 22:37:03 +04:00
static const char * AusBarTable [ 64 ] = { " 000 " , " 001 " , " 002 " , " 003 " , " 010 " , " 011 " , " 012 " , " 013 " , " 020 " , " 021 " ,
2008-07-14 01:15:55 +04:00
" 022 " , " 023 " , " 030 " , " 031 " , " 032 " , " 033 " , " 100 " , " 101 " , " 102 " , " 103 " , " 110 " , " 111 " , " 112 " ,
" 113 " , " 120 " , " 121 " , " 122 " , " 123 " , " 130 " , " 131 " , " 132 " , " 133 " , " 200 " , " 201 " , " 202 " , " 203 " ,
" 210 " , " 211 " , " 212 " , " 213 " , " 220 " , " 221 " , " 222 " , " 223 " , " 230 " , " 231 " , " 232 " , " 233 " , " 300 " ,
" 301 " , " 302 " , " 303 " , " 310 " , " 311 " , " 312 " , " 313 " , " 320 " , " 321 " , " 322 " , " 323 " , " 330 " , " 331 " ,
" 332 " , " 333 " } ;
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include "common.h"
# include "reedsol.h"
2011-03-08 13:16:18 +03:00
static inline char convert_pattern ( char data , int shift )
{
return ( data - ' 0 ' ) < < shift ;
}
2008-07-14 01:15:55 +04:00
void rs_error ( char data_pattern [ ] )
{
/* Adds Reed-Solomon error correction to auspost */
2011-03-08 13:16:18 +03:00
int reader , triple_writer = 0 ;
2008-07-14 01:15:55 +04:00
char triple [ 31 ] , inv_triple [ 31 ] ;
2008-10-03 13:26:27 +04:00
unsigned char result [ 5 ] ;
2008-07-14 01:15:55 +04:00
2011-03-08 13:16:18 +03:00
for ( reader = 2 ; reader < strlen ( data_pattern ) ; reader + = 3 , triple_writer + + )
2008-07-14 01:15:55 +04:00
{
2011-03-08 13:16:18 +03:00
triple [ triple_writer ] = convert_pattern ( data_pattern [ reader ] , 4 )
+ convert_pattern ( data_pattern [ reader + 1 ] , 2 )
+ convert_pattern ( data_pattern [ reader + 2 ] , 0 ) ;
2008-07-14 01:15:55 +04:00
}
for ( reader = 0 ; reader < triple_writer ; reader + + )
{
inv_triple [ reader ] = triple [ ( triple_writer - 1 ) - reader ] ;
}
rs_init_gf ( 0x43 ) ;
rs_init_code ( 4 , 1 ) ;
2008-10-03 13:26:27 +04:00
rs_encode ( triple_writer , ( unsigned char * ) inv_triple , result ) ;
2008-07-14 01:15:55 +04:00
for ( reader = 4 ; reader > 0 ; reader - - )
{
2008-10-05 09:51:58 +04:00
concat ( data_pattern , AusBarTable [ ( int ) result [ reader - 1 ] ] ) ;
2008-07-14 01:15:55 +04:00
}
2008-10-12 22:52:54 +04:00
rs_free ( ) ;
2008-07-14 01:15:55 +04:00
}
2009-09-29 13:45:46 +04:00
int australia_post ( struct zint_symbol * symbol , unsigned char source [ ] , int length )
2008-07-14 01:15:55 +04:00
{
/* Handles Australia Posts's 4 State Codes */
/* Customer Standard Barcode, Barcode 2 or Barcode 3 system determined automatically
( i . e . the FCC doesn ' t need to be specified by the user ) dependent
on the length of the input string */
/* The contents of data_pattern conform to the following standard:
0 = Tracker , Ascender and Descender
1 = Tracker and Ascender
2 = Tracker and Descender
3 = Tracker only */
2009-08-06 22:48:42 +04:00
int error_number , zeroes ;
2009-10-06 23:03:00 +04:00
int writer ;
unsigned int loopey , reader , h ;
2008-07-14 01:15:55 +04:00
char data_pattern [ 200 ] ;
2012-12-29 22:37:03 +04:00
char fcc [ 3 ] = { 0 , 0 } , dpid [ 10 ] ;
2008-10-13 01:05:53 +04:00
char localstr [ 30 ] ;
2008-07-14 01:15:55 +04:00
2008-12-25 00:26:38 +03:00
error_number = 0 ;
2009-08-06 22:48:42 +04:00
strcpy ( localstr , " " ) ;
2012-12-29 22:37:03 +04:00
2008-07-14 01:15:55 +04:00
/* Do all of the length checking first to avoid stack smashing */
if ( symbol - > symbology = = BARCODE_AUSPOST ) {
/* Format control code (FCC) */
2009-09-29 13:45:46 +04:00
switch ( length )
2008-07-14 01:15:55 +04:00
{
2011-03-08 13:16:18 +03:00
case 8 :
strcpy ( fcc , " 11 " ) ;
break ;
case 13 :
strcpy ( fcc , " 59 " ) ;
break ;
case 16 :
strcpy ( fcc , " 59 " ) ;
error_number = is_sane ( NEON , source , length ) ;
break ;
case 18 :
strcpy ( fcc , " 62 " ) ;
break ;
case 23 :
strcpy ( fcc , " 62 " ) ;
error_number = is_sane ( NEON , source , length ) ;
break ;
default :
strcpy ( symbol - > errtxt , " Auspost input is wrong length " ) ;
return ERROR_TOO_LONG ;
2008-07-14 01:15:55 +04:00
break ;
}
2008-12-25 00:26:38 +03:00
if ( error_number = = ERROR_INVALID_DATA ) {
2009-06-01 00:33:54 +04:00
strcpy ( symbol - > errtxt , " Invalid characters in data " ) ;
2008-12-25 00:26:38 +03:00
return error_number ;
2008-07-14 01:15:55 +04:00
}
} else {
2012-12-29 22:37:03 +04:00
if ( length > 8 ) {
2009-06-01 00:33:54 +04:00
strcpy ( symbol - > errtxt , " Auspost input is too long " ) ;
2008-07-14 01:15:55 +04:00
return ERROR_TOO_LONG ;
}
switch ( symbol - > symbology ) {
case BARCODE_AUSREPLY : strcpy ( fcc , " 45 " ) ; break ;
case BARCODE_AUSROUTE : strcpy ( fcc , " 87 " ) ; break ;
case BARCODE_AUSREDIRECT : strcpy ( fcc , " 92 " ) ; break ;
}
2012-12-29 22:37:03 +04:00
2008-10-13 01:05:53 +04:00
/* Add leading zeros as required */
2009-09-29 13:45:46 +04:00
zeroes = 8 - length ;
2009-10-06 23:03:00 +04:00
memset ( localstr , ' 0 ' , zeroes ) ;
localstr [ 8 ] = ' \0 ' ;
2008-07-14 01:15:55 +04:00
}
2008-10-13 01:05:53 +04:00
concat ( localstr , ( char * ) source ) ;
2009-10-06 23:03:00 +04:00
h = strlen ( localstr ) ;
error_number = is_sane ( GDSET , ( unsigned char * ) localstr , h ) ;
2008-12-25 00:26:38 +03:00
if ( error_number = = ERROR_INVALID_DATA ) {
2009-06-01 00:33:54 +04:00
strcpy ( symbol - > errtxt , " Invalid characters in data " ) ;
2008-12-25 00:26:38 +03:00
return error_number ;
2008-07-14 01:15:55 +04:00
}
2012-12-29 22:37:03 +04:00
2008-07-14 01:15:55 +04:00
/* Verifiy that the first 8 characters are numbers */
2009-10-06 23:03:00 +04:00
memcpy ( dpid , localstr , 8 ) ;
2008-07-14 01:15:55 +04:00
dpid [ 8 ] = ' \0 ' ;
2009-10-06 23:03:00 +04:00
error_number = is_sane ( NEON , ( unsigned char * ) dpid , strlen ( dpid ) ) ;
2008-12-25 00:26:38 +03:00
if ( error_number = = ERROR_INVALID_DATA ) {
2009-06-01 00:33:54 +04:00
strcpy ( symbol - > errtxt , " Invalid characters in DPID " ) ;
2008-12-25 00:26:38 +03:00
return error_number ;
2008-07-14 01:15:55 +04:00
}
/* Start character */
2009-10-06 23:03:00 +04:00
strcpy ( data_pattern , " 13 " ) ;
2008-07-14 01:15:55 +04:00
/* Encode the FCC */
for ( reader = 0 ; reader < 2 ; reader + + )
{
2009-10-06 23:03:00 +04:00
lookup ( NEON , AusNTable , fcc [ reader ] , data_pattern ) ;
2008-07-14 01:15:55 +04:00
}
/* printf("AUSPOST FCC: %s ", fcc); */
/* Delivery Point Identifier (DPID) */
for ( reader = 0 ; reader < 8 ; reader + + )
{
2009-10-06 23:03:00 +04:00
lookup ( NEON , AusNTable , dpid [ reader ] , data_pattern ) ;
2008-07-14 01:15:55 +04:00
}
/* Customer Information */
2009-10-06 23:03:00 +04:00
if ( h > 8 )
2008-07-14 01:15:55 +04:00
{
2009-10-06 23:03:00 +04:00
if ( ( h = = 13 ) | | ( h = = 18 ) ) {
for ( reader = 8 ; reader < h ; reader + + ) {
2008-10-13 01:05:53 +04:00
lookup ( GDSET , AusCTable , localstr [ reader ] , data_pattern ) ;
2008-07-14 01:15:55 +04:00
}
}
2011-03-08 13:16:18 +03:00
else if ( ( h = = 16 ) | | ( h = = 23 ) ) {
2009-10-06 23:03:00 +04:00
for ( reader = 8 ; reader < h ; reader + + ) {
lookup ( NEON , AusNTable , localstr [ reader ] , data_pattern ) ;
2008-07-14 01:15:55 +04:00
}
}
}
/* Filler bar */
2009-10-06 23:03:00 +04:00
h = strlen ( data_pattern ) ;
2012-12-29 22:37:03 +04:00
switch ( h )
{
case 22 :
case 37 :
case 52 :
concat ( data_pattern , " 3 " ) ;
break ;
default :
break ;
2008-07-14 01:15:55 +04:00
}
/* Reed Solomon error correction */
rs_error ( data_pattern ) ;
/* Stop character */
concat ( data_pattern , " 13 " ) ;
2012-12-29 22:37:03 +04:00
2008-07-14 01:15:55 +04:00
/* Turn the symbol into a bar pattern ready for plotting */
writer = 0 ;
2009-10-06 23:03:00 +04:00
h = strlen ( data_pattern ) ;
for ( loopey = 0 ; loopey < h ; loopey + + )
2008-07-14 01:15:55 +04:00
{
if ( ( data_pattern [ loopey ] = = ' 1 ' ) | | ( data_pattern [ loopey ] = = ' 0 ' ) )
{
2009-06-01 00:33:54 +04:00
set_module ( symbol , 0 , writer ) ;
2008-07-14 01:15:55 +04:00
}
2009-06-01 00:33:54 +04:00
set_module ( symbol , 1 , writer ) ;
2008-07-14 01:15:55 +04:00
if ( ( data_pattern [ loopey ] = = ' 2 ' ) | | ( data_pattern [ loopey ] = = ' 0 ' ) )
{
2009-06-01 00:33:54 +04:00
set_module ( symbol , 2 , writer ) ;
2008-07-14 01:15:55 +04:00
}
writer + = 2 ;
}
2010-09-12 14:54:47 +04:00
symbol - > row_height [ 0 ] = 3 ;
2008-07-14 01:15:55 +04:00
symbol - > row_height [ 1 ] = 2 ;
2010-09-12 14:54:47 +04:00
symbol - > row_height [ 2 ] = 3 ;
2008-07-14 01:15:55 +04:00
symbol - > rows = 3 ;
symbol - > width = writer - 1 ;
2008-12-25 00:26:38 +03:00
return error_number ;
2008-07-14 01:15:55 +04:00
}