Skip to content

Commit 6df85c6

Browse files
committed
Encoder performance
1 parent 85bcf2b commit 6df85c6

File tree

2 files changed

+155
-82
lines changed

2 files changed

+155
-82
lines changed

crypto/src/util/encoders/Base64Encoder.cs

Lines changed: 98 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -44,69 +44,69 @@ public Base64Encoder()
4444
InitialiseDecodingTable();
4545
}
4646

47-
/**
48-
* encode the input data producing a base 64 output stream.
49-
*
50-
* @return the number of bytes produced.
51-
*/
52-
public int Encode(
53-
byte[] data,
54-
int off,
55-
int length,
56-
Stream outStream)
47+
public int Encode(byte[] inBuf, int inOff, int inLen, byte[] outBuf, int outOff)
5748
{
58-
int modulus = length % 3;
59-
int dataLength = (length - modulus);
60-
int a1, a2, a3;
49+
int inPos = inOff;
50+
int inEnd = inOff + inLen - 2;
51+
int outPos = outOff;
6152

62-
for (int i = off; i < off + dataLength; i += 3)
53+
while (inPos < inEnd)
6354
{
64-
a1 = data[i] & 0xff;
65-
a2 = data[i + 1] & 0xff;
66-
a3 = data[i + 2] & 0xff;
67-
68-
outStream.WriteByte(encodingTable[(int) ((uint) a1 >> 2) & 0x3f]);
69-
outStream.WriteByte(encodingTable[((a1 << 4) | (int) ((uint) a2 >> 4)) & 0x3f]);
70-
outStream.WriteByte(encodingTable[((a2 << 2) | (int) ((uint) a3 >> 6)) & 0x3f]);
71-
outStream.WriteByte(encodingTable[a3 & 0x3f]);
55+
uint a1 = inBuf[inPos++];
56+
uint a2 = inBuf[inPos++];
57+
uint a3 = inBuf[inPos++];
58+
59+
outBuf[outPos++] = encodingTable[(a1 >> 2) & 0x3F];
60+
outBuf[outPos++] = encodingTable[((a1 << 4) | (a2 >> 4)) & 0x3F];
61+
outBuf[outPos++] = encodingTable[((a2 << 2) | (a3 >> 6)) & 0x3F];
62+
outBuf[outPos++] = encodingTable[a3 & 0x3F];
7263
}
7364

74-
/*
75-
* process the tail end.
76-
*/
77-
int b1, b2, b3;
78-
int d1, d2;
65+
switch (inLen - (inPos - inOff))
66+
{
67+
case 1:
68+
{
69+
uint a1 = inBuf[inPos++];
7970

80-
switch (modulus)
71+
outBuf[outPos++] = encodingTable[(a1 >> 2) & 0x3F];
72+
outBuf[outPos++] = encodingTable[(a1 << 4) & 0x3F];
73+
outBuf[outPos++] = padding;
74+
outBuf[outPos++] = padding;
75+
break;
76+
}
77+
case 2:
8178
{
82-
case 0: /* nothing left to do */
83-
break;
84-
case 1:
85-
d1 = data[off + dataLength] & 0xff;
86-
b1 = (d1 >> 2) & 0x3f;
87-
b2 = (d1 << 4) & 0x3f;
88-
89-
outStream.WriteByte(encodingTable[b1]);
90-
outStream.WriteByte(encodingTable[b2]);
91-
outStream.WriteByte(padding);
92-
outStream.WriteByte(padding);
93-
break;
94-
case 2:
95-
d1 = data[off + dataLength] & 0xff;
96-
d2 = data[off + dataLength + 1] & 0xff;
97-
98-
b1 = (d1 >> 2) & 0x3f;
99-
b2 = ((d1 << 4) | (d2 >> 4)) & 0x3f;
100-
b3 = (d2 << 2) & 0x3f;
101-
102-
outStream.WriteByte(encodingTable[b1]);
103-
outStream.WriteByte(encodingTable[b2]);
104-
outStream.WriteByte(encodingTable[b3]);
105-
outStream.WriteByte(padding);
106-
break;
79+
uint a1 = inBuf[inPos++];
80+
uint a2 = inBuf[inPos++];
81+
82+
outBuf[outPos++] = encodingTable[(a1 >> 2) & 0x3F];
83+
outBuf[outPos++] = encodingTable[((a1 << 4) | (a2 >> 4)) & 0x3F];
84+
outBuf[outPos++] = encodingTable[(a2 << 2) & 0x3F];
85+
outBuf[outPos++] = padding;
86+
break;
10787
}
88+
}
89+
90+
return outPos - outOff;
91+
}
10892

