1+ #include < memory>
2+ #include < string>
3+
14#include " compact_lang_det.h"
25#include " encodings.h"
36#include " constants.h"
@@ -9,73 +12,98 @@ using std::unexpected_handler;
912#include < napi.h>
1013
1114namespace NodeCld {
12- Napi::Object Detect (const Napi::CallbackInfo& info) {
15+ struct CLDInput {
16+ std::string bytes,
17+ languageHint,
18+ encodingHint,
19+ tldHint,
20+ httpHint;
21+ int numBytes;
22+ bool isPlainText;
23+ };
24+
25+ struct CLDOutput {
26+ CLD2::Language language3[3 ];
27+ int percent3[3 ];
28+ double normalized_score3[3 ];
29+ CLD2::ResultChunkVector resultChunkVector;
30+ int textBytesFound;
31+ bool isReliable;
32+ };
33+
34+ std::unique_ptr<CLDInput> UnpackInputFromJSArgs (const Napi::CallbackInfo &info) {
1335 auto env = info.Env ();
36+ std::unique_ptr<CLDInput> input (new CLDInput);
37+
38+ input->bytes = info[0 ].ToString ().Utf8Value ();
39+ input->numBytes = input->bytes .length ();
40+ input->isPlainText = info[1 ].ToBoolean ();
1441
15- std::string text = info[0 ].ToString ().Utf8Value ();
16- const char *bytes = text.c_str ();
17- int numBytes = text.length ();
18- bool isPlainText = info[1 ].ToBoolean ();
42+ if (info[2 ].IsString ()) {
43+ input->languageHint = info[2 ].ToString ().Utf8Value ();
44+ }
45+
46+ if (info[3 ].IsString ()) {
47+ input->encodingHint = info[3 ].ToString ().Utf8Value ();
48+ }
1949
50+ if (info[4 ].IsString ()) {
51+ input->tldHint = info[4 ].ToString ().Utf8Value ();
52+ }
53+
54+ if (info[5 ].IsString ()) {
55+ input->httpHint = info[5 ].ToString ().Utf8Value ();
56+ }
57+
58+ return input;
59+ }
60+
61+ std::unique_ptr<CLDOutput> DetectLanguage (std::unique_ptr<CLDInput> input) {
62+ std::unique_ptr<CLDOutput> output (new CLDOutput);
2063 CLD2::CLDHints hints;
2164 hints.tld_hint = 0 ;
2265 hints.content_language_hint = 0 ;
2366 hints.language_hint = CLD2::UNKNOWN_LANGUAGE;
2467 hints.encoding_hint = CLD2::UNKNOWN_ENCODING;
2568
26-
27- if (info[2 ].IsString ()) {
28- std::string languageHint = info[2 ].ToString ().Utf8Value ();
29- if (languageHint.length () > 0 ) {
30- hints.language_hint = Constants::getInstance ().getLanguageFromName (languageHint.c_str ());
31- }
69+ if (input->languageHint .length () > 0 ) {
70+ hints.language_hint = Constants::getInstance ().getLanguageFromName (input->languageHint .c_str ());
3271 }
3372
34- if (info[3 ].IsString ()) {
35- std::string encodingHint = info[3 ].ToString ().Utf8Value ();
36- if (encodingHint.length () > 0 ) {
37- hints.encoding_hint = Constants::getInstance ().getEncodingFromName (encodingHint.c_str ());
38- }
73+ if (input->encodingHint .length () > 0 ) {
74+ hints.encoding_hint = Constants::getInstance ().getEncodingFromName (input->encodingHint .c_str ());
3975 }
4076
41- if (info[4 ].IsString ()) {
42- std::string tldHint = info[4 ].ToString ().Utf8Value ();
43- if (tldHint.length () > 0 ) {
44- hints.tld_hint = tldHint.c_str ();
45- }
77+ if (input->tldHint .length () > 0 ) {
78+ hints.tld_hint = input->tldHint .c_str ();
4679 }
4780
48- if (info[5 ].IsString ()) {
49- std::string httpHint = info[5 ].ToString ().Utf8Value ();
50- if (httpHint.length () > 0 ) {
51- hints.content_language_hint = httpHint.c_str ();
52- }
81+ if (input->httpHint .length () > 0 ) {
82+ hints.content_language_hint = input->httpHint .c_str ();
5383 }
5484
55- CLD2::Language language3[3 ];
56- int percent3[3 ];
57- double normalized_score3[3 ];
58- CLD2::ResultChunkVector resultChunkVector;
59- int textBytesFound;
60- bool isReliable;
61-
6285 CLD2::ExtDetectLanguageSummary (
63- bytes, numBytes,
64- isPlainText,
86+ input->bytes .c_str (),
87+ input->numBytes ,
88+ input->isPlainText ,
6589 &hints,
6690 0 ,
67- language3,
68- percent3,
69- normalized_score3,
70- &resultChunkVector,
71- &textBytesFound,
72- &isReliable
91+ output-> language3 ,
92+ output-> percent3 ,
93+ output-> normalized_score3 ,
94+ &output-> resultChunkVector ,
95+ &output-> textBytesFound ,
96+ &output-> isReliable
7397 );
7498
99+ return output;
100+ }
101+
102+ Napi::Object UnpackOutputToJS (const Napi::Env env, std::unique_ptr<CLDOutput> output) {
75103 size_t languageIdx = 0 ;
76104 auto languages = Napi::Array::New (env);
77105 for (size_t resultIdx = 0 ; resultIdx < 3 ; resultIdx++) {
78- CLD2::Language lang = language3[resultIdx];
106+ CLD2::Language lang = output-> language3 [resultIdx];
79107
80108 if (lang == CLD2::UNKNOWN_LANGUAGE) {
81109 continue ;
@@ -84,16 +112,16 @@ namespace NodeCld {
84112 auto item = Napi::Object::New (env);
85113 item[" name" ] = Napi::String::New (env, Constants::getInstance ().getLanguageName (lang));
86114 item[" code" ] = Napi::String::New (env, Constants::getInstance ().getLanguageCode (lang));
87- item[" percent" ] = Napi::Number::New (env, percent3[resultIdx]);
88- item[" score" ] = Napi::Number::New (env, normalized_score3[resultIdx]);
115+ item[" percent" ] = Napi::Number::New (env, output-> percent3 [resultIdx]);
116+ item[" score" ] = Napi::Number::New (env, output-> normalized_score3 [resultIdx]);
89117
90118 languages[languageIdx++] = item;
91119 }
92120
93121 size_t chunkIdx = 0 ;
94122 auto chunks = Napi::Array::New (env);
95- for (size_t resultIdx = 0 ; resultIdx < resultChunkVector.size (); resultIdx++) {
96- CLD2::ResultChunk chunk = resultChunkVector.at (resultIdx);
123+ for (size_t resultIdx = 0 ; resultIdx < output-> resultChunkVector .size (); resultIdx++) {
124+ CLD2::ResultChunk chunk = output-> resultChunkVector .at (resultIdx);
97125 CLD2::Language lang = static_cast <CLD2::Language>(chunk.lang1 );
98126
99127 if (lang == CLD2::UNKNOWN_LANGUAGE) {
@@ -110,14 +138,51 @@ namespace NodeCld {
110138 }
111139
112140 auto results = Napi::Object::New (env);
113- results[" reliable" ] = Napi::Boolean::New (env, isReliable);
114- results[" textBytes" ] = Napi::Number::New (env, textBytesFound);
141+ results[" reliable" ] = Napi::Boolean::New (env, output-> isReliable );
142+ results[" textBytes" ] = Napi::Number::New (env, output-> textBytesFound );
115143 results[" languages" ] = languages;
116144 results[" chunks" ] = chunks;
117145
118146 return results;
119147 }
120148
149+ class DetectAsyncWorker : public Napi ::AsyncWorker {
150+ public:
151+ DetectAsyncWorker (const Napi::CallbackInfo &info):
152+ Napi::AsyncWorker (info.Env()),
153+ deferred (Napi::Promise::Deferred::New(info.Env())),
154+ mInput (UnpackInputFromJSArgs(info))
155+ {}
156+
157+ void Execute () {
158+ mOutput = DetectLanguage (std::move (mInput ));
159+ }
160+
161+ void OnOK () {
162+ deferred.Resolve (UnpackOutputToJS (Env (), std::move (mOutput )));
163+ }
164+
165+ Napi::Promise Promise () {
166+ this ->Queue ();
167+ return deferred.Promise ();
168+ }
169+
170+ private:
171+ Napi::Promise::Deferred deferred;
172+ std::unique_ptr<CLDInput> mInput ;
173+ std::unique_ptr<CLDOutput> mOutput ;
174+ };
175+
176+ Napi::Object Detect (const Napi::CallbackInfo &info) {
177+ auto input = UnpackInputFromJSArgs (info);
178+ auto output = DetectLanguage (std::move (input));
179+ return UnpackOutputToJS (info.Env (), std::move (output));
180+ }
181+
182+ Napi::Promise DetectAsync (const Napi::CallbackInfo &info) {
183+ return (new DetectAsyncWorker (info))->Promise ();
184+ }
185+
121186 Napi::Object Init (Napi::Env env, Napi::Object exports) {
122187 auto rawDetected = Constants::getInstance ().getDetected ();
123188 auto numDetected = rawDetected->size ();
@@ -146,7 +211,7 @@ namespace NodeCld {
146211 exports[" ENCODINGS" ] = encodings;
147212
148213 exports[" detect" ] = Napi::Function::New (env, Detect);
149-
214+ exports[ " detectAsync " ] = Napi::Function::New (env, DetectAsync);
150215 return exports;
151216 }
152217
0 commit comments