Houjie
2025-07-24 52a3ff1bce1417b39f6872d8e8cb378e9c2ccc6f
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
import StringUtils from '../../common/StringUtils';
import StringBuilder from '../../util/StringBuilder';
import { EDIFACT_ENCODATION, ASCII_ENCODATION } from './constants';
import HighLevelEncoder from './HighLevelEncoder';
export class EdifactEncoder {
    getEncodingMode() {
        return EDIFACT_ENCODATION;
    }
    encode(context) {
        // step F
        const buffer = new StringBuilder();
        while (context.hasMoreCharacters()) {
            const c = context.getCurrentChar();
            this.encodeChar(c, buffer);
            context.pos++;
            const count = buffer.length();
            if (count >= 4) {
                context.writeCodewords(this.encodeToCodewords(buffer.toString()));
                const test = buffer.toString().substring(4);
                buffer.setLengthToZero();
                buffer.append(test);
                // buffer.delete(0, 4);
                // for (let i = 0; i < 4; i++) {
                //  buffer.deleteCharAt(i);
                // }
                const newMode = HighLevelEncoder.lookAheadTest(context.getMessage(), context.pos, this.getEncodingMode());
                if (newMode !== this.getEncodingMode()) {
                    // Return to ASCII encodation, which will actually handle latch to new mode
                    context.signalEncoderChange(ASCII_ENCODATION);
                    break;
                }
            }
        }
        buffer.append(StringUtils.getCharAt(31)); // Unlatch
        this.handleEOD(context, buffer);
    }
    /**
     * Handle "end of data" situations
     *
     * @param context the encoder context
     * @param buffer  the buffer with the remaining encoded characters
     */
    handleEOD(context, buffer) {
        try {
            const count = buffer.length();
            if (count === 0) {
                return; // Already finished
            }
            if (count === 1) {
                // Only an unlatch at the end
                context.updateSymbolInfo();
                let available = context.getSymbolInfo().getDataCapacity() -
                    context.getCodewordCount();
                const remaining = context.getRemainingCharacters();
                // The following two lines are a hack inspired by the 'fix' from https://sourceforge.net/p/barcode4j/svn/221/
                if (remaining > available) {
                    context.updateSymbolInfo(context.getCodewordCount() + 1);
                    available =
                        context.getSymbolInfo().getDataCapacity() -
                            context.getCodewordCount();
                }
                if (remaining <= available && available <= 2) {
                    return; // No unlatch
                }
            }
            if (count > 4) {
                throw new Error('Count must not exceed 4');
            }
            const restChars = count - 1;
            const encoded = this.encodeToCodewords(buffer.toString());
            const endOfSymbolReached = !context.hasMoreCharacters();
            let restInAscii = endOfSymbolReached && restChars <= 2;
            if (restChars <= 2) {
                context.updateSymbolInfo(context.getCodewordCount() + restChars);
                const available = context.getSymbolInfo().getDataCapacity() -
                    context.getCodewordCount();
                if (available >= 3) {
                    restInAscii = false;
                    context.updateSymbolInfo(context.getCodewordCount() + encoded.length);
                    // available = context.symbolInfo.dataCapacity - context.getCodewordCount();
                }
            }
            if (restInAscii) {
                context.resetSymbolInfo();
                context.pos -= restChars;
            }
            else {
                context.writeCodewords(encoded);
            }
        }
        finally {
            context.signalEncoderChange(ASCII_ENCODATION);
        }
    }
    encodeChar(c, sb) {
        if (c >= ' '.charCodeAt(0) && c <= '?'.charCodeAt(0)) {
            sb.append(c);
        }
        else if (c >= '@'.charCodeAt(0) && c <= '^'.charCodeAt(0)) {
            sb.append(StringUtils.getCharAt(c - 64));
        }
        else {
            HighLevelEncoder.illegalCharacter(StringUtils.getCharAt(c));
        }
    }
    encodeToCodewords(sb) {
        const len = sb.length;
        if (len === 0) {
            throw new Error('StringBuilder must not be empty');
        }
        const c1 = sb.charAt(0).charCodeAt(0);
        const c2 = len >= 2 ? sb.charAt(1).charCodeAt(0) : 0;
        const c3 = len >= 3 ? sb.charAt(2).charCodeAt(0) : 0;
        const c4 = len >= 4 ? sb.charAt(3).charCodeAt(0) : 0;
        const v = (c1 << 18) + (c2 << 12) + (c3 << 6) + c4;
        const cw1 = (v >> 16) & 255;
        const cw2 = (v >> 8) & 255;
        const cw3 = v & 255;
        const res = new StringBuilder();
        res.append(cw1);
        if (len >= 2) {
            res.append(cw2);
        }
        if (len >= 3) {
            res.append(cw3);
        }
        return res.toString();
    }
}