@ddunigma/node 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENCE +9 -0
- package/README.md +23 -0
- package/dist/cjs/index.js +158 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/test/test1.d.ts +1 -0
- package/dist/cjs/test/test1.js +44 -0
- package/dist/index.d.ts +24 -0
- package/dist/mjs/index.js +166 -0
- package/dist/mjs/package.json +3 -0
- package/dist/mjs/test/test1.d.ts +1 -0
- package/dist/mjs/test/test1.js +42 -0
- package/package.json +27 -0
package/LICENCE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Copyright 2025 i3l3
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
4
|
+
|
|
5
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
6
|
+
|
|
7
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
8
|
+
|
|
9
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
## ddunigma-node
|
|
2
|
+
|
|
3
|
+
### Overview
|
|
4
|
+
Node.js implementation of [ddunigma](https://github.com/i3l3/ddunigma) (Python original)
|
|
5
|
+
|
|
6
|
+
### Credits
|
|
7
|
+
- Original Python Implementation by:
|
|
8
|
+
- [@i3ls](https://github.com/i3l3)
|
|
9
|
+
- [@gunu3371](https://github.com/gunu3371)
|
|
10
|
+
- Original Repository: [ddunigma](https://github.com/i3l3/ddunigma)
|
|
11
|
+
|
|
12
|
+
### Usage
|
|
13
|
+
```js
|
|
14
|
+
import { Ddu64 } from 'ddunigma-node'
|
|
15
|
+
|
|
16
|
+
const ddu64 = new Ddu64(); //default encode utf-8
|
|
17
|
+
|
|
18
|
+
const answer = "뜌땨어 고수가 될거야!"
|
|
19
|
+
const encoded = ddu64.encode(answer);
|
|
20
|
+
console.log(encoded);
|
|
21
|
+
const decoded = ddu64.decode(encoded);
|
|
22
|
+
console.log(decoded);
|
|
23
|
+
```
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Ddu64 = void 0;
|
|
4
|
+
class Ddu64 {
|
|
5
|
+
constructor(dduChar, paddingChar) {
|
|
6
|
+
this.dduCharKr = ["뜌", "땨", "이", "우", "야", "!", "?", "."];
|
|
7
|
+
this.paddingCharKr = "뭐";
|
|
8
|
+
this.defaultEncoding = "utf-8";
|
|
9
|
+
this.dduChar = dduChar || this.dduCharKr;
|
|
10
|
+
this.paddingChar = paddingChar || this.paddingCharKr;
|
|
11
|
+
this.bitLengthMap = new Map();
|
|
12
|
+
this.binaryLookup = new Array(256);
|
|
13
|
+
this.dduBinaryLookup = new Map();
|
|
14
|
+
this.dduBinaryLookupKr = new Map();
|
|
15
|
+
this.paddingRegex = new Map();
|
|
16
|
+
for (let i = 0; i < 256; i++) {
|
|
17
|
+
this.binaryLookup[i] = i.toString(2).padStart(8, '0');
|
|
18
|
+
}
|
|
19
|
+
this.dduChar.forEach((char, index) => {
|
|
20
|
+
this.dduBinaryLookup.set(char, index);
|
|
21
|
+
});
|
|
22
|
+
this.dduCharKr.forEach((char, index) => {
|
|
23
|
+
this.dduBinaryLookupKr.set(char, index);
|
|
24
|
+
});
|
|
25
|
+
this.paddingRegex.set('default', new RegExp(this.paddingChar, "g"));
|
|
26
|
+
this.paddingRegex.set('KR', new RegExp(this.paddingCharKr, "g"));
|
|
27
|
+
}
|
|
28
|
+
getLargestPowerOfTwo(n) {
|
|
29
|
+
let power = Math.floor(Math.log2(n));
|
|
30
|
+
return Math.pow(2, power);
|
|
31
|
+
}
|
|
32
|
+
getBitLength(setLength) {
|
|
33
|
+
let cached = this.bitLengthMap.get(setLength);
|
|
34
|
+
if (cached === undefined) {
|
|
35
|
+
cached = Math.ceil(Math.log2(setLength));
|
|
36
|
+
this.bitLengthMap.set(setLength, cached);
|
|
37
|
+
}
|
|
38
|
+
return cached;
|
|
39
|
+
}
|
|
40
|
+
*splitString(s, length) {
|
|
41
|
+
const len = s.length;
|
|
42
|
+
for (let i = 0; i < len; i += length) {
|
|
43
|
+
yield s.slice(i, Math.min(i + length, len));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
getSelectedSets(option) {
|
|
47
|
+
if (option === "KR") {
|
|
48
|
+
return {
|
|
49
|
+
dduSet: this.dduCharKr,
|
|
50
|
+
padChar: this.paddingCharKr,
|
|
51
|
+
dduLength: this.dduCharKr.length,
|
|
52
|
+
bitLength: this.getBitLength(this.dduCharKr.length),
|
|
53
|
+
lookupTable: this.dduBinaryLookupKr,
|
|
54
|
+
paddingRegExp: this.paddingRegex.get('KR')
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
dduSet: this.dduChar,
|
|
59
|
+
padChar: this.paddingChar,
|
|
60
|
+
dduLength: this.dduChar.length,
|
|
61
|
+
bitLength: this.getBitLength(this.dduChar.length),
|
|
62
|
+
lookupTable: this.dduBinaryLookup,
|
|
63
|
+
paddingRegExp: this.paddingRegex.get('default')
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
getSelectedSets64(option) {
|
|
67
|
+
const baseSet = this.getSelectedSets(option);
|
|
68
|
+
const powerOfTwoLength = this.getLargestPowerOfTwo(baseSet.dduSet.length);
|
|
69
|
+
return Object.assign(Object.assign({}, baseSet), { dduSet: baseSet.dduSet.slice(0, powerOfTwoLength), dduLength: powerOfTwoLength, bitLength: Math.log2(powerOfTwoLength) });
|
|
70
|
+
}
|
|
71
|
+
bufferToDduBinary(input, bitLength) {
|
|
72
|
+
const bufferLength = input.length;
|
|
73
|
+
let encodedBin = '';
|
|
74
|
+
for (let i = 0; i < bufferLength; i++) {
|
|
75
|
+
encodedBin += this.binaryLookup[input[i]];
|
|
76
|
+
}
|
|
77
|
+
const dduBinary = Array.from(this.splitString(encodedBin, bitLength));
|
|
78
|
+
const padding = bitLength - dduBinary[dduBinary.length - 1].length;
|
|
79
|
+
if (padding > 0) {
|
|
80
|
+
dduBinary[dduBinary.length - 1] += '0'.repeat(padding);
|
|
81
|
+
}
|
|
82
|
+
return { dduBinary, padding };
|
|
83
|
+
}
|
|
84
|
+
dduBinaryToBuffer(decodedBin, paddingCount) {
|
|
85
|
+
const paddingBits = paddingCount * 2;
|
|
86
|
+
if (paddingBits > 0) {
|
|
87
|
+
decodedBin = decodedBin.slice(0, -paddingBits);
|
|
88
|
+
}
|
|
89
|
+
const chunkCount = Math.floor(decodedBin.length / 8);
|
|
90
|
+
const buffer = new Array(chunkCount);
|
|
91
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
92
|
+
const start = i * 8;
|
|
93
|
+
buffer[i] = parseInt(decodedBin.slice(start, start + 8), 2);
|
|
94
|
+
}
|
|
95
|
+
return buffer;
|
|
96
|
+
}
|
|
97
|
+
encode(input, option = "default", encoding = this.defaultEncoding) {
|
|
98
|
+
const bufferInput = typeof input === 'string' ? Buffer.from(input, encoding) : input;
|
|
99
|
+
const { dduSet, padChar, dduLength, bitLength } = this.getSelectedSets(option);
|
|
100
|
+
const { dduBinary, padding } = this.bufferToDduBinary(bufferInput, bitLength);
|
|
101
|
+
let resultString = "";
|
|
102
|
+
for (const char of dduBinary) {
|
|
103
|
+
const charInt = parseInt(char, 2);
|
|
104
|
+
const quotient = Math.floor(charInt / dduLength);
|
|
105
|
+
const remainder = charInt % dduLength;
|
|
106
|
+
resultString += dduSet[quotient] + dduSet[remainder];
|
|
107
|
+
}
|
|
108
|
+
if (padding > 0) {
|
|
109
|
+
return resultString + padChar.repeat(Math.floor(padding / 2));
|
|
110
|
+
}
|
|
111
|
+
return resultString;
|
|
112
|
+
}
|
|
113
|
+
encode64(input, option = "default", encoding = this.defaultEncoding) {
|
|
114
|
+
const bufferInput = typeof input === 'string' ? Buffer.from(input, encoding) : input;
|
|
115
|
+
const { dduSet, padChar, bitLength } = this.getSelectedSets64(option);
|
|
116
|
+
const { dduBinary, padding } = this.bufferToDduBinary(bufferInput, bitLength);
|
|
117
|
+
let resultString = "";
|
|
118
|
+
for (const char of dduBinary) {
|
|
119
|
+
const charInt = parseInt(char, 2);
|
|
120
|
+
resultString += dduSet[charInt];
|
|
121
|
+
}
|
|
122
|
+
if (padding > 0) {
|
|
123
|
+
return resultString + padChar.repeat(Math.floor(padding / 2));
|
|
124
|
+
}
|
|
125
|
+
return resultString;
|
|
126
|
+
}
|
|
127
|
+
decode(input, option = "default", encoding = this.defaultEncoding) {
|
|
128
|
+
const { dduSet, dduLength, bitLength, lookupTable, paddingRegExp } = this.getSelectedSets(option);
|
|
129
|
+
const paddingCount = (input.match(paddingRegExp) || []).length;
|
|
130
|
+
input = input.replace(paddingRegExp, '');
|
|
131
|
+
let dduBinary = "";
|
|
132
|
+
for (let i = 0; i < input.length; i += 2) {
|
|
133
|
+
const firstIndex = lookupTable.get(input[i]);
|
|
134
|
+
const secondIndex = lookupTable.get(input[i + 1]);
|
|
135
|
+
if (firstIndex === undefined || secondIndex === undefined)
|
|
136
|
+
continue;
|
|
137
|
+
const value = firstIndex * dduLength + secondIndex;
|
|
138
|
+
dduBinary += value.toString(2).padStart(bitLength, '0');
|
|
139
|
+
}
|
|
140
|
+
const decoded = this.dduBinaryToBuffer(dduBinary, paddingCount);
|
|
141
|
+
return Buffer.from(decoded).toString(encoding);
|
|
142
|
+
}
|
|
143
|
+
decode64(input, option = "default", encoding = this.defaultEncoding) {
|
|
144
|
+
const { dduSet, bitLength, lookupTable, paddingRegExp } = this.getSelectedSets64(option);
|
|
145
|
+
const paddingCount = (input.match(paddingRegExp) || []).length;
|
|
146
|
+
input = input.replace(paddingRegExp, '');
|
|
147
|
+
let dduBinary = '';
|
|
148
|
+
for (let i = 0; i < input.length; i++) {
|
|
149
|
+
const charIndex = lookupTable.get(input[i]);
|
|
150
|
+
if (charIndex === undefined)
|
|
151
|
+
continue;
|
|
152
|
+
dduBinary += charIndex.toString(2).padStart(bitLength, '0');
|
|
153
|
+
}
|
|
154
|
+
const decoded = this.dduBinaryToBuffer(dduBinary, paddingCount);
|
|
155
|
+
return Buffer.from(decoded).toString(encoding);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.Ddu64 = Ddu64;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const __1 = require("..");
|
|
4
|
+
const koreanChars = [
|
|
5
|
+
// 기본 자음+모음 조합
|
|
6
|
+
"가", "나", "다", "라", "마", "바", "사", "아", "자", "차", "카", "타", "파", "하",
|
|
7
|
+
"개", "내", "대", "래", "매", "배", "새", "애", "재", "채", "캐", "태", "패", "해",
|
|
8
|
+
"고", "노", "도", "로", "모", "보", "소", "오", "조", "초", "코", "토", "포", "호",
|
|
9
|
+
"구", "누", "두", "루", "무", "부", "수", "우", "주", "추", "쿠", "투", "푸", "후",
|
|
10
|
+
"그", "느", "드", "르", "므", "브", "스", "으", "즈", "츠", "크", "트", "프", "흐",
|
|
11
|
+
"기", "니", "디", "리", "미", "비", "시", "이", "지", "치", "키", "티", "피", "히",
|
|
12
|
+
"게", "네", "데", "레", "메", "베", "세", "에", "제", "체", "케", "테", "페", "헤",
|
|
13
|
+
"겨", "녀", "더", "려", "며", "벼", "셔", "여", "져", "쳐", "켜", "텨", "펴", "혀",
|
|
14
|
+
"교", "뇨", "됴", "료", "묘", "뵤", "쇼", "요", "죠", "쵸", "쿄", "툐", "표", "효",
|
|
15
|
+
"규", "뉴", "듀", "류", "뮤", "뷰", "슈", "유", "쥬", "츄", "큐", "튜", "퓨", "휴",
|
|
16
|
+
// 받침 있는 조합
|
|
17
|
+
"각", "낙", "닥", "락", "막", "박", "삭", "악", "작", "착", "칵", "탁", "팍", "학",
|
|
18
|
+
"갑", "납", "답", "랍", "맙", "밥", "삽", "압", "잡", "찹", "캅", "탑", "팝", "합",
|
|
19
|
+
"곡", "녹", "독", "록", "목", "복", "속", "옥", "족", "촉", "콕", "톡", "폭", "혹",
|
|
20
|
+
"국", "눅", "둑", "룩", "묵", "북", "숙", "욱", "죽", "축", "쿡", "툭", "푹", "훅",
|
|
21
|
+
"극", "늑", "득", "륵", "믁", "븍", "슥", "윽", "즉", "츰", "큭", "특", "픅", "흑",
|
|
22
|
+
"금", "늠", "듬", "름", "뭄", "붐", "숨", "음", "줌", "춤", "큼", "틈", "품", "흠",
|
|
23
|
+
"갈", "날", "달", "랄", "말", "발", "살", "알", "잘", "찰", "칼", "탈", "팔", "할",
|
|
24
|
+
"감", "남", "담", "람", "맘", "밤", "샘", "암", "잠", "참", "캄", "탐", "팜", "함",
|
|
25
|
+
"건", "넌", "던", "런", '먼'
|
|
26
|
+
]; //129
|
|
27
|
+
const ddu64 = new __1.Ddu64(["D", "d", "U", "u", "T", "t", "A", "a"], "응");
|
|
28
|
+
const answer = "안녕 나 안보고싶었어?12";
|
|
29
|
+
const encoded = ddu64.encode64(answer);
|
|
30
|
+
console.log(encoded);
|
|
31
|
+
const decoded = ddu64.decode64(encoded);
|
|
32
|
+
console.log(decoded);
|
|
33
|
+
console.log("=-==");
|
|
34
|
+
const encoded_eng = ddu64.encode(answer, "KR");
|
|
35
|
+
console.log(encoded_eng);
|
|
36
|
+
const decoded_eng = ddu64.decode(encoded_eng, "KR");
|
|
37
|
+
console.log(decoded_eng);
|
|
38
|
+
console.log("=-==");
|
|
39
|
+
const ddu64_other = new __1.Ddu64(koreanChars, "즁");
|
|
40
|
+
const answer2 = "안녕나안보고싶었어?스스로칭찬하려니까부담되는걸?하지만기록은완성해야하니까어쩔수없지~엘리시아는상냥하고,친근하고,귀엽고,똑똑하고아름다운소녀야.그녀의초대를거절하거나그녀를냉정하게대할수있는사람은없어.전설속의엘프처럼모든이의마음을사로잡고13명의영웅을이곳에모았으면서첫번째자리를양보하는겸손함까지...영웅들에게엘리시아는가장믿음직스럽고사랑받는동료야.너희도그렇게생각하지?1";
|
|
41
|
+
const encoded2 = ddu64_other.encode64(answer2);
|
|
42
|
+
console.log(encoded2);
|
|
43
|
+
const decoded2 = ddu64_other.decode64(encoded2);
|
|
44
|
+
console.log(decoded2);
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare class Ddu64 {
|
|
2
|
+
private readonly dduChar;
|
|
3
|
+
private readonly paddingChar;
|
|
4
|
+
private readonly dduCharKr;
|
|
5
|
+
private readonly paddingCharKr;
|
|
6
|
+
private readonly defaultEncoding;
|
|
7
|
+
private readonly bitLengthMap;
|
|
8
|
+
private readonly binaryLookup;
|
|
9
|
+
private readonly dduBinaryLookup;
|
|
10
|
+
private readonly dduBinaryLookupKr;
|
|
11
|
+
private readonly paddingRegex;
|
|
12
|
+
constructor(dduChar?: string[], paddingChar?: string);
|
|
13
|
+
private getLargestPowerOfTwo;
|
|
14
|
+
private getBitLength;
|
|
15
|
+
private splitString;
|
|
16
|
+
private getSelectedSets;
|
|
17
|
+
private getSelectedSets64;
|
|
18
|
+
private bufferToDduBinary;
|
|
19
|
+
private dduBinaryToBuffer;
|
|
20
|
+
encode(input: Buffer | string, option?: string, encoding?: BufferEncoding): string;
|
|
21
|
+
encode64(input: Buffer | string, option?: string, encoding?: BufferEncoding): string;
|
|
22
|
+
decode(input: string, option?: string, encoding?: BufferEncoding): string;
|
|
23
|
+
decode64(input: string, option?: string, encoding?: BufferEncoding): string;
|
|
24
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
export class Ddu64 {
|
|
2
|
+
dduChar;
|
|
3
|
+
paddingChar;
|
|
4
|
+
dduCharKr = ["뜌", "땨", "이", "우", "야", "!", "?", "."];
|
|
5
|
+
paddingCharKr = "뭐";
|
|
6
|
+
defaultEncoding = "utf-8";
|
|
7
|
+
bitLengthMap;
|
|
8
|
+
binaryLookup;
|
|
9
|
+
dduBinaryLookup;
|
|
10
|
+
dduBinaryLookupKr;
|
|
11
|
+
paddingRegex;
|
|
12
|
+
constructor(dduChar, paddingChar) {
|
|
13
|
+
this.dduChar = dduChar || this.dduCharKr;
|
|
14
|
+
this.paddingChar = paddingChar || this.paddingCharKr;
|
|
15
|
+
this.bitLengthMap = new Map();
|
|
16
|
+
this.binaryLookup = new Array(256);
|
|
17
|
+
this.dduBinaryLookup = new Map();
|
|
18
|
+
this.dduBinaryLookupKr = new Map();
|
|
19
|
+
this.paddingRegex = new Map();
|
|
20
|
+
for (let i = 0; i < 256; i++) {
|
|
21
|
+
this.binaryLookup[i] = i.toString(2).padStart(8, '0');
|
|
22
|
+
}
|
|
23
|
+
this.dduChar.forEach((char, index) => {
|
|
24
|
+
this.dduBinaryLookup.set(char, index);
|
|
25
|
+
});
|
|
26
|
+
this.dduCharKr.forEach((char, index) => {
|
|
27
|
+
this.dduBinaryLookupKr.set(char, index);
|
|
28
|
+
});
|
|
29
|
+
this.paddingRegex.set('default', new RegExp(this.paddingChar, "g"));
|
|
30
|
+
this.paddingRegex.set('KR', new RegExp(this.paddingCharKr, "g"));
|
|
31
|
+
}
|
|
32
|
+
getLargestPowerOfTwo(n) {
|
|
33
|
+
let power = Math.floor(Math.log2(n));
|
|
34
|
+
return 2 ** power;
|
|
35
|
+
}
|
|
36
|
+
getBitLength(setLength) {
|
|
37
|
+
let cached = this.bitLengthMap.get(setLength);
|
|
38
|
+
if (cached === undefined) {
|
|
39
|
+
cached = Math.ceil(Math.log2(setLength));
|
|
40
|
+
this.bitLengthMap.set(setLength, cached);
|
|
41
|
+
}
|
|
42
|
+
return cached;
|
|
43
|
+
}
|
|
44
|
+
*splitString(s, length) {
|
|
45
|
+
const len = s.length;
|
|
46
|
+
for (let i = 0; i < len; i += length) {
|
|
47
|
+
yield s.slice(i, Math.min(i + length, len));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
getSelectedSets(option) {
|
|
51
|
+
if (option === "KR") {
|
|
52
|
+
return {
|
|
53
|
+
dduSet: this.dduCharKr,
|
|
54
|
+
padChar: this.paddingCharKr,
|
|
55
|
+
dduLength: this.dduCharKr.length,
|
|
56
|
+
bitLength: this.getBitLength(this.dduCharKr.length),
|
|
57
|
+
lookupTable: this.dduBinaryLookupKr,
|
|
58
|
+
paddingRegExp: this.paddingRegex.get('KR')
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
dduSet: this.dduChar,
|
|
63
|
+
padChar: this.paddingChar,
|
|
64
|
+
dduLength: this.dduChar.length,
|
|
65
|
+
bitLength: this.getBitLength(this.dduChar.length),
|
|
66
|
+
lookupTable: this.dduBinaryLookup,
|
|
67
|
+
paddingRegExp: this.paddingRegex.get('default')
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
getSelectedSets64(option) {
|
|
71
|
+
const baseSet = this.getSelectedSets(option);
|
|
72
|
+
const powerOfTwoLength = this.getLargestPowerOfTwo(baseSet.dduSet.length);
|
|
73
|
+
return {
|
|
74
|
+
...baseSet,
|
|
75
|
+
dduSet: baseSet.dduSet.slice(0, powerOfTwoLength),
|
|
76
|
+
dduLength: powerOfTwoLength,
|
|
77
|
+
bitLength: Math.log2(powerOfTwoLength)
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
bufferToDduBinary(input, bitLength) {
|
|
81
|
+
const bufferLength = input.length;
|
|
82
|
+
let encodedBin = '';
|
|
83
|
+
for (let i = 0; i < bufferLength; i++) {
|
|
84
|
+
encodedBin += this.binaryLookup[input[i]];
|
|
85
|
+
}
|
|
86
|
+
const dduBinary = Array.from(this.splitString(encodedBin, bitLength));
|
|
87
|
+
const padding = bitLength - dduBinary[dduBinary.length - 1].length;
|
|
88
|
+
if (padding > 0) {
|
|
89
|
+
dduBinary[dduBinary.length - 1] += '0'.repeat(padding);
|
|
90
|
+
}
|
|
91
|
+
return { dduBinary, padding };
|
|
92
|
+
}
|
|
93
|
+
dduBinaryToBuffer(decodedBin, paddingCount) {
|
|
94
|
+
const paddingBits = paddingCount * 2;
|
|
95
|
+
if (paddingBits > 0) {
|
|
96
|
+
decodedBin = decodedBin.slice(0, -paddingBits);
|
|
97
|
+
}
|
|
98
|
+
const chunkCount = Math.floor(decodedBin.length / 8);
|
|
99
|
+
const buffer = new Array(chunkCount);
|
|
100
|
+
for (let i = 0; i < chunkCount; i++) {
|
|
101
|
+
const start = i * 8;
|
|
102
|
+
buffer[i] = parseInt(decodedBin.slice(start, start + 8), 2);
|
|
103
|
+
}
|
|
104
|
+
return buffer;
|
|
105
|
+
}
|
|
106
|
+
encode(input, option = "default", encoding = this.defaultEncoding) {
|
|
107
|
+
const bufferInput = typeof input === 'string' ? Buffer.from(input, encoding) : input;
|
|
108
|
+
const { dduSet, padChar, dduLength, bitLength } = this.getSelectedSets(option);
|
|
109
|
+
const { dduBinary, padding } = this.bufferToDduBinary(bufferInput, bitLength);
|
|
110
|
+
let resultString = "";
|
|
111
|
+
for (const char of dduBinary) {
|
|
112
|
+
const charInt = parseInt(char, 2);
|
|
113
|
+
const quotient = Math.floor(charInt / dduLength);
|
|
114
|
+
const remainder = charInt % dduLength;
|
|
115
|
+
resultString += dduSet[quotient] + dduSet[remainder];
|
|
116
|
+
}
|
|
117
|
+
if (padding > 0) {
|
|
118
|
+
return resultString + padChar.repeat(Math.floor(padding / 2));
|
|
119
|
+
}
|
|
120
|
+
return resultString;
|
|
121
|
+
}
|
|
122
|
+
encode64(input, option = "default", encoding = this.defaultEncoding) {
|
|
123
|
+
const bufferInput = typeof input === 'string' ? Buffer.from(input, encoding) : input;
|
|
124
|
+
const { dduSet, padChar, bitLength } = this.getSelectedSets64(option);
|
|
125
|
+
const { dduBinary, padding } = this.bufferToDduBinary(bufferInput, bitLength);
|
|
126
|
+
let resultString = "";
|
|
127
|
+
for (const char of dduBinary) {
|
|
128
|
+
const charInt = parseInt(char, 2);
|
|
129
|
+
resultString += dduSet[charInt];
|
|
130
|
+
}
|
|
131
|
+
if (padding > 0) {
|
|
132
|
+
return resultString + padChar.repeat(Math.floor(padding / 2));
|
|
133
|
+
}
|
|
134
|
+
return resultString;
|
|
135
|
+
}
|
|
136
|
+
decode(input, option = "default", encoding = this.defaultEncoding) {
|
|
137
|
+
const { dduSet, dduLength, bitLength, lookupTable, paddingRegExp } = this.getSelectedSets(option);
|
|
138
|
+
const paddingCount = (input.match(paddingRegExp) || []).length;
|
|
139
|
+
input = input.replace(paddingRegExp, '');
|
|
140
|
+
let dduBinary = "";
|
|
141
|
+
for (let i = 0; i < input.length; i += 2) {
|
|
142
|
+
const firstIndex = lookupTable.get(input[i]);
|
|
143
|
+
const secondIndex = lookupTable.get(input[i + 1]);
|
|
144
|
+
if (firstIndex === undefined || secondIndex === undefined)
|
|
145
|
+
continue;
|
|
146
|
+
const value = firstIndex * dduLength + secondIndex;
|
|
147
|
+
dduBinary += value.toString(2).padStart(bitLength, '0');
|
|
148
|
+
}
|
|
149
|
+
const decoded = this.dduBinaryToBuffer(dduBinary, paddingCount);
|
|
150
|
+
return Buffer.from(decoded).toString(encoding);
|
|
151
|
+
}
|
|
152
|
+
decode64(input, option = "default", encoding = this.defaultEncoding) {
|
|
153
|
+
const { dduSet, bitLength, lookupTable, paddingRegExp } = this.getSelectedSets64(option);
|
|
154
|
+
const paddingCount = (input.match(paddingRegExp) || []).length;
|
|
155
|
+
input = input.replace(paddingRegExp, '');
|
|
156
|
+
let dduBinary = '';
|
|
157
|
+
for (let i = 0; i < input.length; i++) {
|
|
158
|
+
const charIndex = lookupTable.get(input[i]);
|
|
159
|
+
if (charIndex === undefined)
|
|
160
|
+
continue;
|
|
161
|
+
dduBinary += charIndex.toString(2).padStart(bitLength, '0');
|
|
162
|
+
}
|
|
163
|
+
const decoded = this.dduBinaryToBuffer(dduBinary, paddingCount);
|
|
164
|
+
return Buffer.from(decoded).toString(encoding);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Ddu64 } from "..";
|
|
2
|
+
const koreanChars = [
|
|
3
|
+
// 기본 자음+모음 조합
|
|
4
|
+
"가", "나", "다", "라", "마", "바", "사", "아", "자", "차", "카", "타", "파", "하",
|
|
5
|
+
"개", "내", "대", "래", "매", "배", "새", "애", "재", "채", "캐", "태", "패", "해",
|
|
6
|
+
"고", "노", "도", "로", "모", "보", "소", "오", "조", "초", "코", "토", "포", "호",
|
|
7
|
+
"구", "누", "두", "루", "무", "부", "수", "우", "주", "추", "쿠", "투", "푸", "후",
|
|
8
|
+
"그", "느", "드", "르", "므", "브", "스", "으", "즈", "츠", "크", "트", "프", "흐",
|
|
9
|
+
"기", "니", "디", "리", "미", "비", "시", "이", "지", "치", "키", "티", "피", "히",
|
|
10
|
+
"게", "네", "데", "레", "메", "베", "세", "에", "제", "체", "케", "테", "페", "헤",
|
|
11
|
+
"겨", "녀", "더", "려", "며", "벼", "셔", "여", "져", "쳐", "켜", "텨", "펴", "혀",
|
|
12
|
+
"교", "뇨", "됴", "료", "묘", "뵤", "쇼", "요", "죠", "쵸", "쿄", "툐", "표", "효",
|
|
13
|
+
"규", "뉴", "듀", "류", "뮤", "뷰", "슈", "유", "쥬", "츄", "큐", "튜", "퓨", "휴",
|
|
14
|
+
// 받침 있는 조합
|
|
15
|
+
"각", "낙", "닥", "락", "막", "박", "삭", "악", "작", "착", "칵", "탁", "팍", "학",
|
|
16
|
+
"갑", "납", "답", "랍", "맙", "밥", "삽", "압", "잡", "찹", "캅", "탑", "팝", "합",
|
|
17
|
+
"곡", "녹", "독", "록", "목", "복", "속", "옥", "족", "촉", "콕", "톡", "폭", "혹",
|
|
18
|
+
"국", "눅", "둑", "룩", "묵", "북", "숙", "욱", "죽", "축", "쿡", "툭", "푹", "훅",
|
|
19
|
+
"극", "늑", "득", "륵", "믁", "븍", "슥", "윽", "즉", "츰", "큭", "특", "픅", "흑",
|
|
20
|
+
"금", "늠", "듬", "름", "뭄", "붐", "숨", "음", "줌", "춤", "큼", "틈", "품", "흠",
|
|
21
|
+
"갈", "날", "달", "랄", "말", "발", "살", "알", "잘", "찰", "칼", "탈", "팔", "할",
|
|
22
|
+
"감", "남", "담", "람", "맘", "밤", "샘", "암", "잠", "참", "캄", "탐", "팜", "함",
|
|
23
|
+
"건", "넌", "던", "런", '먼'
|
|
24
|
+
]; //129
|
|
25
|
+
const ddu64 = new Ddu64(["D", "d", "U", "u", "T", "t", "A", "a"], "응");
|
|
26
|
+
const answer = "안녕 나 안보고싶었어?12";
|
|
27
|
+
const encoded = ddu64.encode64(answer);
|
|
28
|
+
console.log(encoded);
|
|
29
|
+
const decoded = ddu64.decode64(encoded);
|
|
30
|
+
console.log(decoded);
|
|
31
|
+
console.log("=-==");
|
|
32
|
+
const encoded_eng = ddu64.encode(answer, "KR");
|
|
33
|
+
console.log(encoded_eng);
|
|
34
|
+
const decoded_eng = ddu64.decode(encoded_eng, "KR");
|
|
35
|
+
console.log(decoded_eng);
|
|
36
|
+
console.log("=-==");
|
|
37
|
+
const ddu64_other = new Ddu64(koreanChars, "즁");
|
|
38
|
+
const answer2 = "안녕나안보고싶었어?스스로칭찬하려니까부담되는걸?하지만기록은완성해야하니까어쩔수없지~엘리시아는상냥하고,친근하고,귀엽고,똑똑하고아름다운소녀야.그녀의초대를거절하거나그녀를냉정하게대할수있는사람은없어.전설속의엘프처럼모든이의마음을사로잡고13명의영웅을이곳에모았으면서첫번째자리를양보하는겸손함까지...영웅들에게엘리시아는가장믿음직스럽고사랑받는동료야.너희도그렇게생각하지?1";
|
|
39
|
+
const encoded2 = ddu64_other.encode64(answer2);
|
|
40
|
+
console.log(encoded2);
|
|
41
|
+
const decoded2 = ddu64_other.decode64(encoded2);
|
|
42
|
+
console.log(decoded2);
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ddunigma/node",
|
|
3
|
+
"version": "1.0.10",
|
|
4
|
+
"main": "dist/cjs/index.js",
|
|
5
|
+
"module": "dist/mjs/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "tsx ./src/test/test.ts",
|
|
10
|
+
"build": "rm -rf dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && sh postProcess.sh",
|
|
11
|
+
"test1": "tsx ./src/test/test1.ts"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"import": "./dist/mjs/index.js",
|
|
16
|
+
"require": "./dist/cjs/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"description": "",
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^22.13.0",
|
|
24
|
+
"tsx": "^4.19.2",
|
|
25
|
+
"typescript": "^5.7.3"
|
|
26
|
+
}
|
|
27
|
+
}
|