• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15const fs = require('fs');
16
17function utf8ArrayToStr(array) {
18    let out, i, len, c;
19    let char2, char3;
20
21    out = '';
22    len = array.length;
23    i = 0;
24    while (i < len) {
25        c = array[i++];
26        switch (c >> 4) {
27            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
28                // 0xxxxxxx
29                out += String.fromCharCode(c);
30                break;
31            case 12: case 13:
32                // 110x xxxx   10xx xxxx
33                char2 = array[i++];
34                out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
35                break;
36            case 14:
37                // 1110 xxxx  10xx xxxx  10xx xxxx
38                char2 = array[i++];
39                char3 = array[i++];
40                out += String.fromCharCode(((c & 0x0F) << 12) |
41                    ((char2 & 0x3F) << 6) |
42                    ((char3 & 0x3F) << 0));
43                break;
44        }
45    }
46
47    return out;
48}
49
50function stringToUint8Array(string, options = { stream: false }) {
51    if (options.stream) {
52        throw new Error(`Failed to encode: the 'stream' option is unsupported.`);
53    }
54    let pos = 0;
55    const len = string.length;
56    let at = 0; // output position
57    let tlen = Math.max(32, len + (len >> 1) + 7); // 1.5x size
58    let target = new Uint8Array((tlen >> 3) << 3); // ... but at 8 byte offset
59
60    while (pos < len) {
61        let value = string.charCodeAt(pos++);
62        let isContinue = false;
63        if (value >= 0xd800 && value <= 0xdbff) {
64            if (pos < len) {// high surrogate
65                const extra = string.charCodeAt(pos);
66                if ((extra & 0xfc00) === 0xdc00) {
67                    ++pos;
68                    value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
69                }
70            }
71            if (value >= 0xd800 && value <= 0xdbff) {
72                isContinue = true; // drop lone surrogate
73            }
74        }
75
76        if (!isContinue) {
77            // expand the buffer if we couldn't write 4 bytes
78            if (at + 4 > target.length) {
79                tlen += 8; // minimum extra
80                tlen *= (1.0 + (pos / string.length) * 2); // take 2x the remaining
81                tlen = (tlen >> 3) << 3; // 8 byte offset
82
83                target = uint8Array(tlen, target);
84            }
85
86            let calculateResult = calculate(value, target, at);
87            isContinue = calculateResult[0];
88            target = calculateResult[1];
89            at = calculateResult[2];
90        }
91    }
92    return target.slice(0, at);
93}
94
95function calculate(value, target, at) {
96    let isContinue = false;
97    if ((value & 0xffffff80) === 0) { // 1-byte
98        target[at++] = value; // ASCII
99        isContinue = true;
100    } else if ((value & 0xfffff800) === 0) { // 2-byte
101        target[at++] = ((value >> 6) & 0x1f) | 0xc0;
102    } else if ((value & 0xffff0000) === 0) { // 3-byte
103        target[at++] = ((value >> 12) & 0x0f) | 0xe0;
104        target[at++] = ((value >> 6) & 0x3f) | 0x80;
105    } else if ((value & 0xffe00000) === 0) { // 4-byte
106        target[at++] = ((value >> 18) & 0x07) | 0xf0;
107        target[at++] = ((value >> 12) & 0x3f) | 0x80;
108        target[at++] = ((value >> 6) & 0x3f) | 0x80;
109    } else {
110        isContinue = true;
111    }
112    if (!isContinue) {
113        target[at++] = (value & 0x3f) | 0x80;
114    }
115    return [isContinue, target, at];
116}
117
118function uint8Array(tlen, target) {
119    const update = new Uint8Array(tlen);
120    update.set(target);
121    return update;
122}
123
124function readFile(fn) {
125    if (!fs.existsSync(fn)) {
126        return '';
127    }
128    let data = fs.readFileSync(fn);
129    data = utf8ArrayToStr(data);
130    return data;
131}
132function writeFile(fn, str) {
133    let data = stringToUint8Array(str);
134    fs.writeFileSync(fn, data);
135}
136
137module.exports = {
138    readFile,
139    writeFile,
140};