109-
return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);
93+
/**
94+
* encode the input data producing a base 64 output stream.
95+
*
96+
* @return the number of bytes produced.
97+
*/
98+
public int Encode(byte[] buf, int off, int len, Stream outStream)
99+
{
100+
byte[] tmp = new byte[72];
101+
while (len > 0)
102+
{
103+
int inLen = System.Math.Min(54, len);
104+
int outLen = Encode(buf, off, inLen, tmp, 0);
105+
outStream.Write(tmp, 0, outLen);
106+
off += inLen;
107+
len -= inLen;
108+
}
109+
return ((len + 2) / 3) * 4;
110110
}
111111

112112
private bool ignore(
@@ -128,8 +128,9 @@ public int Decode(
128128
Stream outStream)
129129
{
130130
byte b1, b2, b3, b4;
131+
byte[] outBuffer = new byte[54]; // S/MIME standard
132+
int bufOff = 0;
131133
int outLen = 0;
132-
133134
int end = off + length;
134135

135136
while (end > off)
@@ -166,16 +167,32 @@ public int Decode(
166167
if ((b1 | b2 | b3 | b4) >= 0x80)
167168
throw new IOException("invalid characters encountered in base64 data");
168169

169-
outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
170-
outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2)));
171-
outStream.WriteByte((byte)((b3 << 6) | b4));
170+
outBuffer[bufOff++] = (byte)((b1 << 2) | (b2 >> 4));
171+
outBuffer[bufOff++] = (byte)((b2 << 4) | (b3 >> 2));
172+
outBuffer[bufOff++] = (byte)((b3 << 6) | b4);
173+
174+
if (bufOff == outBuffer.Length)
175+
{
176+
outStream.Write(outBuffer, 0, bufOff);
177+
bufOff = 0;
178+
}
172179

173180
outLen += 3;
174181

175182
i = nextI(data, i, finish);
176183
}
177184

178-
outLen += decodeLastBlock(outStream, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);
185+
if (bufOff > 0)
186+
{
187+
outStream.Write(outBuffer, 0, bufOff);
188+
}
189+
190+
int e0 = nextI(data, i, end);
191+
int e1 = nextI(data, e0 + 1, end);
192+
int e2 = nextI(data, e1 + 1, end);
193+
int e3 = nextI(data, e2 + 1, end);
194+
195+
outLen += decodeLastBlock(outStream, (char)data[e0], (char)data[e1], (char)data[e2], (char)data[e3]);
179196

180197
return outLen;
181198
}
@@ -208,8 +225,9 @@ public int DecodeString(
208225
// return bytes.Length;
209226

210227
byte b1, b2, b3, b4;
228+
byte[] outBuffer = new byte[54]; // S/MIME standard
229+
int bufOff = 0;
211230
int length = 0;
212-
213231
int end = data.Length;
214232

215233
while (end > 0)
@@ -246,16 +264,32 @@ public int DecodeString(
246264
if ((b1 | b2 | b3 | b4) >= 0x80)
247265
throw new IOException("invalid characters encountered in base64 data");
248266

249-
outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
250-
outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2)));
251-
outStream.WriteByte((byte)((b3 << 6) | b4));
267+
outBuffer[bufOff++] = (byte)((b1 << 2) | (b2 >> 4));
268+
outBuffer[bufOff++] = (byte)((b2 << 4) | (b3 >> 2));
269+
outBuffer[bufOff++] = (byte)((b3 << 6) | b4);
252270

253271
length += 3;
254272

273+
if (bufOff == outBuffer.Length)
274+
{
275+
outStream.Write(outBuffer, 0, bufOff);
276+
bufOff = 0;
277+
}
278+
255279
i = nextI(data, i, finish);
256280
}
257281

258-
length += decodeLastBlock(outStream, data[end - 4], data[end - 3], data[end - 2], data[end - 1]);
282+
if (bufOff > 0)
283+
{
284+
outStream.Write(outBuffer, 0, bufOff);
285+
}
286+
287+
int e0 = nextI(data, i, end);
288+
int e1 = nextI(data, e0 + 1, end);
289+
int e2 = nextI(data, e1 + 1, end);
290+
int e3 = nextI(data, e2 + 1, end);
291+
292+
length += decodeLastBlock(outStream, data[e0], data[e1], data[e2], data[e3]);
259293

260294
return length;
261295
}

crypto/src/util/encoders/HexEncoder.cs

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,40 @@ public HexEncoder()
3939
InitialiseDecodingTable();
4040
}
4141

42+
public int Encode(byte[] inBuf, int inOff, int inLen, byte[] outBuf, int outOff)
43+
{
44+
int inPos = inOff;
45+
int inEnd = inOff + inLen;
46+
int outPos = outOff;
47+
48+
while (inPos < inEnd)
49+
{
50+
uint b = inBuf[inPos++];
51+
52+
outBuf[outPos++] = encodingTable[b >> 4];
53+
outBuf[outPos++] = encodingTable[b & 0xF];
54+
}
55+
56+
return outPos - outOff;
57+
}
58+
4259
/**
4360
* encode the input data producing a Hex output stream.
4461
*
4562
* @return the number of bytes produced.
4663
*/
47-
public int Encode(
48-
byte[] data,
49-
int off,
50-
int length,
51-
Stream outStream)
64+
public int Encode(byte[] buf, int off, int len, Stream outStream)
5265
{
53-
for (int i = off; i < (off + length); i++)
66+
byte[] tmp = new byte[72];
67+
while (len > 0)
5468
{
55-
int v = data[i];
56-
57-
outStream.WriteByte(encodingTable[v >> 4]);
58-
outStream.WriteByte(encodingTable[v & 0xf]);
69+
int inLen = System.Math.Min(36, len);
70+
int outLen = Encode(buf, off, inLen, tmp, 0);
71+
outStream.Write(tmp, 0, outLen);
72+
off += inLen;
73+
len -= inLen;
5974
}
60-
61-
return length * 2;
75+
return len * 2;
6276
}
6377

6478
private static bool Ignore(char c)
@@ -80,6 +94,8 @@ public int Decode(
8094
{
8195
byte b1, b2;
8296
int outLen = 0;
97+
byte[] buf = new byte[36];
98+
int bufOff = 0;
8399
int end = off + length;
84100

85101
while (end > off)
@@ -112,11 +128,22 @@ public int Decode(
112128
if ((b1 | b2) >= 0x80)
113129
throw new IOException("invalid characters encountered in Hex data");
114130

115-
outStream.WriteByte((byte)((b1 << 4) | b2));
131+
buf[bufOff++] = (byte)((b1 << 4) | b2);
132+
133+
if (bufOff == buf.Length)
134+
{
135+
outStream.Write(buf, 0, bufOff);
136+
bufOff = 0;
137+
}
116138

117139
outLen++;
118140
}
119141

142+
if (bufOff > 0)
143+
{
144+
outStream.Write(buf, 0, bufOff);
145+
}
146+
120147
return outLen;
121148
}
122149

@@ -130,10 +157,11 @@ public int DecodeString(
130157
string data,
131158
Stream outStream)
132159
{
133-
byte b1, b2;
134-
int length = 0;
135-
136-
int end = data.Length;
160+
byte b1, b2;
161+
int length = 0;
162+
byte[] buf = new byte[36];
163+
int bufOff = 0;
164+
int end = data.Length;
137165

138166
while (end > 0)
139167
{
@@ -165,11 +193,22 @@ public int DecodeString(
165193
if ((b1 | b2) >= 0x80)
166194
throw new IOException("invalid characters encountered in Hex data");
167195

168-
outStream.WriteByte((byte)((b1 << 4) | b2));
196+
buf[bufOff++] = (byte)((b1 << 4) | b2);
197+
198+
if (bufOff == buf.Length)
199+
{
200+
outStream.Write(buf, 0, bufOff);
201+
bufOff = 0;
202+
}
169203

170204
length++;
171205
}
172206

207+
if (bufOff > 0)
208+
{
209+
outStream.Write(buf, 0, bufOff);
210+
}
211+
173212
return length;
174213
}
175214

0 commit comments

Comments
 (0)