@ddunigma/node 1.0.17 → 1.0.18

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/dist/cjs/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Ddu64 = void 0;
3
+ exports.Custom64 = exports.Ddu64 = void 0;
4
4
  class Ddu64 {
5
5
  constructor(dduChar, paddingChar) {
6
6
  this.dduCharKr = [
@@ -131,3 +131,189 @@ class Ddu64 {
131
131
  }
132
132
  }
133
133
  exports.Ddu64 = Ddu64;
134
+ class Custom64 {
135
+ constructor(dduChar, paddingChar) {
136
+ this.dduCharKr = [
137
+ "A",
138
+ "s",
139
+ "q",
140
+ "r",
141
+ "0",
142
+ "z",
143
+ "3",
144
+ "t",
145
+ "y",
146
+ "1",
147
+ "5",
148
+ "2",
149
+ "4",
150
+ "E",
151
+ "B",
152
+ "C",
153
+ "Q",
154
+ "F",
155
+ "R",
156
+ "T",
157
+ "U",
158
+ "W",
159
+ "V",
160
+ "X",
161
+ "Y",
162
+ "Z",
163
+ "b",
164
+ "a",
165
+ "c",
166
+ "d",
167
+ "D",
168
+ "G",
169
+ "L",
170
+ "H",
171
+ "I",
172
+ "+",
173
+ "J",
174
+ "K",
175
+ "M",
176
+ "O",
177
+ "N",
178
+ "f",
179
+ "e",
180
+ "h",
181
+ "g",
182
+ "P",
183
+ "i",
184
+ "S",
185
+ "k",
186
+ "l",
187
+ "m",
188
+ "u",
189
+ "j",
190
+ "v",
191
+ "n",
192
+ "o",
193
+ "p",
194
+ "9",
195
+ "w",
196
+ "6",
197
+ "7",
198
+ "8",
199
+ "x",
200
+ "/",
201
+ ];
202
+ this.paddingCharKr = "=";
203
+ this.defaultEncoding = "utf-8";
204
+ this.bitLengthMap = new Map();
205
+ this.binaryLookup = Array.from({ length: 256 }, (_, i) => i.toString(2).padStart(8, "0"));
206
+ this.dduBinaryLookup = new Map();
207
+ this.dduBinaryLookupKr = new Map();
208
+ this.paddingRegex = new Map();
209
+ this.dduChar = dduChar || this.dduCharKr;
210
+ this.paddingChar = paddingChar || this.paddingCharKr;
211
+ this.dduChar.forEach((char, index) => this.dduBinaryLookup.set(char, index));
212
+ this.dduCharKr.forEach((char, index) => this.dduBinaryLookupKr.set(char, index));
213
+ this.paddingRegex.set("default", new RegExp(this.paddingChar, "g"));
214
+ this.paddingRegex.set("KR", new RegExp(this.paddingCharKr, "g"));
215
+ }
216
+ getBitLength(setLength) {
217
+ let cached = this.bitLengthMap.get(setLength);
218
+ if (cached === undefined) {
219
+ cached = Math.ceil(Math.log2(setLength));
220
+ this.bitLengthMap.set(setLength, cached);
221
+ }
222
+ return cached;
223
+ }
224
+ getLargestPowerOfTwo(n) {
225
+ return Math.pow(2, Math.floor(Math.log2(n)));
226
+ }
227
+ *splitString(s, length) {
228
+ for (let i = 0; i < s.length; i += length) {
229
+ yield s.slice(i, Math.min(i + length, s.length));
230
+ }
231
+ }
232
+ getSelectedSets(dduSetSymbol, usePowerOfTwo) {
233
+ const isKR = dduSetSymbol === "KR";
234
+ const dduSet = isKR ? this.dduCharKr : this.dduChar;
235
+ const padChar = isKR ? this.paddingCharKr : this.paddingChar;
236
+ let dduLength = dduSet.length;
237
+ if (usePowerOfTwo) {
238
+ const powerOfTwoLength = this.getLargestPowerOfTwo(dduLength);
239
+ dduLength = powerOfTwoLength;
240
+ }
241
+ return {
242
+ dduSet: usePowerOfTwo ? dduSet.slice(0, dduLength) : dduSet,
243
+ padChar,
244
+ dduLength,
245
+ bitLength: this.getBitLength(dduLength),
246
+ lookupTable: isKR ? this.dduBinaryLookupKr : this.dduBinaryLookup,
247
+ paddingRegExp: this.paddingRegex.get(isKR ? "KR" : "default"),
248
+ };
249
+ }
250
+ bufferToDduBinary(input, bitLength) {
251
+ const encodedBin = input.reduce((acc, byte) => acc + this.binaryLookup[byte], "");
252
+ const dduBinary = Array.from(this.splitString(encodedBin, bitLength));
253
+ const padding = bitLength - dduBinary[dduBinary.length - 1].length;
254
+ if (padding > 0) {
255
+ dduBinary[dduBinary.length - 1] += "0".repeat(padding);
256
+ }
257
+ return { dduBinary, padding };
258
+ }
259
+ dduBinaryToBuffer(decodedBin, paddingBits) {
260
+ if (paddingBits > 0) {
261
+ decodedBin = decodedBin.slice(0, -paddingBits);
262
+ }
263
+ const buffer = [];
264
+ for (let i = 0; i < decodedBin.length; i += 8) {
265
+ buffer.push(parseInt(decodedBin.slice(i, i + 8), 2));
266
+ }
267
+ return Buffer.from(buffer);
268
+ }
269
+ encode(input, options = {}) {
270
+ const { dduSetSymbol = "default", encoding = this.defaultEncoding, usePowerOfTwo = false, } = options;
271
+ const bufferInput = typeof input === "string" ? Buffer.from(input, encoding) : input;
272
+ const { dduSet, padChar, dduLength, bitLength } = this.getSelectedSets(dduSetSymbol, usePowerOfTwo);
273
+ const { dduBinary, padding } = this.bufferToDduBinary(bufferInput, bitLength);
274
+ let resultString = "";
275
+ for (const binaryChunk of dduBinary) {
276
+ const charInt = parseInt(binaryChunk, 2);
277
+ if (usePowerOfTwo) {
278
+ resultString += dduSet[charInt];
279
+ }
280
+ else {
281
+ const quotient = Math.floor(charInt / dduLength);
282
+ const remainder = charInt % dduLength;
283
+ resultString += dduSet[quotient] + dduSet[remainder];
284
+ }
285
+ }
286
+ return padding > 0
287
+ ? resultString + padChar.repeat(Math.floor(padding / 2))
288
+ : resultString;
289
+ }
290
+ decode(input, options = {}) {
291
+ const { dduSetSymbol = "default", encoding = this.defaultEncoding, usePowerOfTwo = false, } = options;
292
+ const { dduSet, dduLength, bitLength, lookupTable, paddingRegExp } = this.getSelectedSets(dduSetSymbol, usePowerOfTwo);
293
+ const paddingCount = (input.match(paddingRegExp) || []).length;
294
+ const paddingBits = paddingCount * 2;
295
+ input = input.replace(paddingRegExp, "");
296
+ let dduBinary = "";
297
+ for (let i = 0; i < input.length; i += usePowerOfTwo ? 1 : 2) {
298
+ const firstChar = input[i];
299
+ const secondChar = input[i + 1];
300
+ if (usePowerOfTwo) {
301
+ const charIndex = lookupTable.get(firstChar);
302
+ if (charIndex === undefined)
303
+ throw new Error(`Invalid character: ${firstChar}`);
304
+ dduBinary += charIndex.toString(2).padStart(bitLength, "0");
305
+ }
306
+ else {
307
+ const firstIndex = lookupTable.get(firstChar);
308
+ const secondIndex = lookupTable.get(secondChar);
309
+ if (firstIndex === undefined || secondIndex === undefined)
310
+ throw new Error(`Invalid character: ${firstChar} or ${secondChar}`);
311
+ const value = firstIndex * dduLength + secondIndex;
312
+ dduBinary += value.toString(2).padStart(bitLength, "0");
313
+ }
314
+ }
315
+ const decoded = this.dduBinaryToBuffer(dduBinary, usePowerOfTwo ? paddingBits : paddingCount * bitLength);
316
+ return decoded.toString(encoding);
317
+ }
318
+ }
319
+ exports.Custom64 = Custom64;
package/dist/index.d.ts CHANGED
@@ -27,3 +27,32 @@ export declare class Ddu64 {
27
27
  usePowerOfTwo?: boolean;
28
28
  }): string;
29
29
  }
30
+ export declare class Custom64 {
31
+ private readonly dduChar;
32
+ private readonly paddingChar;
33
+ private readonly dduCharKr;
34
+ private readonly paddingCharKr;
35
+ private readonly defaultEncoding;
36
+ private readonly bitLengthMap;
37
+ private readonly binaryLookup;
38
+ private readonly dduBinaryLookup;
39
+ private readonly dduBinaryLookupKr;
40
+ private readonly paddingRegex;
41
+ constructor(dduChar?: string[], paddingChar?: string);
42
+ private getBitLength;
43
+ private getLargestPowerOfTwo;
44
+ private splitString;
45
+ private getSelectedSets;
46
+ private bufferToDduBinary;
47
+ private dduBinaryToBuffer;
48
+ encode(input: Buffer | string, options?: {
49
+ dduSetSymbol?: string;
50
+ encoding?: BufferEncoding;
51
+ usePowerOfTwo?: boolean;
52
+ }): string;
53
+ decode(input: string, options?: {
54
+ dduSetSymbol?: string;
55
+ encoding?: BufferEncoding;
56
+ usePowerOfTwo?: boolean;
57
+ }): string;
58
+ }
package/dist/mjs/index.js CHANGED
@@ -129,3 +129,190 @@ export class Ddu64 {
129
129
  return decoded.toString(encoding);
130
130
  }
131
131
  }
132
+ export class Custom64 {
133
+ dduChar;
134
+ paddingChar;
135
+ dduCharKr = [
136
+ "A",
137
+ "s",
138
+ "q",
139
+ "r",
140
+ "0",
141
+ "z",
142
+ "3",
143
+ "t",
144
+ "y",
145
+ "1",
146
+ "5",
147
+ "2",
148
+ "4",
149
+ "E",
150
+ "B",
151
+ "C",
152
+ "Q",
153
+ "F",
154
+ "R",
155
+ "T",
156
+ "U",
157
+ "W",
158
+ "V",
159
+ "X",
160
+ "Y",
161
+ "Z",
162
+ "b",
163
+ "a",
164
+ "c",
165
+ "d",
166
+ "D",
167
+ "G",
168
+ "L",
169
+ "H",
170
+ "I",
171
+ "+",
172
+ "J",
173
+ "K",
174
+ "M",
175
+ "O",
176
+ "N",
177
+ "f",
178
+ "e",
179
+ "h",
180
+ "g",
181
+ "P",
182
+ "i",
183
+ "S",
184
+ "k",
185
+ "l",
186
+ "m",
187
+ "u",
188
+ "j",
189
+ "v",
190
+ "n",
191
+ "o",
192
+ "p",
193
+ "9",
194
+ "w",
195
+ "6",
196
+ "7",
197
+ "8",
198
+ "x",
199
+ "/",
200
+ ];
201
+ paddingCharKr = "=";
202
+ defaultEncoding = "utf-8";
203
+ bitLengthMap = new Map();
204
+ binaryLookup = Array.from({ length: 256 }, (_, i) => i.toString(2).padStart(8, "0"));
205
+ dduBinaryLookup = new Map();
206
+ dduBinaryLookupKr = new Map();
207
+ paddingRegex = new Map();
208
+ constructor(dduChar, paddingChar) {
209
+ this.dduChar = dduChar || this.dduCharKr;
210
+ this.paddingChar = paddingChar || this.paddingCharKr;
211
+ this.dduChar.forEach((char, index) => this.dduBinaryLookup.set(char, index));
212
+ this.dduCharKr.forEach((char, index) => this.dduBinaryLookupKr.set(char, index));
213
+ this.paddingRegex.set("default", new RegExp(this.paddingChar, "g"));
214
+ this.paddingRegex.set("KR", new RegExp(this.paddingCharKr, "g"));
215
+ }
216
+ getBitLength(setLength) {
217
+ let cached = this.bitLengthMap.get(setLength);
218
+ if (cached === undefined) {
219
+ cached = Math.ceil(Math.log2(setLength));
220
+ this.bitLengthMap.set(setLength, cached);
221
+ }
222
+ return cached;
223
+ }
224
+ getLargestPowerOfTwo(n) {
225
+ return 2 ** Math.floor(Math.log2(n));
226
+ }
227
+ *splitString(s, length) {
228
+ for (let i = 0; i < s.length; i += length) {
229
+ yield s.slice(i, Math.min(i + length, s.length));
230
+ }
231
+ }
232
+ getSelectedSets(dduSetSymbol, usePowerOfTwo) {
233
+ const isKR = dduSetSymbol === "KR";
234
+ const dduSet = isKR ? this.dduCharKr : this.dduChar;
235
+ const padChar = isKR ? this.paddingCharKr : this.paddingChar;
236
+ let dduLength = dduSet.length;
237
+ if (usePowerOfTwo) {
238
+ const powerOfTwoLength = this.getLargestPowerOfTwo(dduLength);
239
+ dduLength = powerOfTwoLength;
240
+ }
241
+ return {
242
+ dduSet: usePowerOfTwo ? dduSet.slice(0, dduLength) : dduSet,
243
+ padChar,
244
+ dduLength,
245
+ bitLength: this.getBitLength(dduLength),
246
+ lookupTable: isKR ? this.dduBinaryLookupKr : this.dduBinaryLookup,
247
+ paddingRegExp: this.paddingRegex.get(isKR ? "KR" : "default"),
248
+ };
249
+ }
250
+ bufferToDduBinary(input, bitLength) {
251
+ const encodedBin = input.reduce((acc, byte) => acc + this.binaryLookup[byte], "");
252
+ const dduBinary = Array.from(this.splitString(encodedBin, bitLength));
253
+ const padding = bitLength - dduBinary[dduBinary.length - 1].length;
254
+ if (padding > 0) {
255
+ dduBinary[dduBinary.length - 1] += "0".repeat(padding);
256
+ }
257
+ return { dduBinary, padding };
258
+ }
259
+ dduBinaryToBuffer(decodedBin, paddingBits) {
260
+ if (paddingBits > 0) {
261
+ decodedBin = decodedBin.slice(0, -paddingBits);
262
+ }
263
+ const buffer = [];
264
+ for (let i = 0; i < decodedBin.length; i += 8) {
265
+ buffer.push(parseInt(decodedBin.slice(i, i + 8), 2));
266
+ }
267
+ return Buffer.from(buffer);
268
+ }
269
+ encode(input, options = {}) {
270
+ const { dduSetSymbol = "default", encoding = this.defaultEncoding, usePowerOfTwo = false, } = options;
271
+ const bufferInput = typeof input === "string" ? Buffer.from(input, encoding) : input;
272
+ const { dduSet, padChar, dduLength, bitLength } = this.getSelectedSets(dduSetSymbol, usePowerOfTwo);
273
+ const { dduBinary, padding } = this.bufferToDduBinary(bufferInput, bitLength);
274
+ let resultString = "";
275
+ for (const binaryChunk of dduBinary) {
276
+ const charInt = parseInt(binaryChunk, 2);
277
+ if (usePowerOfTwo) {
278
+ resultString += dduSet[charInt];
279
+ }
280
+ else {
281
+ const quotient = Math.floor(charInt / dduLength);
282
+ const remainder = charInt % dduLength;
283
+ resultString += dduSet[quotient] + dduSet[remainder];
284
+ }
285
+ }
286
+ return padding > 0
287
+ ? resultString + padChar.repeat(Math.floor(padding / 2))
288
+ : resultString;
289
+ }
290
+ decode(input, options = {}) {
291
+ const { dduSetSymbol = "default", encoding = this.defaultEncoding, usePowerOfTwo = false, } = options;
292
+ const { dduSet, dduLength, bitLength, lookupTable, paddingRegExp } = this.getSelectedSets(dduSetSymbol, usePowerOfTwo);
293
+ const paddingCount = (input.match(paddingRegExp) || []).length;
294
+ const paddingBits = paddingCount * 2;
295
+ input = input.replace(paddingRegExp, "");
296
+ let dduBinary = "";
297
+ for (let i = 0; i < input.length; i += usePowerOfTwo ? 1 : 2) {
298
+ const firstChar = input[i];
299
+ const secondChar = input[i + 1];
300
+ if (usePowerOfTwo) {
301
+ const charIndex = lookupTable.get(firstChar);
302
+ if (charIndex === undefined)
303
+ throw new Error(`Invalid character: ${firstChar}`);
304
+ dduBinary += charIndex.toString(2).padStart(bitLength, "0");
305
+ }
306
+ else {
307
+ const firstIndex = lookupTable.get(firstChar);
308
+ const secondIndex = lookupTable.get(secondChar);
309
+ if (firstIndex === undefined || secondIndex === undefined)
310
+ throw new Error(`Invalid character: ${firstChar} or ${secondChar}`);
311
+ const value = firstIndex * dduLength + secondIndex;
312
+ dduBinary += value.toString(2).padStart(bitLength, "0");
313
+ }
314
+ }
315
+ const decoded = this.dduBinaryToBuffer(dduBinary, usePowerOfTwo ? paddingBits : paddingCount * bitLength);
316
+ return decoded.toString(encoding);
317
+ }
318
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ddunigma/node",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/mjs/index.js",
6
6
  "types": "dist/index.d.ts",