JLChen
2021-10-28 e96683081abd5c1a94608dd33d092d8f45371cd6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
 * 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