Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(343)

Side by Side Diff: third_party/liblouis/nacl_wrapper/liblouis_instance.cc

Issue 67283007: Build liblouis_nacl using gyp. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Build failure fixes. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "liblouis_instance.h"
16
17 #include <cstring>
18 #include <sys/mount.h>
19 #include <vector>
20
21 #include "nacl_io/nacl_io.h"
22 #include "ppapi/c/pp_errors.h"
23 #include "ppapi/cpp/module.h"
24
25 #include "translation_result.h"
26
27 namespace {
28
29 static const char kHexadecimalChars[] = "0123456789abcdef";
30
31 // Converts a vector of bytes into a (lowercase) hexadecimal string.
32 static void BytesToHexString(const std::vector<unsigned char>& bytes,
33 std::string* out) {
34 std::string hex;
35 hex.reserve(bytes.size() * 2);
36 for (size_t i = 0; i < bytes.size(); ++i) {
37 unsigned char byte = bytes[i];
38 hex.push_back(kHexadecimalChars[byte >> 4]);
39 hex.push_back(kHexadecimalChars[byte & 0x0f]);
40 }
41 out->swap(hex);
42 }
43
44 // Converts a hexadecimal string to a vector of bytes.
45 // Returns false on failure.
46 static bool HexStringToBytes(const std::string& hex,
47 std::vector<unsigned char>* out) {
48 if (hex.size() % 2 != 0) {
49 return false;
50 }
51
52 std::vector<unsigned char> bytes;
53 bytes.reserve(hex.size() / 2);
54 for (size_t i = 0; i < hex.size(); i += 2) {
55 unsigned char byte;
56 char ch = hex[i];
57 if ('0' <= ch && ch <= '9') {
58 byte = (ch - '0') << 4;
59 } else if ('a' <= ch && ch <= 'f') {
60 byte = (ch - 'a' + 10) << 4;
61 } else if ('A' <= ch && ch <= 'F') {
62 byte = (ch - 'A' + 10) << 4;
63 } else {
64 return false;
65 }
66 ch = hex[i+1];
67 if ('0' <= ch && ch <= '9') {
68 byte |= ch - '0';
69 } else if ('a' <= ch && ch <= 'f') {
70 byte |= ch - 'a' + 10;
71 } else if ('A' <= ch && ch <= 'F') {
72 byte |= ch - 'A' + 10;
73 } else {
74 return false;
75 }
76 bytes.push_back(byte);
77 }
78 out->swap(bytes);
79 return true;
80 }
81
82 template <typename T>
83 static void CopyVectorToJson(const std::vector<T>& vec, Json::Value* out) {
84 Json::Value result(Json::arrayValue);
85 result.resize(vec.size());
86 for (size_t i = 0; i < vec.size(); ++i) {
87 result[i] = vec[i];
88 }
89 out->swap(result);
90 }
91
92 } // namespace
93
94
95 namespace liblouis_nacl {
96
97 // Well-known strings used for configuration.
98 static const char kTablesDirKey[] = "tablesdir";
99 static const char kTablesDirDefault[] = "tables";
100
101 // Well-known strings used in JSON messages.
102 static const char kCommandKey[] = "command";
103 static const char kMessageIdKey[] = "message_id";
104 static const char kInReplyToKey[] = "in_reply_to";
105 static const char kErrorKey[] = "error";
106 static const char kTableNameKey[] = "table_name";
107 static const char kSuccessKey[] = "success";
108 static const char kTextKey[] = "text";
109 static const char kCellsKey[] = "cells";
110 static const char kCursorPositionKey[] = "cursor_position";
111 static const char kTextToBrailleKey[] = "text_to_braille";
112 static const char kBrailleToTextKey[] = "braille_to_text";
113 static const char kCheckTableCommand[] = "CheckTable";
114 static const char kTranslateCommand[] = "Translate";
115 static const char kBackTranslateCommand[] = "BackTranslate";
116
117 LibLouisInstance::LibLouisInstance(PP_Instance instance)
118 : pp::Instance(instance), liblouis_thread_(this), cc_factory_(this) {}
119
120 LibLouisInstance::~LibLouisInstance() {}
121
122 bool LibLouisInstance::Init(uint32_t argc, const char* argn[],
123 const char* argv[]) {
124 const char* tables_dir = kTablesDirDefault;
125 for (size_t i = 0; i < argc; ++i) {
126 if (strcmp(argn[i], kTablesDirKey) == 0) {
127 tables_dir = argv[i];
128 }
129 }
130
131 nacl_io_init_ppapi(pp_instance(),
132 pp::Module::Get()->get_browser_interface());
133 if (mount(tables_dir, liblouis_.tables_dir(), "httpfs", 0, "") != 0) {
134 // TODO(jbroman): report this error.
135 return false;
136 }
137
138 return liblouis_thread_.Start();
139 }
140
141 void LibLouisInstance::HandleMessage(const pp::Var& var_message) {
142 if (!var_message.is_string()) {
143 PostError("expected message to be a JSON string");
144 return;
145 }
146
147 Json::Value message;
148 Json::Reader reader;
149 bool parsed = reader.parse(var_message.AsString(),
150 message, false /* collectComments */);
151 if (!parsed) {
152 PostError("expected message to be a JSON string");
153 return;
154 }
155
156 Json::Value message_id = message[kMessageIdKey];
157 if (!message_id.isString()) {
158 PostError("expected message_id string");
159 return;
160 }
161 std::string message_id_str = message_id.asString();
162
163 Json::Value command = message[kCommandKey];
164 if (!command.isString()) {
165 PostError("expected command string", message_id_str);
166 return;
167 }
168
169 std::string command_str = command.asString();
170 if (command_str == kCheckTableCommand) {
171 HandleCheckTable(message, message_id_str);
172 } else if (command_str == kTranslateCommand) {
173 HandleTranslate(message, message_id_str);
174 } else if (command_str == kBackTranslateCommand) {
175 HandleBackTranslate(message, message_id_str);
176 } else {
177 PostError("unknown command", message_id_str);
178 }
179 }
180
181 void LibLouisInstance::PostReply(Json::Value reply,
182 const std::string& in_reply_to) {
183 Json::FastWriter writer;
184 reply[kInReplyToKey] = in_reply_to;
185 pp::Var var_reply(writer.write(reply));
186 PostMessage(var_reply);
187 }
188
189 void LibLouisInstance::PostError(const std::string& error_message) {
190 Json::FastWriter writer;
191 Json::Value reply(Json::objectValue);
192 reply[kErrorKey] = error_message;
193 pp::Var var_reply(writer.write(reply));
194 PostMessage(var_reply);
195 }
196
197 void LibLouisInstance::PostError(const std::string& error_message,
198 const std::string& in_reply_to) {
199 Json::FastWriter writer;
200 Json::Value reply(Json::objectValue);
201 reply[kErrorKey] = error_message;
202 reply[kInReplyToKey] = in_reply_to;
203 reply[kSuccessKey] = false;
204 pp::Var var_reply(writer.write(reply));
205 PostMessage(var_reply);
206 }
207
208 void LibLouisInstance::HandleCheckTable(const Json::Value& message,
209 const std::string& message_id) {
210 Json::Value table_name = message[kTableNameKey];
211 if (!table_name.isString()) {
212 PostError("expected table_name to be a string", message_id);
213 return;
214 }
215 PostWorkToBackground(cc_factory_.NewCallback(
216 &LibLouisInstance::CheckTableInBackground,
217 table_name.asString(), message_id));
218 }
219
220 void LibLouisInstance::CheckTableInBackground(int32_t result,
221 const std::string& table_name, const std::string& message_id) {
222 if (result != PP_OK) {
223 PostError("failed to transfer call to background thread", message_id);
224 return;
225 }
226 bool success = liblouis_.CheckTable(table_name);
227 Json::Value reply(Json::objectValue);
228 reply[kSuccessKey] = success;
229 PostReply(reply, message_id);
230 }
231
232 void LibLouisInstance::HandleTranslate(const Json::Value& message,
233 const std::string& message_id) {
234 Json::Value table_name = message[kTableNameKey];
235 Json::Value text = message[kTextKey];
236 Json::Value cursor_position = message[kCursorPositionKey];
237 if (!table_name.isString()) {
238 PostError("expected table_name to be a string", message_id);
239 return;
240 } else if (!text.isString()) {
241 PostError("expected text to be a string", message_id);
242 return;
243 } else if (!cursor_position.isNull() && !cursor_position.isIntegral()) {
244 PostError("expected cursor_position to be null or integral", message_id);
245 return;
246 }
247 TranslationParams params;
248 params.table_name = table_name.asString();
249 params.text = text.asString();
250 params.cursor_position = cursor_position.isIntegral() ?
251 cursor_position.asInt() : -1;
252 PostWorkToBackground(cc_factory_.NewCallback(
253 &LibLouisInstance::TranslateInBackground,
254 params, message_id));
255 }
256
257 void LibLouisInstance::TranslateInBackground(int32_t result,
258 const TranslationParams& params, const std::string& message_id) {
259 if (result != PP_OK) {
260 PostError("failed to transfer call to background thread", message_id);
261 return;
262 }
263 TranslationResult translation_result;
264 bool success = liblouis_.Translate(params, &translation_result);
265 Json::Value reply(Json::objectValue);
266 reply[kSuccessKey] = success;
267 if (success) {
268 std::string hex_cells;
269 Json::Value text_to_braille;
270 Json::Value braille_to_text;
271 BytesToHexString(translation_result.cells, &hex_cells);
272 CopyVectorToJson(translation_result.text_to_braille, &text_to_braille);
273 CopyVectorToJson(translation_result.braille_to_text, &braille_to_text);
274 reply[kCellsKey] = hex_cells;
275 reply[kTextToBrailleKey] = text_to_braille;
276 reply[kBrailleToTextKey] = braille_to_text;
277 if (translation_result.cursor_position >= 0) {
278 reply[kCursorPositionKey] = translation_result.cursor_position;
279 }
280 }
281 PostReply(reply, message_id);
282 }
283
284 void LibLouisInstance::HandleBackTranslate(const Json::Value& message,
285 const std::string& message_id) {
286 Json::Value table_name = message[kTableNameKey];
287 Json::Value cells = message[kCellsKey];
288 if (!table_name.isString()) {
289 PostError("expected table_name to be a string", message_id);
290 return;
291 } else if (!cells.isString()) {
292 PostError("expected cells to be a string", message_id);
293 return;
294 }
295 std::vector<unsigned char> cells_vector;
296 if (!HexStringToBytes(cells.asString(), &cells_vector)) {
297 PostError("expected cells to be a valid hexadecimal string", message_id);
298 return;
299 }
300 PostWorkToBackground(cc_factory_.NewCallback(
301 &LibLouisInstance::BackTranslateInBackground,
302 table_name.asString(), cells_vector, message_id));
303 }
304
305 void LibLouisInstance::BackTranslateInBackground(int32_t result,
306 const std::string& table_name, const std::vector<unsigned char>& cells,
307 const std::string& message_id) {
308 if (result != PP_OK) {
309 PostError("failed to transfer call to background thread", message_id);
310 return;
311 }
312 std::string text;
313 bool success = liblouis_.BackTranslate(table_name, cells, &text);
314 Json::Value reply(Json::objectValue);
315 reply[kSuccessKey] = success;
316 if (success) {
317 reply[kTextKey] = text;
318 }
319 PostReply(reply, message_id);
320 }
321
322 } // namespace liblouis_nacl
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698