int aztec_text_process()

in Sharing/Src/External/zint-2.4.3/src/backend/aztec.c [69:665]


int aztec_text_process(unsigned char source[], const unsigned int src_len, char binary_string[], int gs1)
{
	int i, j, k, bytes;
	int curtable, newtable, lasttable, chartype, maplength, blocks, debug;
#ifndef _MSC_VER
	int charmap[src_len * 2], typemap[src_len * 2];
	int blockmap[2][src_len];
#else
        int* charmap = (int*)_alloca(src_len * 2 * sizeof(int));
        int* typemap = (int*)_alloca(src_len * 2 * sizeof(int));
        int* blockmap[2];
        blockmap[0] = (int*)_alloca(src_len * sizeof(int));
        blockmap[1] = (int*)_alloca(src_len * sizeof(int));
#endif
	/* Lookup input string in encoding table */
	maplength = 0;
	debug = 0;
	
	for(i = 0; i < src_len; i++) {
		if(gs1 && (i == 0)) {
			/* Add FNC1 to beginning of GS1 messages */
			charmap[maplength] = 0;
			typemap[maplength++] = PUNC;
			charmap[maplength] = 400;
			typemap[maplength++] = PUNC;
		}
		if((gs1) && (source[i] == '[')) {
			/* FNC1 represented by FLG(0) */
			charmap[maplength] = 0;
			typemap[maplength++] = PUNC;
			charmap[maplength] = 400;
			typemap[maplength++] = PUNC;
		} else {
			if(source[i] > 127) {
				charmap[maplength] = source[i];
				typemap[maplength++] = BINARY;
			} else {
				charmap[maplength] = AztecSymbolChar[source[i]];
				typemap[maplength++] = AztecCodeSet[source[i]];
			}
		}
	}

	/* Look for double character encoding possibilities */
	i = 0;
	do{
		if(((charmap[i] == 300) && (charmap[i + 1] == 11)) && ((typemap[i] == PUNC) && (typemap[i + 1] == PUNC))) {
			/* CR LF combination */
			charmap[i] = 2;
			typemap[i] = PUNC;
			mapshorten(charmap, typemap, i, maplength);
			maplength--;
		}

		if(((charmap[i] == 302) && (charmap[i + 1] == 1)) && ((typemap[i] == 24) && (typemap[i + 1] == 23))) {
			/* . SP combination */
			charmap[i] = 3;
			typemap[i] = PUNC;
			mapshorten(charmap, typemap, i, maplength);
			maplength--;
		}

		if(((charmap[i] == 301) && (charmap[i + 1] == 1)) && ((typemap[i] == 24) && (typemap[i + 1] == 23))) {
			/* , SP combination */
			charmap[i] = 4;
			typemap[i] = PUNC;
			mapshorten(charmap, typemap, i, maplength);
			maplength--;
		}

		if(((charmap[i] == 21) && (charmap[i + 1] == 1)) && ((typemap[i] == PUNC) && (typemap[i + 1] == 23))) {
			/* : SP combination */
			charmap[i] = 5;
			typemap[i] = PUNC;
			mapshorten(charmap, typemap, i, maplength);
			maplength--;
		}

		i++;
	}while(i < (maplength - 1));

	/* look for blocks of characters which use the same table */
	blocks = 1;
	blockmap[0][0] = typemap[0];
	blockmap[1][0] = 1;
	for(i = 1; i < maplength; i++) {
		if(typemap[i] == typemap[i - 1]) {
			blockmap[1][blocks - 1]++;
		} else {
			blocks++;
			blockmap[0][blocks - 1] = typemap[i];
			blockmap[1][blocks - 1] = 1;
		}
	}
	
	if(blockmap[0][0] & 1) { blockmap[0][0] = 1; }
	if(blockmap[0][0] & 2) { blockmap[0][0] = 2; }
	if(blockmap[0][0] & 4) { blockmap[0][0] = 4; }
	if(blockmap[0][0] & 8) { blockmap[0][0] = 8; }
	
	if(blocks > 1) {
		/* look for adjacent blocks which can use the same table (left to right search) */
		for(i = 1; i < blocks; i++) {
			if(blockmap[0][i] & blockmap[0][i - 1]) {
				blockmap[0][i] = (blockmap[0][i] & blockmap[0][i - 1]);
			}
		}
		
		if(blockmap[0][blocks - 1] & 1) { blockmap[0][blocks - 1] = 1; }
		if(blockmap[0][blocks - 1] & 2) { blockmap[0][blocks - 1] = 2; }
		if(blockmap[0][blocks - 1] & 4) { blockmap[0][blocks - 1] = 4; }
		if(blockmap[0][blocks - 1] & 8) { blockmap[0][blocks - 1] = 8; }
		
		/* look for adjacent blocks which can use the same table (right to left search) */
		for(i = blocks - 1; i > 0; i--) {
			if(blockmap[0][i] & blockmap[0][i + 1]) {
				blockmap[0][i] = (blockmap[0][i] & blockmap[0][i + 1]);
			}
		}
		
		/* determine the encoding table for characters which do not fit with adjacent blocks */
		for(i = 1; i < blocks; i++) {
			if(blockmap[0][i] & 8) { blockmap[0][i] = 8; }
			if(blockmap[0][i] & 4) { blockmap[0][i] = 4; }
			if(blockmap[0][i] & 2) { blockmap[0][i] = 2; }
			if(blockmap[0][i] & 1) { blockmap[0][i] = 1; }
		}

		/* Combine blocks of the same type */
		i = 0;
		do{
			if(blockmap[0][i] == blockmap[0][i + 1]) {
				blockmap[1][i] += blockmap[1][i + 1];
				for(j = i + 1; j < blocks; j++) {
					blockmap[0][j] = blockmap[0][j + 1];
					blockmap[1][j] = blockmap[1][j + 1];
				}
				blocks--;
			} else {
				i++;
			}
		} while (i < blocks);
	}

	/* Put the adjusted block data back into typemap */
	j = 0;
	for(i = 0; i < blocks; i++) {
		if((blockmap[1][i] < 3) && (blockmap[0][i] != 32)) { /* Shift character(s) needed */
			for(k = 0; k < blockmap[1][i]; k++) {
				typemap[j + k] = blockmap[0][i] + 64;
			}
		} else { /* Latch character (or byte mode) needed */
			for(k = 0; k < blockmap[1][i]; k++) {
				typemap[j + k] = blockmap[0][i];
			}
		}
		j += blockmap[1][i];
	}

	/* Don't shift an initial capital letter */
	if(typemap[0] == 65) { typemap[0] = 1; };

	/* Problem characters (those that appear in different tables with different values) can now be resolved into their tables */
	for(i = 0; i < maplength; i++) {
		if((charmap[i] >= 300) && (charmap[i] < 400)) {
			curtable = typemap[i];
			if(curtable > 64) {
				curtable -= 64;
			}
			switch(charmap[i]) {
				case 300: /* Carriage Return */
					switch(curtable) {
						case PUNC: charmap[i] = 1; break;
						case MIXED: charmap[i] = 14; break;
					}
					break;
				case 301: /* Comma */
					switch(curtable) {
						case PUNC: charmap[i] = 17; break;
						case DIGIT: charmap[i] = 12; break;
					}
					break;
				case 302: /* Full Stop */
					switch(curtable) {
						case PUNC: charmap[i] = 19; break;
						case DIGIT: charmap[i] = 13; break;
					}
					break;
			}
		}
	}
	*binary_string  = '\0';

	curtable = UPPER; /* start with UPPER table */
	lasttable = UPPER;
	for(i = 0; i < maplength; i++) {
		newtable = curtable;
		if((typemap[i] != curtable) && (charmap[i] < 400)) {
			/* Change table */
			if(curtable == BINARY) {
				/* If ending binary mode the current table is the same as when entering binary mode */
				curtable = lasttable;
				newtable = lasttable;
			}
			if(typemap[i] > 64) {
				/* Shift character */
				switch(typemap[i]) {
					case (64 + UPPER): /* To UPPER */
						switch(curtable) {
							case LOWER: /* US */
								concat(binary_string, hexbit[28]);
								if(debug) printf("US ");
								break;
							case MIXED: /* UL */
								concat(binary_string, hexbit[29]);
								if(debug) printf("UL ");
								newtable = UPPER;
								break;
							case PUNC: /* UL */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								newtable = UPPER;
								break;
							case DIGIT: /* US */
								concat(binary_string, pentbit[15]);
								if(debug) printf("US ");
								break;
						}
						break;
					case (64 + LOWER): /* To LOWER */
						switch(curtable) {
							case UPPER: /* LL */
								concat(binary_string, hexbit[28]);
								if(debug) printf("LL ");
								newtable = LOWER;
								break;
							case MIXED: /* LL */
								concat(binary_string, hexbit[28]);
								if(debug) printf("LL ");
								newtable = LOWER;
								break;
							case PUNC: /* UL LL */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[28]);
								if(debug) printf("LL ");
								newtable = LOWER;
								break;
							case DIGIT: /* UL LL */
								concat(binary_string, pentbit[14]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[28]);
								if(debug) printf("LL ");
								newtable = LOWER;
								break;
						}
						break;
					case (64 + MIXED): /* To MIXED */
						switch(curtable) {
							case UPPER: /* ML */
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								newtable = MIXED;
								break;
							case LOWER: /* ML */
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								newtable = MIXED;
								break;
							case PUNC: /* UL ML */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								newtable = MIXED;
								break;
							case DIGIT: /* UL ML */
								concat(binary_string, pentbit[14]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								newtable = MIXED;
								break;
						}
						break;
					case (64 + PUNC): /* To PUNC */
						switch(curtable) {
							case UPPER: /* PS */
								concat(binary_string, hexbit[0]);
								if(debug) printf("PS ");
								break;
							case LOWER: /* PS */
								concat(binary_string, hexbit[0]);
								if(debug) printf("PS ");
								break;
							case MIXED: /* PS */
								concat(binary_string, hexbit[0]);
								if(debug) printf("PS ");
								break;
							case DIGIT: /* PS */
								concat(binary_string, pentbit[0]);
								if(debug) printf("PS ");
								break;
						}
						break;
					case (64 + DIGIT): /* To DIGIT */
						switch(curtable) {
							case UPPER: /* DL */
								concat(binary_string, hexbit[30]);
								if(debug) printf("DL ");
								newtable = DIGIT;
								break;
							case LOWER: /* DL */
								concat(binary_string, hexbit[30]);
								if(debug) printf("DL ");
								newtable = DIGIT;
								break;
							case MIXED: /* UL DL */
								concat(binary_string, hexbit[29]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[30]);
								if(debug) printf("DL ");
								newtable = DIGIT;
								break;
							case PUNC: /* UL DL */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[30]);
								if(debug) printf("DL ");
								newtable = DIGIT;
								break;
						}
						break;
				}
			} else {
				/* Latch character */
				switch(typemap[i]) {
					case UPPER: /* To UPPER */
						switch(curtable) {
							case LOWER: /* ML UL */
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								concat(binary_string, hexbit[29]);
								if(debug) printf("UL ");
								newtable = UPPER;
								break;
							case MIXED: /* UL */
								concat(binary_string, hexbit[29]);
								if(debug) printf("UL ");
								newtable = UPPER;
								break;
							case PUNC: /* UL */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								newtable = UPPER;
								break;
							case DIGIT: /* UL */
								concat(binary_string, pentbit[14]);
								if(debug) printf("UL ");
								newtable = UPPER;
								break;
						}
						break;
					case LOWER: /* To LOWER */
						switch(curtable) {
							case UPPER: /* LL */
								concat(binary_string, hexbit[28]);
								if(debug) printf("LL ");
								newtable = LOWER;
								break;
							case MIXED: /* LL */
								concat(binary_string, hexbit[28]);
								if(debug) printf("LL ");
								newtable = LOWER;
								break;
							case PUNC: /* UL LL */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[28]);
								if(debug) printf("LL ");
								newtable = LOWER;
								break;
							case DIGIT: /* UL LL */
								concat(binary_string, pentbit[14]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[28]);
								if(debug) printf("LL ");
								newtable = LOWER;
								break;
						}
						break;
					case MIXED: /* To MIXED */
						switch(curtable) {
							case UPPER: /* ML */
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								newtable = MIXED;
								break;
							case LOWER: /* ML */
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								newtable = MIXED;
								break;
							case PUNC: /* UL ML */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								newtable = MIXED;
								break;
							case DIGIT: /* UL ML */
								concat(binary_string, pentbit[14]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								newtable = MIXED;
								break;
						}
						break;
					case PUNC: /* To PUNC */
						switch(curtable) {
							case UPPER: /* ML PL */
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								concat(binary_string, hexbit[30]);
								if(debug) printf("PL ");
								newtable = PUNC;
								break;
							case LOWER: /* ML PL */
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								concat(binary_string, hexbit[30]);
								if(debug) printf("PL ");
								newtable = PUNC;
								break;
							case MIXED: /* PL */
								concat(binary_string, hexbit[30]);
								if(debug) printf("PL ");
								newtable = PUNC;
								break;
							case DIGIT: /* UL ML PL */
								concat(binary_string, pentbit[14]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[29]);
								if(debug) printf("ML ");
								concat(binary_string, hexbit[30]);
								if(debug) printf("PL ");
								newtable = PUNC;
								break;
						}
						break;
					case DIGIT: /* To DIGIT */
						switch(curtable) {
							case UPPER: /* DL */
								concat(binary_string, hexbit[30]);
								if(debug) printf("DL ");
								newtable = DIGIT;
								break;
							case LOWER: /* DL */
								concat(binary_string, hexbit[30]);
								if(debug) printf("DL ");
								newtable = DIGIT;
								break;
							case MIXED: /* UL DL */
								concat(binary_string, hexbit[29]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[30]);
								if(debug) printf("DL ");
								newtable = DIGIT;
								break;
							case PUNC: /* UL DL */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[30]);
								if(debug) printf("DL ");
								newtable = DIGIT;
								break;
						}
						break;
					case BINARY: /* To BINARY */
						lasttable = curtable;
						switch(curtable) {
							case UPPER: /* BS */
								concat(binary_string, hexbit[31]);
								if(debug) printf("BS ");
								newtable = BINARY;
								break;
							case LOWER: /* BS */
								concat(binary_string, hexbit[31]);
								if(debug) printf("BS ");
								newtable = BINARY;
								break;
							case MIXED: /* BS */
								concat(binary_string, hexbit[31]);
								if(debug) printf("BS ");
								newtable = BINARY;
								break;
							case PUNC: /* UL BS */
								concat(binary_string, hexbit[31]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[31]);
								if(debug) printf("BS ");
								newtable = BINARY;
								break;
							case DIGIT: /* UL BS */
								concat(binary_string, pentbit[14]);
								if(debug) printf("UL ");
								concat(binary_string, hexbit[31]);
								if(debug) printf("BS ");
								newtable = BINARY;
								break;
						}

						bytes = 0;
						do{
							bytes++;
						}while(typemap[i + (bytes - 1)] == BINARY);
						bytes--;

						if(bytes > 2079) {
							return ZINT_ERROR_TOO_LONG;
						}

						if(bytes > 31) { /* Put 00000 followed by 11-bit number of bytes less 31 */
							int adjusted;

							adjusted = bytes - 31;
							concat(binary_string, "00000");
							if(adjusted & 0x400) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x200) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x100) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x80) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x40) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x20) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x10) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x08) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x04) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x02) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(adjusted & 0x01) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
						} else { /* Put 5-bit number of bytes */
							if(bytes & 0x10) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(bytes & 0x08) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(bytes & 0x04) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(bytes & 0x02) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
							if(bytes & 0x01) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
						}
						if(debug) printf("(%d bytes) ", bytes);

						break;
				}
			}
		}
		/* Add data to the binary string */
		curtable = newtable;
		chartype = typemap[i];
		if(chartype > 64) { chartype -= 64; }
		switch(chartype) {
			case UPPER:
			case LOWER:
			case MIXED:
			case PUNC:
				if(charmap[i] >= 400) {
					concat(binary_string, tribit[charmap[i] - 400]);
					if(debug) printf("FLG(%d) ",charmap[i] - 400);
				} else {
					concat(binary_string, hexbit[charmap[i]]);
					if(!((chartype == PUNC) && (charmap[i] == 0)))
						if(debug) printf("%d ",charmap[i]);
				}
				break;
			case DIGIT:
				concat(binary_string, pentbit[charmap[i]]);
				if(debug) printf("%d ",charmap[i]);
				break;
			case BINARY:
				if(charmap[i] & 0x80) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
				if(charmap[i] & 0x40) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
				if(charmap[i] & 0x20) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
				if(charmap[i] & 0x10) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
				if(charmap[i] & 0x08) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
				if(charmap[i] & 0x04) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
				if(charmap[i] & 0x02) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
				if(charmap[i] & 0x01) { concat(binary_string, "1"); } else { concat(binary_string, "0"); }
				if(debug) printf("%d ",charmap[i]);
				break;
		}

	}

	if(debug) printf("\n");

	if(strlen(binary_string) > 14970) {
		return ZINT_ERROR_TOO_LONG;
	}

	return 0;
}