/* * Copyright 2013 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #import "ZXDataMatrixEdifactEncoder.h" #import "ZXDataMatrixEncoderContext.h" #import "ZXDataMatrixHighLevelEncoder.h" #import "ZXDataMatrixSymbolInfo.h" @implementation ZXDataMatrixEdifactEncoder - (int)encodingMode { return [ZXDataMatrixHighLevelEncoder edifactEncodation]; } - (void)encode:(ZXDataMatrixEncoderContext *)context { //step F NSMutableString *buffer = [NSMutableString string]; while ([context hasMoreCharacters]) { unichar c = [context currentChar]; [self encodeChar:c buffer:buffer]; context.pos++; NSUInteger count = buffer.length; if (count >= 4) { [context writeCodewords:[self encodeToCodewords:buffer startpos:0]]; [buffer deleteCharactersInRange:NSMakeRange(0, 4)]; int newMode = [ZXDataMatrixHighLevelEncoder lookAheadTest:context.message startpos:context.pos currentMode:[self encodingMode]]; if (newMode != [self encodingMode]) { [context signalEncoderChange:[ZXDataMatrixHighLevelEncoder asciiEncodation]]; break; } } } [buffer appendFormat:@"%C", (unichar) 31]; //Unlatch [self handleEOD:context buffer:buffer]; } /** * Handle "end of data" situations * * @param context the encoder context * @param buffer the buffer with the remaining encoded characters */ - (void)handleEOD:(ZXDataMatrixEncoderContext *)context buffer:(NSMutableString *)buffer { @try { NSUInteger count = buffer.length; if (count == 0) { return; //Already finished } if (count == 1) { //Only an unlatch at the end [context updateSymbolInfo]; int available = context.symbolInfo.dataCapacity - context.codewordCount; int remaining = [context remainingCharacters]; if (remaining == 0 && available <= 2) { return; //No unlatch } } if (count > 4) { @throw [NSException exceptionWithName:@"IllegalStateException" reason:@"Count must not exceed 4" userInfo:nil]; } int restChars = (int)count - 1; NSString *encoded = [self encodeToCodewords:buffer startpos:0]; BOOL endOfSymbolReached = ![context hasMoreCharacters]; BOOL restInAscii = endOfSymbolReached && restChars <= 2; if (restChars <= 2) { [context updateSymbolInfoWithLength:context.codewordCount + restChars]; int available = context.symbolInfo.dataCapacity - context.codewordCount; if (available >= 3) { restInAscii = NO; [context updateSymbolInfoWithLength:context.codewordCount + (int)encoded.length]; //available = context.symbolInfo.dataCapacity - context.codewordCount; } } if (restInAscii) { [context resetSymbolInfo]; context.pos -= restChars; } else { [context writeCodewords:encoded]; } } @finally { [context signalEncoderChange:[ZXDataMatrixHighLevelEncoder asciiEncodation]]; } } - (void)encodeChar:(unichar)c buffer:(NSMutableString *)sb { if (c >= ' ' && c <= '?') { [sb appendFormat:@"%C", c]; } else if (c >= '@' && c <= '^') { [sb appendFormat:@"%C", (unichar) (c - 64)]; } else { [ZXDataMatrixHighLevelEncoder illegalCharacter:c]; } } - (NSString *)encodeToCodewords:(NSMutableString *)sb startpos:(int)startPos { int len = (int)sb.length - startPos; if (len == 0) { @throw [NSException exceptionWithName:@"IllegalStateException" reason:@"Buffer must not be empty" userInfo:nil]; } unichar c1 = [sb characterAtIndex:startPos]; unichar c2 = len >= 2 ? [sb characterAtIndex:startPos + 1] : 0; unichar c3 = len >= 3 ? [sb characterAtIndex:startPos + 2] : 0; unichar c4 = len >= 4 ? [sb characterAtIndex:startPos + 3] : 0; int v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4; unichar cw1 = (unichar) ((v >> 16) & 255); unichar cw2 = (unichar) ((v >> 8) & 255); unichar cw3 = (unichar) (v & 255); NSMutableString *res = [NSMutableString stringWithCapacity:3]; [res appendFormat:@"%C", cw1]; if (len >= 2) { [res appendFormat:@"%C", cw2]; } if (len >= 3) { [res appendFormat:@"%C", cw3]; } return [NSString stringWithString:res]; } @end