Open Chinese Convert  0.4.3
A project for conversion between Traditional and Simplified Chinese
/usr/src/RPM/BUILD/opencc-0.4.3/node/binding.cc
00001 #include <iostream>
00002 #include <node.h>
00003 #include <v8.h>
00004 #include "../src/opencc.h"
00005 
00006 using namespace v8;
00007 
00008 char* ToUtf8String(const Local<String>& str) {
00009   char* utf8 = new char[str->Utf8Length() + 1];
00010   utf8[str->Utf8Length()] = '\0';
00011   str->WriteUtf8(utf8);
00012   return utf8;
00013 }
00014 
00015 class OpenccBinding : public node::ObjectWrap {
00016   struct ConvertRequest {
00017     OpenccBinding* opencc_instance;
00018     char* input;
00019     char* output;
00020     Persistent<Function> callback;
00021   };
00022  public:
00023   explicit OpenccBinding(const char * config_file) {
00024     handler_ = opencc_open(config_file);
00025   }
00026 
00027   virtual ~OpenccBinding() {
00028     if (handler_ != (opencc_t) -1)
00029       opencc_close(handler_);
00030   }
00031 
00032   operator bool() const {
00033     return handler_ != (opencc_t) -1;
00034   }
00035 
00036   static Handle<Value> New(const Arguments& args) {
00037     HandleScope scope;
00038     OpenccBinding* opencc_instance;
00039 
00040     if (args.Length() >= 1 && args[0]->IsString()) {
00041       char* config_file = ToUtf8String(args[0]->ToString());
00042       opencc_instance = new OpenccBinding(config_file);
00043       delete[] config_file;
00044     } else {
00045       const char* config_file = OPENCC_DEFAULT_CONFIG_SIMP_TO_TRAD;
00046       opencc_instance = new OpenccBinding(config_file);
00047     }
00048 
00049     if (!*opencc_instance) {
00050       ThrowException(Exception::Error(
00051           String::New("Can not create opencc instance")));
00052       return scope.Close(Undefined());
00053     }
00054     opencc_instance->Wrap(args.This());
00055     return args.This();
00056   }
00057 
00058   static Handle<Value> Convert(const Arguments& args) {
00059     HandleScope scope;
00060     if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsFunction()) {
00061       ThrowException(Exception::TypeError(String::New("Wrong arguments")));
00062       return scope.Close(Undefined());
00063     }
00064 
00065     ConvertRequest* conv_data = new ConvertRequest;
00066     conv_data->opencc_instance = ObjectWrap::Unwrap<OpenccBinding>(args.This());
00067     conv_data->input = ToUtf8String(args[0]->ToString());
00068     conv_data->callback = Persistent<Function>::New(Local<Function>::Cast(args[1]));
00069     uv_work_t* req = new uv_work_t;
00070     req->data = conv_data;
00071     uv_queue_work(uv_default_loop(), req, DoConnect, (uv_after_work_cb)AfterConvert);
00072 
00073     return Undefined();
00074   }
00075   
00076   static void DoConnect(uv_work_t* req) {
00077     ConvertRequest* conv_data = static_cast<ConvertRequest*>(req->data);
00078     opencc_t opencc_handler = conv_data->opencc_instance->handler_;
00079     conv_data->output = opencc_convert_utf8(opencc_handler, conv_data->input, (size_t) -1);
00080   }
00081 
00082   static void AfterConvert(uv_work_t* req) {
00083     HandleScope scope;
00084     ConvertRequest* conv_data = static_cast<ConvertRequest*>(req->data);
00085     Local<String> converted = String::New(conv_data->output);
00086     const unsigned argc = 2;
00087     Local<Value> argv[argc] = {
00088       Local<Value>::New(Undefined()),
00089       Local<Value>::New(converted)
00090     };
00091     conv_data->callback->Call(Context::GetCurrent()->Global(), argc, argv);
00092     conv_data->callback.Dispose();
00093     delete[] conv_data->input;
00094     opencc_convert_utf8_free(conv_data->output);
00095     delete conv_data;
00096     delete req;
00097   }
00098 
00099   static Handle<Value> ConvertSync(const Arguments& args) {
00100     HandleScope scope;
00101     if (args.Length() < 1 || !args[0]->IsString()) {
00102       ThrowException(Exception::TypeError(String::New("Wrong arguments")));
00103       return scope.Close(Undefined());
00104     }
00105 
00106     OpenccBinding* opencc_instance = ObjectWrap::Unwrap<OpenccBinding>(args.This());
00107     opencc_t opencc_handler = opencc_instance->handler_;
00108     char* input = ToUtf8String(args[0]->ToString());
00109     char* output = opencc_convert_utf8(opencc_handler, input, (size_t) -1);
00110 
00111     Local<String> converted = String::New(output);
00112     delete[] input;
00113     opencc_convert_utf8_free(output);
00114     return scope.Close(converted);
00115   }
00116 
00117   static Handle<Value> SetConversionMode(const Arguments& args) {
00118     HandleScope scope;
00119     if (args.Length() < 1 || !args[0]->IsInt32()) {
00120       ThrowException(Exception::TypeError(String::New("Wrong arguments")));
00121       return scope.Close(Undefined());
00122     }
00123 
00124     OpenccBinding* opencc_instance = ObjectWrap::Unwrap<OpenccBinding>(args.This());
00125     opencc_t opencc_handler = opencc_instance->handler_;
00126     int conversion_mode = args[0]->ToInt32()->Value();
00127     if (conversion_mode < 0 || conversion_mode > 2) {
00128       ThrowException(Exception::Error(
00129           String::New("conversion_mode must between 0 and 2")));
00130       return scope.Close(Undefined());
00131     }
00132 
00133     opencc_set_conversion_mode(opencc_handler,
00134                                (opencc_conversion_mode) conversion_mode);
00135     return scope.Close(Boolean::New(true));
00136   }
00137 
00138   static void init(Handle<Object> target) {
00139     // Prepare constructor template
00140     Local<FunctionTemplate> tpl = FunctionTemplate::New(OpenccBinding::New);
00141     tpl->SetClassName(String::NewSymbol("Opencc"));
00142     tpl->InstanceTemplate()->SetInternalFieldCount(1);
00143     // Prototype
00144     tpl->PrototypeTemplate()->Set(String::NewSymbol("convert"),
00145         FunctionTemplate::New(Convert)->GetFunction());
00146     tpl->PrototypeTemplate()->Set(String::NewSymbol("convertSync"),
00147         FunctionTemplate::New(ConvertSync)->GetFunction());
00148     tpl->PrototypeTemplate()->Set(String::NewSymbol("setConversionMode"),
00149         FunctionTemplate::New(SetConversionMode)->GetFunction());
00150     // Constructor
00151     Persistent<Function> constructor = Persistent<Function>::New(
00152         tpl->GetFunction());
00153     target->Set(String::NewSymbol("Opencc"), constructor);
00154   }
00155 
00156   opencc_t handler_;
00157 };
00158 
00159 void init(Handle<Object> target) {
00160   OpenccBinding::init(target);
00161 }
00162 
00163 NODE_MODULE(binding, init);
 All Data Structures Files Functions Variables Defines