Chromium Code Reviews| Index: third_party/liblouis/nacl_wrapper/liblouis_wrapper.cc |
| diff --git a/third_party/liblouis/nacl_wrapper/liblouis_wrapper.cc b/third_party/liblouis/nacl_wrapper/liblouis_wrapper.cc |
| index 67c6341dd76ebfce2a943fa68428a1534b75fb14..2fff14edf39104e533266e5857d06c51262f8d9e 100644 |
| --- a/third_party/liblouis/nacl_wrapper/liblouis_wrapper.cc |
| +++ b/third_party/liblouis/nacl_wrapper/liblouis_wrapper.cc |
| @@ -197,17 +197,39 @@ bool LibLouisWrapper::BackTranslate(const std::string& table_name, |
| // Set the high-order bit to prevent liblouis from dropping empty cells. |
| inbuf.push_back(*it | 0x8000); |
| } |
| - int inlen = inbuf.size(); |
| - int outlen = inlen * 2; // TODO(jbroman): choose this size more accurately. |
| - std::vector<widechar> outbuf(outlen); |
| + // To avoid unsigned/signed comparison warnings. |
| + int inbufsize = inbuf.size(); |
| + std::vector<widechar> outbuf; |
| + int outlen; |
| + |
| + // Invoke liblouis. Do this in a loop since we can't precalculate the |
| + // translated size. We add an extra slot in the output buffer so that |
| + // common cases like single digits or capital letters won't always trigger |
| + // retranslations (see the comments above the second exit condition inside |
| + // the loop). We also set an arbitrary upper bound for the allocation |
| + // to make sure the loop exits without running out of memory. |
| + for (int outalloc = (inbufsize + 1) * 2, maxoutalloc = (inbufsize + 1) * 8; |
| + outalloc <= maxoutalloc; outalloc *= 2) { |
| + int inlen = inbufsize; |
| + outlen = outalloc; |
| + outbuf.resize(outalloc); |
| - // Invoke liblouis. |
| - int result = lou_backTranslateString(table_name.c_str(), |
| - &inbuf[0], &inlen, &outbuf[0], &outlen, |
| + int result = lou_backTranslateString( |
| + table_name.c_str(), &inbuf[0], &inlen, &outbuf[0], &outlen, |
| NULL /* typeform */, NULL /* spacing */, dotsIO /* mode */); |
| - if (result == 0) { |
| - // TODO(njbroman): log this |
| - return false; |
| + if (result == 0) { |
| + // TODO(jbroman): log this |
| + return false; |
| + } |
| + |
| + // If all of inbuf was not consumed, the output buffer must be too small |
| + // and we have to retry with a larger buffer. |
|
David Tseng
2014/02/27 22:05:07
nit: |inbuf| and smiliarly below.
|
| + // In addition, if all of outbuf was exhausted, there's no way to know if |
| + // more space was needed, so we'll have to retry the translation in that |
| + // corner case as well. |
| + if (inlen == inbufsize && outlen < outalloc) |
| + break; |
| + outbuf.clear(); |
| } |
| // Massage the result. |