Created
February 20, 2011 01:29
-
-
Save isaacs/835585 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From ae20f7804bf5afed1de190f87a05db26bee7fd66 Mon Sep 17 00:00:00 2001 | |
From: isaacs <i@izs.me> | |
Date: Sat, 19 Feb 2011 17:29:01 -0800 | |
Subject: [PATCH] Closes GH-695 Add 'hex' encoding to Buffer | |
--- | |
doc/api/buffers.markdown | 2 + | |
lib/buffer.js | 45 ++++++++++++++++++++++++++++++++++++++++++++ | |
src/node.cc | 3 ++ | |
src/node.h | 2 +- | |
src/node_buffer.cc | 2 + | |
test/simple/test-buffer.js | 31 ++++++++++++++++++++++++++++++ | |
6 files changed, 84 insertions(+), 1 deletions(-) | |
diff --git a/doc/api/buffers.markdown b/doc/api/buffers.markdown | |
index 9c26b61..4fc6890 100644 | |
--- a/doc/api/buffers.markdown | |
+++ b/doc/api/buffers.markdown | |
@@ -26,6 +26,8 @@ the first 8 bits of each character. This encoding method is depreciated and | |
should be avoided in favor of `Buffer` objects where possible. This encoding | |
will be removed in future versions of Node. | |
+* `'hex'` - Encode each byte as two hexidecimal characters. | |
+ | |
### new Buffer(size) | |
diff --git a/lib/buffer.js b/lib/buffer.js | |
index 25db4a5..d5fb174 100644 | |
--- a/lib/buffer.js | |
+++ b/lib/buffer.js | |
@@ -17,6 +17,21 @@ SlowBuffer.prototype.inspect = function() { | |
}; | |
+SlowBuffer.prototype.hexSlice = function(start, end) { | |
+ var len = this.length; | |
+ | |
+ if (!start || start < 0) start = 0; | |
+ if (end < 0 || start + end > len) end = len - start; | |
+ | |
+ var out = ''; | |
+ for (var i = start; i < end; i ++) { | |
+ out += toHex(this[i]); | |
+ } | |
+ return out; | |
+}; | |
+ | |
+ | |
+ | |
SlowBuffer.prototype.toString = function(encoding, start, end) { | |
encoding = String(encoding || 'utf8').toLowerCase(); | |
start = +start || 0; | |
@@ -28,6 +43,9 @@ SlowBuffer.prototype.toString = function(encoding, start, end) { | |
} | |
switch (encoding) { | |
+ case 'hex': | |
+ return this.hexSlice(start, end); | |
+ | |
case 'utf8': | |
case 'utf-8': | |
return this.utf8Slice(start, end); | |
@@ -51,6 +69,23 @@ SlowBuffer.prototype.toString = function(encoding, start, end) { | |
}; | |
+SlowBuffer.prototype.hexWrite = function(string, offset) { | |
+ var len = string.length; | |
+ offset = +offset || 0; | |
+ | |
+ // must be an even number of digits | |
+ if (len % 2) { | |
+ throw new Error('Invalid hex string'); | |
+ } | |
+ for (var i = 0; i < len / 2; i ++) { | |
+ var byte = parseInt(string.substr(i * 2, 2), 16); | |
+ if (isNaN(byte)) throw new Error('Invalid hex string'); | |
+ this[offset + i] = byte; | |
+ } | |
+ return i; | |
+} | |
+ | |
+ | |
SlowBuffer.prototype.write = function(string, offset, encoding) { | |
// Support both (string, offset, encoding) | |
// and the legacy (string, encoding, offset) | |
@@ -64,6 +99,9 @@ SlowBuffer.prototype.write = function(string, offset, encoding) { | |
encoding = String(encoding || 'utf8').toLowerCase(); | |
switch (encoding) { | |
+ case 'hex': | |
+ return this.hexWrite(string, offset); | |
+ | |
case 'utf8': | |
case 'utf-8': | |
return this.utf8Write(string, offset); | |
@@ -224,6 +262,10 @@ Buffer.prototype.write = function(string, offset, encoding) { | |
var ret; | |
switch (encoding) { | |
+ case 'hex': | |
+ ret = this.parent.hexWrite(string, this.offset + offset, maxLength); | |
+ break; | |
+ | |
case 'utf8': | |
case 'utf-8': | |
ret = this.parent.utf8Write(string, this.offset + offset, maxLength); | |
@@ -277,6 +319,9 @@ Buffer.prototype.toString = function(encoding, start, end) { | |
end = end + this.offset; | |
switch (encoding) { | |
+ case 'hex': | |
+ return this.parent.hexSlice(start, end); | |
+ | |
case 'utf8': | |
case 'utf-8': | |
return this.parent.utf8Slice(start, end); | |
diff --git a/src/node.cc b/src/node.cc | |
index 8cc4e82..4e04239 100644 | |
--- a/src/node.cc | |
+++ b/src/node.cc | |
@@ -1084,6 +1084,8 @@ enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) { | |
return UCS2; | |
} else if (strcasecmp(*encoding, "binary") == 0) { | |
return BINARY; | |
+ } else if (strcasecmp(*encoding, "hex") == 0) { | |
+ return HEX; | |
} else if (strcasecmp(*encoding, "raw") == 0) { | |
fprintf(stderr, "'raw' (array of integers) has been removed. " | |
"Use 'binary'.\n"); | |
@@ -1134,6 +1136,7 @@ ssize_t DecodeBytes(v8::Handle<v8::Value> val, enum encoding encoding) { | |
if (encoding == UTF8) return str->Utf8Length(); | |
else if (encoding == UCS2) return str->Length() * 2; | |
+ else if (encoding == HEX) return str->Length() / 2; | |
return str->Length(); | |
} | |
diff --git a/src/node.h b/src/node.h | |
index e2c58d3..4347965 100644 | |
--- a/src/node.h | |
+++ b/src/node.h | |
@@ -44,7 +44,7 @@ do { \ | |
__callback##_TEM); \ | |
} while (0) | |
-enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY}; | |
+enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX}; | |
enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v, | |
enum encoding _default = BINARY); | |
void FatalException(v8::TryCatch &try_catch); | |
diff --git a/src/node_buffer.cc b/src/node_buffer.cc | |
index 8b48f2a..44a6750 100644 | |
--- a/src/node_buffer.cc | |
+++ b/src/node_buffer.cc | |
@@ -86,6 +86,8 @@ static size_t ByteLength (Handle<String> string, enum encoding enc) { | |
return base64_decoded_size(*v, v.length()); | |
} else if (enc == UCS2) { | |
return string->Length() * 2; | |
+ } else if (enc == HEX) { | |
+ return string->Length() / 2; | |
} else { | |
return string->Length(); | |
} | |
diff --git a/test/simple/test-buffer.js b/test/simple/test-buffer.js | |
index 0aad814..f60d29c 100644 | |
--- a/test/simple/test-buffer.js | |
+++ b/test/simple/test-buffer.js | |
@@ -410,3 +410,34 @@ assert.equal(12, Buffer.byteLength('Il était tué', 'binary')); | |
// slice(0,0).length === 0 | |
assert.equal(0, Buffer('hello').slice(0, 0).length); | |
+ | |
+// test hex toString | |
+console.log('Create hex string from buffer'); | |
+var hexb = new Buffer(256); | |
+for (var i = 0; i < 256; i ++) { | |
+ hexb[i] = i; | |
+} | |
+var hexStr = hexb.toString('hex'); | |
+assert.equal(hexStr, | |
+ '000102030405060708090a0b0c0d0e0f'+ | |
+ '101112131415161718191a1b1c1d1e1f'+ | |
+ '202122232425262728292a2b2c2d2e2f'+ | |
+ '303132333435363738393a3b3c3d3e3f'+ | |
+ '404142434445464748494a4b4c4d4e4f'+ | |
+ '505152535455565758595a5b5c5d5e5f'+ | |
+ '606162636465666768696a6b6c6d6e6f'+ | |
+ '707172737475767778797a7b7c7d7e7f'+ | |
+ '808182838485868788898a8b8c8d8e8f'+ | |
+ '909192939495969798999a9b9c9d9e9f'+ | |
+ 'a0a1a2a3a4a5a6a7a8a9aaabacadaeaf'+ | |
+ 'b0b1b2b3b4b5b6b7b8b9babbbcbdbebf'+ | |
+ 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf'+ | |
+ 'd0d1d2d3d4d5d6d7d8d9dadbdcdddedf'+ | |
+ 'e0e1e2e3e4e5e6e7e8e9eaebecedeeef'+ | |
+ 'f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'); | |
+ | |
+console.log('Create buffer from hex string'); | |
+var hexb2 = new Buffer(hexStr, 'hex'); | |
+for (var i = 0; i < 256; i ++) { | |
+ assert.equal(hexb2[i], hexb[i]); | |
+} | |
-- | |
1.7.2.3 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment