Open Chinese Convert
0.4.3
A project for conversion between Traditional and Simplified Chinese
|
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);