Permalink
Browse files

Improved API and added examples

  • Loading branch information...
dinhoabreu committed Mar 16, 2012
1 parent 5ace01f commit 3d5d2c79cdb6275afd059fe140572223b841bd48
Showing with 163 additions and 85 deletions.
  1. +49 −0 README.md
  2. +1 −1 deps.sh
  3. +37 −0 examples/ex01.js
  4. +34 −30 {lib → }/index.js
  5. +5 −3 package.json
  6. +19 −17 src/{iconv_binding.cc → iconv.cc}
  7. +16 −32 test/index.js
  8. +2 −2 wscript
View
@@ -0,0 +1,49 @@
+# codes
+
+Node.js iconv bindings - Streamable, fast and lightweight
+
+## Installing with [npm](http://npmjs.org/)
+
+ npm install codes
+
+## Usage
+
+Encode from one character encoding to another:
+
+ var assert = require('assert');
+ var codes = require('../index');
+
+ // convert from UTF-8 to ISO-8859-1
+ var str = 'É isso ai. Testando acentuação: áéíóú...';
+ var buffer = codes.encode(str, 'ISO-8859-1//TRANSLIT');
+ var str2 = codes.decode(buffer, 'ISO-8859-1');
+ assert.equal(str, str2);
+
+ // stream from LATIN1 to UTF-8
+ var cs = codes.createStream('UTF-8', 'LATIN1');
+ var str4 = '';
+ cs.on('data', function (data) {
+ var str3 = data.toString();
+ console.log(str3);
+ str4 += str3;
+ });
+ cs.on('end', function () {
+ assert.equal(str4, str);
+ console.log(str4);
+ });
+ cs.on('error', function (error) {
+ console.log(error);
+ });
+ cs.write(buffer.slice(0,1));
+ cs.write(buffer.slice(1,8));
+ cs.write(buffer.slice(8,16));
+ cs.write(buffer.slice(16,24));
+ cs.write(buffer.slice(24, 28));
+ cs.write(buffer.slice(28, 32));
+ cs.write(buffer.slice(32));
+ cs.end();
+
+ // convert from UTF-8 to ASCII
+ var str = 'aéióuçÁEÍOÚC';
+ var ascii = codes.convert(str, 'ASCII//TRANSLIT', 'UTF-8');
+ console.log(str + ' => ' + ascii.toString());
View
@@ -19,7 +19,7 @@ fi
cd deps/libiconv-1.14/
if [ ! -f Makefile ]; then
- ./configure --prefix=$PREFIX --enable-static
+ ./configure --prefix=$PREFIX --enable-static --enable-extra-encodings
fi;
make -s && make -s install
cd -
View
@@ -0,0 +1,37 @@
+var assert = require('assert');
+var codes = require('../index');
+
+// convert from UTF-8 to ISO-8859-1
+var str = 'É isso ai. Testando acentuação: áéíóú...';
+var buffer = codes.encode(str, 'ISO-8859-1//TRANSLIT');
+var str2 = codes.decode(buffer, 'ISO-8859-1');
+assert.equal(str, str2);
+
+// stream from LATIN1 to UTF-8
+var cs = codes.createStream('UTF-8', 'LATIN1');
+var str4 = '';
+cs.on('data', function (data) {
+ var str3 = data.toString();
+ console.log(str3);
+ str4 += str3;
+});
+cs.on('end', function () {
+ assert.equal(str4, str);
+ console.log(str4);
+});
+cs.on('error', function (error) {
+ console.log(error);
+});
+cs.write(buffer.slice(0,1));
+cs.write(buffer.slice(1,8));
+cs.write(buffer.slice(8,16));
+cs.write(buffer.slice(16,24));
+cs.write(buffer.slice(24, 28));
+cs.write(buffer.slice(28, 32));
+cs.write(buffer.slice(32));
+cs.end();
+
+// convert from UTF-8 to ASCII
+var str = 'aéióuçÁEÍOÚC';
+var ascii = codes.convert(str, 'ASCII//TRANSLIT', 'UTF-8');
+console.log(str + ' => ' + ascii.toString());
View
@@ -1,23 +1,21 @@
-var bind = require('../build/Release/iconv_binding');
+var bind = require('./build/Release/iconv');
var stream = require('stream');
var util = require('util');
-function create(options) {
- var from = options.from || 'UTF-8',
- to = options.to,
- size = options.size || 8192,
+function create(to, from, options) {
+ var from = from || 'UTF-8',
+ to = to.split('//'),
+ size = options && options.size || 8192,
iconv;
from = bind.canonicalize(from);
- to = bind.canonicalize(to);
- if (options.option)
- to += options.option;
+ to[0] = bind.canonicalize(to[0]);
+ to = to.join('//');
iconv = new bind.Iconv(to, from);
return {from: from, to: to, size: size, iconv: iconv};
}
-function IconvStream(options) {
- var h = create(options);
- this.options = options;
+function CodesStream(to, from, options) {
+ var h = create(to, from, options);
this._iconv = h.iconv;
this._input = new Buffer(h.size);
this._input.start = 0;
@@ -28,15 +26,15 @@ function IconvStream(options) {
this.readable = true;
this.writable = true;
}
-util.inherits(IconvStream, stream.Stream);
+util.inherits(CodesStream, stream.Stream);
-IconvStream.prototype.write = function (data) {
+CodesStream.prototype.write = function (data) {
if (!this.writable) {
this.emit('error', new Error('stream not writable'))
return false;
}
if (!Buffer.isBuffer(data)) {
- var encoding = 'utf8';
+ var encoding = 'UTF-8';
if (typeof(arguments[1]) == 'string') encoding = arguments[1];
data = new Buffer('' + data, encoding);
}
@@ -54,7 +52,7 @@ IconvStream.prototype.write = function (data) {
return true;
}
-IconvStream.prototype.end = function (data) {
+CodesStream.prototype.end = function (data) {
if (data)
this.write.apply(this, arguments);
if (this.writable) {
@@ -65,7 +63,7 @@ IconvStream.prototype.end = function (data) {
this.writable = false;
}
-IconvStream.prototype._write = function (chunk) {
+CodesStream.prototype._write = function (chunk) {
var input = this._input;
chunk.stop = false;
while (chunk.length > 0 && !chunk.stop)
@@ -78,14 +76,13 @@ IconvStream.prototype._write = function (chunk) {
}
}
-IconvStream.prototype._convert = function (chunk) {
+CodesStream.prototype._convert = function (chunk) {
var iconv = this._iconv;
var output = this._output;
var r = iconv.convert(chunk, output);
- var chunkEnd = chunk.length - r.leftBytesIn;
- var outputEnd = output.length - r.leftBytesOut;
- var chunk = chunk.slice(chunkEnd);
- var data = output.slice(0, outputEnd);
+ var offsetIn = r.offsetIn;
+ var chunk = chunk.slice(offsetIn);
+ var data = output.slice(0, r.offsetOut);
chunk.stop = true;
if (data.length)
this.emit('data', data);
@@ -98,7 +95,7 @@ IconvStream.prototype._convert = function (chunk) {
case 'EILSEQ':
var error = new Error(r.error);
error.code = r.errno;
- chunk = chunk.slice(chunkEnd + 1);
+ chunk = chunk.slice(offsetIn + 1);
this.emit('error', error);
return chunk.slice(0, 0);
break;
@@ -112,18 +109,25 @@ IconvStream.prototype._convert = function (chunk) {
return chunk;
}
-exports.createStream = function (options) {
- return new IconvStream(options);
+exports.CodesStream = CodesStream;
+exports.createStream = function (to, from, options) {
+ return new CodesStream(to, from, options);
}
-exports.convert = function (input, options) {
+exports.convert = function (input, to, from, options) {
if (typeof input == 'string')
- input = new Buffer(input, 'utf8');
- var h = create(options);
- var output = new Buffer(input.length * 2);
+ input = new Buffer(input, 'UTF-8');
+ var h = create(to, from, options);
+ var output = new Buffer(input.length * 4);
var r = h.iconv.convert(input, output);
- var outputEnd = output.length - r.leftBytesOut;
- return output.slice(0, outputEnd);
+ return output.slice(0, r.offsetOut);
+}
+exports.encode = function (input, to, options) {
+ return this.convert(input, to, 'UTF-8', options);
+}
+exports.decode = function (input, from, options) {
+ return this.convert(input, 'UTF-8', from, options).toString();
}
exports.encodings = bind.encodings;
+exports.canonicalize = bind.canonicalize;
exports.TRANSLIT = '//TRANSLIT';
exports.IGNORE = '//IGNORE';
View
@@ -2,12 +2,14 @@
"author": "Edison E. Abreu <dinho.abreu@gmail.com>",
"name": "codes",
"description": "Node.js iconv bindings - Streamable, fast and lightweight",
- "version": "0.0.2",
+ "keywords": "iconv charset encoding encode decode convert code codes stream fast ligthweight",
+ "homepage": "https://github.com/dinhoabreu/codes",
+ "version": "0.1.0",
"repository": {
"type": "git",
"url": "git@github.com:dinhoabreu/codes.git"
},
- "main": "lib/index.js",
+ "main": "index.js",
"scripts": {
"prepublish": "node-waf distclean && rm -rf libiconv",
"preinstall": "./deps.sh",
@@ -20,6 +22,6 @@
},
"optionalDependencies": {},
"engines": {
- "node": "0.6.x"
+ "node": ">=0.6.x"
}
}
@@ -57,15 +57,15 @@ class Iconv {
static void Initialize(Handle<Object> target) {
HandleScope scope;
- push_sym = Persistent<String>::New(String::NewSymbol("push"));
- touppercase_sym = Persistent<String>::New(String::NewSymbol("toUpperCase"));
- convert_sym = Persistent<String>::New(String::NewSymbol("convert"));
- iconv_sym = Persistent<String>::New(String::NewSymbol("Iconv"));
- canonicalize_sym = Persistent<String>::New(String::NewSymbol("canonicalize"));
- encodings_sym = Persistent<String>::New(String::NewSymbol("encodings"));
-
- leftBytesIn_sym = Persistent<String>::New(String::NewSymbol("leftBytesIn"));
- leftBytesOut_sym = Persistent<String>::New(String::NewSymbol("leftBytesOut"));
+ push_sym = Persistent<String>::New(String::NewSymbol("push"));
+ touppercase_sym = Persistent<String>::New(String::NewSymbol("toUpperCase"));
+ convert_sym = Persistent<String>::New(String::NewSymbol("convert"));
+ iconv_sym = Persistent<String>::New(String::NewSymbol("Iconv"));
+ canonicalize_sym = Persistent<String>::New(String::NewSymbol("canonicalize"));
+ encodings_sym = Persistent<String>::New(String::NewSymbol("encodings"));
+
+ offsetIn_sym = Persistent<String>::New(String::NewSymbol("offsetIn"));
+ offsetOut_sym = Persistent<String>::New(String::NewSymbol("offsetOut"));
code_sym = Persistent<String>::New(String::NewSymbol("code"));
errno_sym = Persistent<String>::New(String::NewSymbol("errno"));
error_sym = Persistent<String>::New(String::NewSymbol("error"));
@@ -160,13 +160,15 @@ class Iconv {
Local<Object> target_obj = args[1]->ToObject();
char *source_data = Buffer::Data(source_obj);
size_t source_length = Buffer::Length(source_obj);
+ size_t source_left = source_length;
char *target_data = Buffer::Data(target_obj);
size_t target_length = Buffer::Length(target_obj);
- size_t r = ic->convert(&source_data, &source_length, &target_data, &target_length);
+ size_t target_left = target_length;
+ size_t r = ic->convert(&source_data, &source_left, &target_data, &target_left);
Local<Object> obj = Object::New();
- obj->Set(leftBytesIn_sym, Integer::NewFromUnsigned(source_length));
- obj->Set(leftBytesOut_sym, Integer::NewFromUnsigned(target_length));
+ obj->Set(offsetIn_sym, Integer::NewFromUnsigned(source_length - source_left));
+ obj->Set(offsetOut_sym, Integer::NewFromUnsigned(target_length - target_left));
obj->Set(code_sym, Integer::New(r));
if (r == -1) {
obj->Set(error_sym, String::New(strerror(errno)));
@@ -184,8 +186,8 @@ class Iconv {
return scope.Close(obj);
}
static Persistent<FunctionTemplate> constructor_template;
- static Persistent<String> leftBytesIn_sym;
- static Persistent<String> leftBytesOut_sym;
+ static Persistent<String> offsetIn_sym;
+ static Persistent<String> offsetOut_sym;
static Persistent<String> code_sym;
static Persistent<String> errno_sym;
static Persistent<String> error_sym;
@@ -194,13 +196,13 @@ class Iconv {
};
Persistent<FunctionTemplate> Iconv::constructor_template;
-Persistent<String> Iconv::leftBytesIn_sym;
-Persistent<String> Iconv::leftBytesOut_sym;
+Persistent<String> Iconv::offsetIn_sym;
+Persistent<String> Iconv::offsetOut_sym;
Persistent<String> Iconv::code_sym;
Persistent<String> Iconv::errno_sym;
Persistent<String> Iconv::error_sym;
void init(Handle<Object> target) {
Iconv::Initialize(target);
}
-NODE_MODULE(iconv_binding, init)
+NODE_MODULE(iconv, init)
Oops, something went wrong.

0 comments on commit 3d5d2c7

Please sign in to comment.