好吧,我正在尝试用C ++(自定义LZSS解压缩程序)转换此代码:
// Modified LZSS routine
// - starting position at 0 rather than 0xFEE
// - optionally, additional byte for repetition count
// - dictionary writing in two passes
static bstr custom_lzss_decompress(
const bstr &input, size_t output_size, const size_t dict_capacity)
{
std::vector<u8> dict(dict_capacity);
size_t dict_size = 0;
size_t dict_pos = 0;
bstr output(output_size);
auto output_ptr = output.get<u8>();
auto output_end = output.end<const u8>();
auto input_ptr = input.get<const u8>();
auto input_end = input.end<const u8>();
u16 control = 0;
while (output_ptr < output_end)
{
control >>= 1;
if (!(control & 0x100))
control = *input_ptr++ | 0xFF00;
if (control & 1)
{
dict[dict_pos++] = *output_ptr++ = *input_ptr++;
dict_pos %= dict_capacity;
if (dict_size < dict_capacity)
dict_size++;
}
else
{
auto tmp = *reinterpret_cast<const u16*>(input_ptr);
input_ptr += 2;
auto look_behind_pos = tmp >> 4;
auto repetitions = tmp & 0xF;
if (repetitions == 0xF)
repetitions += *input_ptr++;
repetitions += 3;
auto i = repetitions;
while (i-- && output_ptr < output_end)
{
*output_ptr++ = dict[look_behind_pos++];
look_behind_pos %= dict_size;
}
auto source = &output_ptr[-repetitions];
while (source < output_ptr)
{
dict[dict_pos++] = *source++;
dict_pos %= dict_capacity;
if (dict_size < dict_capacity)
dict_size++;
}
}
}
return output;
}
进入javascript版本,我实际上就是这样:
function custom_lzss_decompress(input,osize,dictcap){
var dict = new Uint8Array(dictcap);
var output = new Uint8Array(osize);
var data = str2ab(input);
var dict_size = 0;
var dict_pos = 0;
var control = 0;
var iptr = 0;
var optr = 0;
while (iptr < osize){
control >>= 1;
if(!(control & 0x100)){
control = data[iptr] | 0xFF00;
iptr++;
}
if(control & 1){
dict[dict_pos] = output[optr] = data[iptr];
dict_pos++;
iptr++;
optr++;
dict_pos %= dictcap;
if(dict_size < dictcap)
dict_size++;
}
else{
var tmp = new Uint16Array(1);
tmp[0] = (data[iptr] << 8) + data[iptr+1];
iptr += 2;
var loop_behind_pos = new Uint16Array(1);
loop_behind_pos[0] = tmp >> 4;
var repetitions = new Uint16Array(1);
repetitions[0] = tmp & 0xF;
if(repetitions[0] == 0xF){
repetitions[0] += data[iptr];
}
iptr++;
repetitions[0] += 3;
var ai = new Uint16Array(1);
ai[0] = repetitions[0];
while(ai[0] && (optr < osize)){
ai[0]--;
output[optr] = dict[loop_behind_pos];
optr++;
loop_behind_pos++;
loop_behind_pos %= dict_size;
}
var source = new Uint16Array(1);
source[0] = output[-repetitions[0]];
while(source[0] < optr){
dict[dict_pos] = output[source];
dict_pos++;
source++;
dict_pos %= dictcap;
if(dict_size < dictcap)
dict_size++;
}
}
}
return output;
}
它运行......但是不起作用......我无法弄清楚发生了什么......有人能看到一些我没见过的奇怪错误吗?
答案 0 :(得分:0)
我看到一个问题,一个潜在的问题。问题始终存在于重复[0] == 0xF handler. You're incrementing
iptr`中,但原始代码仅在if的正文中执行。
潜在问题在于16位字读取tmp[0] = (data[iptr] << 8) + data[iptr+1];
。如果单词是big-endian,则可以正常工作,但如果源是little-endian,则不会给出正确的值。