Skip to content

Commit e7ce46e

Browse files
committed
Read/write strings from/to binary
1 parent 8aeb256 commit e7ce46e

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

src/utils/createBinaryReader.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ export type BinaryReader = {
99
binary: (bits: number) => string;
1010
boolean: () => boolean;
1111
uInt: () => number;
12+
uShort: () => number;
1213
uLong: () => number;
1314
float: () => number;
1415
int: () => number;
16+
char: () => string;
17+
string: () => string;
1518
};
1619

1720
export const createBinaryReader = (binary: string): BinaryReader => {
@@ -39,6 +42,12 @@ export const createBinaryReader = (binary: string): BinaryReader => {
3942
return binaryToNumber(bits);
4043
},
4144

45+
uShort: function () {
46+
const bits = this.binary(16);
47+
48+
return binaryToNumber(bits);
49+
},
50+
4251
uLong: function () {
4352
const bits = this.binary(64);
4453

@@ -55,6 +64,55 @@ export const createBinaryReader = (binary: string): BinaryReader => {
5564
const bits = this.binary(32);
5665

5766
return binaryToInt(bits);
67+
},
68+
69+
char: function () {
70+
const bits = this.binary(8);
71+
const charCode = binaryToNumber(bits);
72+
73+
return String.fromCharCode(charCode);
74+
},
75+
76+
string: function () {
77+
const length = this.uShort();
78+
79+
if (length === 0) return '';
80+
81+
/* Align bits. */
82+
const offset = index.current % 8 === 0 ? 0 : 8 - (index.current % 8);
83+
84+
if (offset > 0) this.binary(offset);
85+
86+
let currentByte = (index.current % 32) / 8;
87+
88+
/* Read garbled text from binary. */
89+
let textBuffer = '';
90+
91+
while (textBuffer.length < length) {
92+
textBuffer += this.char();
93+
}
94+
95+
/* Untangle garbled text. */
96+
let text = '';
97+
let bufferIndex = 0;
98+
99+
while (currentByte < 4 && bufferIndex < length) {
100+
text += textBuffer[bufferIndex++];
101+
currentByte++;
102+
}
103+
104+
while (bufferIndex + 4 <= length) {
105+
const chars = textBuffer.substr(bufferIndex, 4);
106+
107+
text += chars.split('').reverse().join('');
108+
bufferIndex += 4;
109+
}
110+
111+
while (bufferIndex < length) {
112+
text += textBuffer[bufferIndex++];
113+
}
114+
115+
return text;
58116
}
59117
};
60118
};

src/utils/createBinaryWriter.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
import { floatToBinary } from './floatToBinary';
2+
import { uShortToBinary } from './uShortToBinary';
23
import { uLongToBinary } from './uLongToBinary';
34
import { intToBinary } from './intToBinary';
45
import { uIntToBinary } from './uIntToBinary';
6+
import { numberToBinary } from './numberToBinary';
57

68
export type BinaryWriter = {
79
binary: (bits: string) => void;
810
boolean: (bit: boolean) => void;
911
uInt: (number: number) => void;
12+
uShort: (number: number) => void;
1013
uLong: (number: number) => void;
1114
float: (number: number) => void;
1215
int: (number: number) => void;
16+
char: (char: string) => void;
17+
string: (text: string) => void;
1318
flush: () => string;
1419
};
1520

@@ -29,6 +34,10 @@ export const createBinaryWriter = (): BinaryWriter => {
2934
binary += uIntToBinary(number);
3035
},
3136

37+
uShort: function (number: number) {
38+
binary += uShortToBinary(number);
39+
},
40+
3241
uLong: function (number: number) {
3342
binary += uLongToBinary(number);
3443
},
@@ -41,6 +50,55 @@ export const createBinaryWriter = (): BinaryWriter => {
4150
binary += intToBinary(number);
4251
},
4352

53+
char: function (char: string) {
54+
const charCode = char.charCodeAt(0);
55+
const bits = numberToBinary(charCode).padStart(8, '0');
56+
57+
binary += bits;
58+
},
59+
60+
string: function (textBuffer: string) {
61+
this.uShort(textBuffer.length);
62+
63+
if (textBuffer.length === 0) return;
64+
65+
/* Align bits. */
66+
const index = binary.length;
67+
const offset = index % 8 === 0 ? 0 : 8 - (index % 8);
68+
69+
if (offset > 0) {
70+
const align = '0'.repeat(offset);
71+
72+
this.binary(align);
73+
}
74+
75+
let currentByte = (binary.length % 32) / 8;
76+
77+
/* Garble text, ATT style. */
78+
let text = '';
79+
let bufferIndex = 0;
80+
81+
while (currentByte < 4 && bufferIndex < textBuffer.length) {
82+
text += textBuffer[bufferIndex++];
83+
currentByte++;
84+
}
85+
86+
while (bufferIndex + 4 <= textBuffer.length) {
87+
const chars = textBuffer.substr(bufferIndex, 4);
88+
89+
text += chars.split('').reverse().join('');
90+
bufferIndex += 4;
91+
}
92+
93+
while (bufferIndex < textBuffer.length) {
94+
text += textBuffer[bufferIndex++];
95+
}
96+
97+
for (const letter of text) {
98+
this.char(letter);
99+
}
100+
},
101+
44102
flush: function () {
45103
const result = binary;
46104
binary = '';

0 commit comments

Comments
 (0)