int gm_encode()

in Sharing/Src/External/zint-2.4.3/src/backend/gridmtx.c [345:742]


int gm_encode(int gbdata[], int length, char binary[], int reader)
{
	/* Create a binary stream representation of the input data.
	   7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters,
	   Mixed numerals and latters, Control characters and 8-bit binary data */
	int sp, current_mode, next_mode, last_mode, glyph = 0;
	int c1, c2, done;
	int p = 0, ppos;
	int numbuf[3], punt = 0;
	int number_pad_posn, debug = 0;
	int byte_count_posn = 0, byte_count = 0;
	int shift, i;

	strcpy(binary, "");

	sp = 0;
	current_mode = 0;
	last_mode = 0;
	number_pad_posn = 0;

	if(reader) {
		concat(binary, "1010"); /* FNC3 - Reader Initialisation */
	}

	do {
		next_mode = seek_forward(gbdata, length, sp, current_mode);

		if(next_mode != current_mode) {
			switch(current_mode) {
				case 0:
					switch(next_mode) {
						case GM_CHINESE: concat(binary, "0001"); break;
						case GM_NUMBER: concat(binary, "0010"); break;
						case GM_LOWER: concat(binary, "0011"); break;
						case GM_UPPER: concat(binary, "0100"); break;
						case GM_MIXED: concat(binary, "0101"); break;
						case GM_BYTE: concat(binary, "0111"); break;
					}
					break;
				case GM_CHINESE:
					switch(next_mode) {
						case GM_NUMBER: concat(binary, "1111111100001"); break; // 8161
						case GM_LOWER: concat(binary, "1111111100010"); break; // 8162
						case GM_UPPER: concat(binary, "1111111100011"); break; // 8163
						case GM_MIXED: concat(binary, "1111111100100"); break; // 8164
						case GM_BYTE: concat(binary, "1111111100101"); break; // 8165
					}
					break;
				case GM_NUMBER:
					/* add numeric block padding value */
					switch(p) {
						case 1: binary[number_pad_posn] = '1'; binary[number_pad_posn + 1] = '0'; break; // 2 pad digits
						case 2: binary[number_pad_posn] = '0'; binary[number_pad_posn + 1] = '1'; break; // 1 pad digit
						case 3: binary[number_pad_posn] = '0'; binary[number_pad_posn + 1] = '0'; break; // 0 pad digits
					}
					switch(next_mode) {
						case GM_CHINESE: concat(binary, "1111111011"); break; // 1019
						case GM_LOWER: concat(binary, "1111111100"); break; // 1020
						case GM_UPPER: concat(binary, "1111111101"); break; // 1021
						case GM_MIXED: concat(binary, "1111111110"); break; // 1022
						case GM_BYTE: concat(binary, "1111111111"); break; // 1023
					}
					break;
				case GM_LOWER:
				case GM_UPPER:
					switch(next_mode) {
						case GM_CHINESE: concat(binary, "11100"); break; // 28
						case GM_NUMBER: concat(binary, "11101"); break; // 29
						case GM_LOWER:
						case GM_UPPER: concat(binary, "11110"); break; // 30
						case GM_MIXED: concat(binary, "1111100"); break; // 124
						case GM_BYTE: concat(binary, "1111110"); break; // 126
					}
					break;
				case GM_MIXED:
					switch(next_mode) {
						case GM_CHINESE: concat(binary, "1111110001"); break; // 1009
						case GM_NUMBER: concat(binary, "1111110010"); break; // 1010
						case GM_LOWER: concat(binary, "1111110011"); break; // 1011
						case GM_UPPER: concat(binary, "1111110100"); break; // 1012
						case GM_BYTE: concat(binary, "1111110111"); break; // 1015
					}
					break;
				case GM_BYTE:
					/* add byte block length indicator */
					add_byte_count(binary, byte_count_posn, byte_count);
					byte_count = 0;
					switch(next_mode) {
						case GM_CHINESE: concat(binary, "0001"); break; // 1
						case GM_NUMBER: concat(binary, "0010"); break; // 2
						case GM_LOWER: concat(binary, "0011"); break; // 3
						case GM_UPPER: concat(binary, "0100"); break; // 4
						case GM_MIXED: concat(binary, "0101"); break; // 5
					}
					break;
			}
			if(debug) {
				switch(next_mode) {
					case GM_CHINESE: printf("CHIN "); break;
					case GM_NUMBER: printf("NUMB "); break;
					case GM_LOWER: printf("LOWR "); break;
					case GM_UPPER: printf("UPPR "); break;
					case GM_MIXED: printf("MIXD "); break;
					case GM_BYTE: printf("BYTE "); break;
				}
			}
		}
		last_mode = current_mode;
		current_mode = next_mode;

		switch(current_mode) {
			case GM_CHINESE: 
				done = 0;
				if(gbdata[sp] > 0xff) {
					/* GB2312 character */
					c1 = (gbdata[sp] & 0xff00) >> 8;
					c2 = gbdata[sp] & 0xff;

					if((c1 >= 0xa0) && (c1 <= 0xa9)) {
						glyph = (0x60 * (c1 - 0xa1)) + (c2 - 0xa0);
					}
					if((c1 >= 0xb0) && (c1 <= 0xf7)) {
						glyph = (0x60 * (c1 - 0xb0 + 9)) + (c2  - 0xa0);
					}
					done = 1;
				}
				if(!(done)) {
					if(sp != (length - 1)) {
						if((gbdata[sp] == 0x13) && (gbdata[sp + 1] == 0x10)) {
							/* End of Line */
							glyph = 7776;
							sp++;
						}
						done = 1;
					}
				}
				if(!(done)) {
					if(sp != (length - 1)) {
						if(((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) &&
							((gbdata[sp + 1] >= '0') && (gbdata[sp + 1] <= '9'))) {
							/* Two digits */
							glyph = 8033 + (10 * (gbdata[sp] - '0')) + (gbdata[sp + 1] - '0');
							sp++;
						}
					}
				}
				if(!(done)) {
					/* Byte value */
					glyph = 7777 + gbdata[sp];
				}

				if(debug) { printf("[%d] ", glyph); }
				
				if(glyph & 0x1000) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x800) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x400) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x200) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x100) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x80) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x40) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x20) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x10) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x08) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x04) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x02) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x01) { concat(binary, "1"); } else { concat(binary, "0"); }
				sp++;
				break;

			case GM_NUMBER:
				if(last_mode != current_mode) {
					/* Reserve a space for numeric digit padding value (2 bits) */
					number_pad_posn = strlen(binary);
					concat(binary, "XX");
				}
				p = 0;
				ppos = -1;

				/* Numeric compression can also include certain combinations of
				   non-numeric character */

				numbuf[0] = '0';
				numbuf[1] = '0';
				numbuf[2] = '0';
				do {
					if((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) {
						numbuf[p] = gbdata[sp];
						sp++;
						p++;
					}
					switch(gbdata[sp]) {
						case ' ':
						case '+':
						case '-':
						case '.':
						case ',':
							punt = gbdata[sp];
							sp++;
							ppos = p;
							break;
					}
					if(sp < (length - 1)) {
						if((gbdata[sp] == 0x13) && (gbdata[sp + 1] == 0x10)) {
							/* <end of line> */
							punt = gbdata[sp];
							sp += 2;
							ppos = p;
						}
					}
				} while ((p < 3) && (sp < length));

				if(ppos != -1) {
					switch(punt) {
						case ' ': glyph = 0; break;
						case '+': glyph = 3; break;
						case '-': glyph = 6; break;
						case '.': glyph = 9; break;
						case ',': glyph = 12; break;
						case 0x13: glyph = 15; break;
					}
					glyph += ppos;
					glyph += 1000;

					if(debug) { printf("[%d] ", glyph); }
					
					if(glyph & 0x200) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x100) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x80) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x40) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x20) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x10) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x08) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x04) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x02) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x01) { concat(binary, "1"); } else { concat(binary, "0"); }
				}

				glyph = (100 * (numbuf[0] - '0')) + (10 * (numbuf[1] - '0')) + (numbuf[2] - '0');
				if(debug) { printf("[%d] ", glyph); }
				
				if(glyph & 0x200) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x100) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x80) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x40) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x20) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x10) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x08) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x04) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x02) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x01) { concat(binary, "1"); } else { concat(binary, "0"); }
				break;

			case GM_BYTE:
				if(last_mode != current_mode) {
					/* Reserve space for byte block length indicator (9 bits) */
					byte_count_posn = strlen(binary);
					concat(binary, "LLLLLLLLL");
				}
				if(byte_count == 512) {
					/* Maximum byte block size is 512 bytes. If longer is needed then start a new block */
					add_byte_count(binary, byte_count_posn, byte_count);
					concat(binary, "0111");
					byte_count_posn = strlen(binary);
					concat(binary, "LLLLLLLLL");
					byte_count = 0;
				}

				glyph = gbdata[sp];
				if(debug) { printf("[%d] ", glyph); }
				if(glyph & 0x80) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x40) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x20) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x10) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x08) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x04) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x02) { concat(binary, "1"); } else { concat(binary, "0"); }
				if(glyph & 0x01) { concat(binary, "1"); } else { concat(binary, "0"); }
				sp++;
				byte_count++;
				break;

			case GM_MIXED:
				shift = 1;
				if((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) { shift = 0; }
				if((gbdata[sp] >= 'A') && (gbdata[sp] <= 'Z')) { shift = 0; }
				if((gbdata[sp] >= 'a') && (gbdata[sp] <= 'z')) { shift = 0; }
				if(gbdata[sp] == ' ') { shift = 0; }

				if(shift == 0) {
					/* Mixed Mode character */
					glyph = posn(EUROPIUM, gbdata[sp]);
					if(debug) { printf("[%d] ", glyph); }
					
					if(glyph & 0x20) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x10) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x08) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x04) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x02) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x01) { concat(binary, "1"); } else { concat(binary, "0"); }
				} else {
					/* Shift Mode character */
					concat(binary, "1111110110"); /* 1014 - shift indicator */
					add_shift_char(binary, gbdata[sp]);
				}

				sp++;
				break;

			case GM_UPPER:
				shift = 1;
				if((gbdata[sp] >= 'A') && (gbdata[sp] <= 'Z')) { shift = 0; }
				if(gbdata[sp] == ' ') { shift = 0; }

				if(shift == 0) {
					/* Upper Case character */
					glyph = posn("ABCDEFGHIJKLMNOPQRSTUVWXYZ ", gbdata[sp]);
					if(debug) { printf("[%d] ", glyph); }
					
					if(glyph & 0x10) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x08) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x04) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x02) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x01) { concat(binary, "1"); } else { concat(binary, "0"); }
				} else {
					/* Shift Mode character */
					concat(binary, "1111101"); /* 127 - shift indicator */
					add_shift_char(binary, gbdata[sp]);
				}

				sp++;
				break;
				
			case GM_LOWER: 
				shift = 1;
				if((gbdata[sp] >= 'a') && (gbdata[sp] <= 'z')) { shift = 0; }
				if(gbdata[sp] == ' ') { shift = 0; }

				if(shift == 0) {
					/* Lower Case character */
					glyph = posn("abcdefghijklmnopqrstuvwxyz ", gbdata[sp]);
					if(debug) { printf("[%d] ", glyph); }
					
					if(glyph & 0x10) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x08) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x04) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x02) { concat(binary, "1"); } else { concat(binary, "0"); }
					if(glyph & 0x01) { concat(binary, "1"); } else { concat(binary, "0"); }
				} else {
					/* Shift Mode character */
					concat(binary, "1111101"); /* 127 - shift indicator */
					add_shift_char(binary, gbdata[sp]);
				}

				sp++;
				break;
		}
		if(strlen(binary) > 9191) {
			return ZINT_ERROR_TOO_LONG;
		}

	} while(sp < length);

	if(current_mode == GM_NUMBER) {
		/* add numeric block padding value */
		switch(p) {
			case 1: binary[number_pad_posn] = '1'; binary[number_pad_posn + 1] = '0'; break; // 2 pad digits
			case 2: binary[number_pad_posn] = '0'; binary[number_pad_posn + 1] = '1'; break; // 1 pad digit
			case 3: binary[number_pad_posn] = '0'; binary[number_pad_posn + 1] = '0'; break; // 0 pad digits
		}
	}

	if(current_mode == GM_BYTE) {
		/* Add byte block length indicator */
		add_byte_count(binary, byte_count_posn, byte_count);
	}

	/* Add "end of data" character */
	switch(current_mode) {
		case GM_CHINESE: concat(binary, "1111111100000"); break; // 8160
		case GM_NUMBER: concat(binary, "1111111010"); break; // 1018
		case GM_LOWER:
		case GM_UPPER: concat(binary, "11011"); break; // 27
		case GM_MIXED: concat(binary, "1111110000"); break; // 1008
		case GM_BYTE: concat(binary, "0000"); break; // 0
	}

	/* Add padding bits if required */
	p = 7 - (strlen(binary) % 7);
	if(p == 7) { p = 0; }
	for(i = 0; i < p; i++) {
		concat(binary, "0");
	}

	if(strlen(binary) > 9191) {
		return ZINT_ERROR_TOO_LONG;
	}
	return 0;
}