• 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;
19    let i;
20    let len;
21    let c;
22    let char2;
23    let char3;
24
25    out = '';
26    len = array.length;
27    i = 0;
28    while (i < len) {
29        c = array[i++];
30        switch (c >> 4) {
31            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
32                // 0xxxxxxx
33                out += String.fromCharCode(c);
34                break;
35            case 12: case 13:
36                // 110x xxxx   10xx xxxx
37                char2 = array[i++];
38                out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
39                break;
40            case 14:
41                // 1110 xxxx  10xx xxxx  10xx xxxx
42                char2 = array[i++];
43                char3 = array[i++];
44                out += String.fromCharCode(((c & 0x0F) << 12) |
45                    ((char2 & 0x3F) << 6) |
46                    ((char3 & 0x3F) << 0));
47                break;
48        }
49    }
50
51    return out;
52}
53
54function stringToUint8Array(string, options = { stream: false }) {
55    if (options.stream) {
56        throw new Error(`Failed to encode: the 'stream' option is unsupported.`);
57    }
58    let pos = 0;
59    const len = string.length;
60    let at = 0; // output position
61    let tlen = Math.max(32, len + (len >> 1) + 7); // 1.5x size
62    let target = new Uint8Array((tlen >> 3) << 3); // ... but at 8 byte offset
63
64    while (pos < len) {
65        let value = string.charCodeAt(pos++);
66        let isContinue = false;
67        if (value >= 0xd800 && value <= 0xdbff) {
68            if (pos < len) {// high surrogate
69                const extra = string.charCodeAt(pos);
70                if ((extra & 0xfc00) === 0xdc00) {
71                    ++pos;
72                    value = ((value & 0x3ff) << 10) + (extra & 0x3ff) + 0x10000;
73                }
74            }
75            if (value >= 0xd800 && value <= 0xdbff) {
76                isContinue = true; // drop lone surrogate
77            }
78        }
79
80        if (!isContinue) {
81            // expand the buffer if we couldn't write 4 bytes
82            if (at + 4 > target.length) {
83                tlen += 8; // minimum extra
84                tlen *= (1.0 + (pos / string.length) * 2); // take 2x the remaining
85                tlen = (tlen >> 3) << 3; // 8 byte offset
86
87                target = uint8Array(tlen, target);
88            }
89
90            let calculateResult = calculate(value, target, at);
91            isContinue = calculateResult[0];
92            target = calculateResult[1];
93            at = calculateResult[2];
94        }
95    }
96    return target.slice(0, at);
97}
98
99function calculate(value, target, at) {
100    let isContinue = false;
101    if ((value & 0xffffff80) === 0) { // 1-byte
102        target[at++] = value; // ASCII
103        isContinue = true;
104    } else if ((value & 0xfffff800) === 0) { // 2-byte
105        target[at++] = ((value >> 6) & 0x1f) | 0xc0;
106    } else if ((value & 0xffff0000) === 0) { // 3-byte
107        target[at++] = ((value >> 12) & 0x0f) | 0xe0;
108        target[at++] = ((value >> 6) & 0x3f) | 0x80;
109    } else if ((value & 0xffe00000) === 0) { // 4-byte
110        target[at++] = ((value >> 18) & 0x07) | 0xf0;
111        target[at++] = ((value >> 12) & 0x3f) | 0x80;
112        target[at++] = ((value >> 6) & 0x3f) | 0x80;
113    } else {
114        isContinue = true;
115    }
116    if (!isContinue) {
117        target[at++] = (value & 0x3f) | 0x80;
118    }
119    return [isContinue, target, at];
120}
121
122function uint8Array(tlen, target) {
123    const update = new Uint8Array(tlen);
124    update.set(target);
125    return update;
126}
127
128function readFile(fn) {
129    if (!fs.existsSync(fn)) {
130        return '';
131    }
132    let data = fs.readFileSync(fn);
133    data = utf8ArrayToStr(data);
134    return data;
135}
136function writeFile(fn, str) {
137    let data = stringToUint8Array(str);
138    fs.writeFileSync(fn, data);
139}
140
141module.exports = {
142    readFile,
143    writeFile,
144};