OLD | NEW |
---|---|
1 // Copyright 2013 Google Inc. | 1 // Copyright 2013 Google Inc. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not | 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 | 4 // use this file except in compliance with the License. You may obtain a copy of |
5 // the License at | 5 // the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 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 | 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 | 190 |
191 bool LibLouisWrapper::BackTranslate(const std::string& table_name, | 191 bool LibLouisWrapper::BackTranslate(const std::string& table_name, |
192 const std::vector<unsigned char>& cells, std::string* out) { | 192 const std::vector<unsigned char>& cells, std::string* out) { |
193 std::vector<widechar> inbuf; | 193 std::vector<widechar> inbuf; |
194 inbuf.reserve(cells.size()); | 194 inbuf.reserve(cells.size()); |
195 for (std::vector<unsigned char>::const_iterator it = cells.begin(); | 195 for (std::vector<unsigned char>::const_iterator it = cells.begin(); |
196 it != cells.end(); ++it) { | 196 it != cells.end(); ++it) { |
197 // Set the high-order bit to prevent liblouis from dropping empty cells. | 197 // Set the high-order bit to prevent liblouis from dropping empty cells. |
198 inbuf.push_back(*it | 0x8000); | 198 inbuf.push_back(*it | 0x8000); |
199 } | 199 } |
200 int inlen = inbuf.size(); | 200 // To avoid unsigned/signed comparison warnings. |
201 int outlen = inlen * 2; // TODO(jbroman): choose this size more accurately. | 201 int inbufsize = inbuf.size(); |
202 std::vector<widechar> outbuf(outlen); | 202 std::vector<widechar> outbuf; |
203 int outlen; | |
203 | 204 |
204 // Invoke liblouis. | 205 // Invoke liblouis. Do this in a loop since we can't precalculate the |
205 int result = lou_backTranslateString(table_name.c_str(), | 206 // translated size. We add an extra slot in the output buffer so that |
206 &inbuf[0], &inlen, &outbuf[0], &outlen, | 207 // common cases like single digits or capital letters won't always trigger |
208 // retranslations (see the comments above the second exit condition inside | |
209 // the loop). We also set an arbitrary upper bound for the allocation | |
210 // to make sure the loop exits without running out of memory. | |
211 for (int outalloc = (inbufsize + 1) * 2, maxoutalloc = (inbufsize + 1) * 8; | |
212 outalloc <= maxoutalloc; outalloc *= 2) { | |
213 int inlen = inbufsize; | |
214 outlen = outalloc; | |
215 outbuf.resize(outalloc); | |
216 | |
217 int result = lou_backTranslateString( | |
218 table_name.c_str(), &inbuf[0], &inlen, &outbuf[0], &outlen, | |
207 NULL /* typeform */, NULL /* spacing */, dotsIO /* mode */); | 219 NULL /* typeform */, NULL /* spacing */, dotsIO /* mode */); |
208 if (result == 0) { | 220 if (result == 0) { |
209 // TODO(njbroman): log this | 221 // TODO(jbroman): log this |
210 return false; | 222 return false; |
223 } | |
224 | |
225 // If all of inbuf was not consumed, the output buffer must be too small | |
226 // and we have to retry with a larger buffer. | |
David Tseng
2014/02/27 22:05:07
nit: |inbuf| and smiliarly below.
| |
227 // In addition, if all of outbuf was exhausted, there's no way to know if | |
228 // more space was needed, so we'll have to retry the translation in that | |
229 // corner case as well. | |
230 if (inlen == inbufsize && outlen < outalloc) | |
231 break; | |
232 outbuf.clear(); | |
211 } | 233 } |
212 | 234 |
213 // Massage the result. | 235 // Massage the result. |
214 outbuf.resize(outlen); | 236 outbuf.resize(outlen); |
215 std::string text; | 237 std::string text; |
216 if (!EncodeUtf8(outbuf, &text)) { | 238 if (!EncodeUtf8(outbuf, &text)) { |
217 // TODO(jbroman): log this | 239 // TODO(jbroman): log this |
218 return false; | 240 return false; |
219 } | 241 } |
220 | 242 |
221 // Return the back translation result. | 243 // Return the back translation result. |
222 out->swap(text); | 244 out->swap(text); |
223 return true; | 245 return true; |
224 } | 246 } |
225 | 247 |
226 } // namespace liblouis_nacl | 248 } // namespace liblouis_nacl |
OLD | NEW |