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 var out, i, len, c; 19 var 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}