Allow braille translation result to be larger than twice the size of the input.

The liblouis wrapper used to allocate an output buffer that was twice as big
as the number of input characters.  There are situations where this is
not enough.  The new approach is to retry with a larger buffer up to
a certain limit.

R=dtseng@chromium.org
BUG=none

Review URL: https://codereview.chromium.org/124403002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@243251 0039d316-1c4b-4281-b951-d872f2087c98
parent cd863872
...@@ -42,7 +42,7 @@ function rpc(command, args, callback) { ...@@ -42,7 +42,7 @@ function rpc(command, args, callback) {
var messageId = '' + nextMessageId++; var messageId = '' + nextMessageId++;
args['command'] = command; args['command'] = command;
args['message_id'] = messageId; args['message_id'] = messageId;
var json = JSON.stringify(args) var json = JSON.stringify(args);
console.log('Message to liblouis: ' + json); console.log('Message to liblouis: ' + json);
naclEmbed.postMessage(json); naclEmbed.postMessage(json);
pendingCallback = callback; pendingCallback = callback;
...@@ -76,6 +76,17 @@ loadLibrary(function() { ...@@ -76,6 +76,17 @@ loadLibrary(function() {
}))); })));
}, },
// Regression test for the case where the translated result is more than
// the double size of the input. In this particular case, a single capital
// letter 'T' should be translated to 3 cells in US English grade 2
// braille (dots 56, 6, 2345).
function testTranslateGrade2SingleCapital() {
rpc('Translate', { 'table_name': 'en-us-g2.ctb', 'text': 'T'},
pass(expectSuccessReply(function(reply) {
chrome.test.assertEq('30201e', reply['cells']);
})));
},
function testBackTranslateString() { function testBackTranslateString() {
rpc('BackTranslate', { 'table_name': TABLE_NAME, 'cells': CELLS}, rpc('BackTranslate', { 'table_name': TABLE_NAME, 'cells': CELLS},
pass(expectSuccessReply(function(reply) { pass(expectSuccessReply(function(reply) {
......
...@@ -121,12 +121,13 @@ bool LibLouisWrapper::Translate(const TranslationParams& params, ...@@ -121,12 +121,13 @@ bool LibLouisWrapper::Translate(const TranslationParams& params,
// TODO(jbroman): log this // TODO(jbroman): log this
return false; return false;
} }
// To avoid unsigned/signed comparison warnings.
int inbufsize = inbuf.size();
int inlen = inbuf.size(); std::vector<widechar> outbuf;
int outlen = inlen * 2; // TODO(jbroman): choose this size more accurately. std::vector<int> text_to_braille(inbuf.size());
std::vector<widechar> outbuf(outlen); std::vector<int> braille_to_text;
std::vector<int> text_to_braille(inlen); int outlen;
std::vector<int> braille_to_text(outlen);
// Compute the cursor position pointer to pass to liblouis. // Compute the cursor position pointer to pass to liblouis.
int out_cursor_position; int out_cursor_position;
...@@ -139,15 +140,36 @@ bool LibLouisWrapper::Translate(const TranslationParams& params, ...@@ -139,15 +140,36 @@ bool LibLouisWrapper::Translate(const TranslationParams& params,
out_cursor_position_ptr = &out_cursor_position; out_cursor_position_ptr = &out_cursor_position;
} }
// Invoke liblouis. // Invoke liblouis. Do this in a loop since we can't precalculate the
int result = lou_translate(params.table_name.c_str(), // translated size. We add an extra slot in the output buffer so that
&inbuf[0], &inlen, &outbuf[0], &outlen, // common cases like single digits or capital letters won't always trigger
NULL /* typeform */, NULL /* spacing */, // retranslations (see the comments above the second exit condition inside
&text_to_braille[0], &braille_to_text[0], // the loop). We also set an arbitrary upper bound for the allocation
out_cursor_position_ptr, dotsIO /* mode */); // to make sure the loop exits without running out of memory.
if (result == 0) { for (int outalloc = (inbufsize + 1) * 2, maxoutalloc = (inbufsize + 1) * 8;
// TODO(jbroman): log this outalloc <= maxoutalloc; outalloc *= 2) {
return false; int inlen = inbufsize;
outlen = outalloc;
outbuf.resize(outalloc);
braille_to_text.resize(outalloc);
int result = lou_translate(params.table_name.c_str(),
&inbuf[0], &inlen, &outbuf[0], &outlen,
NULL /* typeform */, NULL /* spacing */,
&text_to_braille[0], &braille_to_text[0],
out_cursor_position_ptr, dotsIO /* mode */);
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.
// 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();
braille_to_text.clear();
} }
// Massage the result. // Massage the result.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment