HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0625
js2hsp可変長32ビット整数???4解決


js2hsp

リンク

2020/6/25(Thu) 21:02:54|NO.90869


#module #defcfunc vu array data out = 0 _at = 0 while (data(at) & 0x80) out |= (data(at) & 0x7f) << _at at++ _at += 7 wend out |= data(at) << _at return out #global data = -128, 16 mes vu(data) // 2048 stop

サーバーから受信したデータを解析しています。
そこに突如「可変長32ビット整数」(variable-length integer)というデータが登場しました。


「可変長32ビット整数」で検索しましたが中々理解できないので、
関数vuがどのような処理を行っているのかを教えてほしいです。



この記事に返信する


あらや

リンク

2020/6/25(Thu) 22:25:15|NO.90872

おそらくデータ圧縮系の処理だと思いますが。。。

とりあえず説明しやすいようにソース内の数値を2進数に直すと

配列の-128は『11111111 11111111 11111111 10000000』(2進数で8桁区切り)
同じく 16は『00000000 00000000 00000000 00010000』

0x80は『00000000 00000000 00000000 10000000』
0x7fは『00000000 00000000 00000000 01111111』

配列変数dataの最初が-128なので
>while (data(at) & 0x80)
この行での条件式は8ビット目が1なのかどうかを確認しているので
真となりwhile内を実行

>out |= (data(at) & 0x7f) << _at
この行のカッコ内を先に計算すると
これは下位7ビットだけ抜き出す処理なのですが
-128の下位7ビットが全て0なので結果も0、

その後のビットシフトも0なので
outに対しての論理和は 0 | 0 でoutは0のまま

at、_atに関しては見たままなので省略

2度目のwhile文に入りますが、
dataの2番目の数値16は上記の通り8ビット目が0のためwhileは実行せず
>out |= data(at) << _at
この行へ飛びます。

1度目のwhileの最後に加算したので
atは1
_atは7なので
16を左へ7ビットシフトした数『2048』をoutに論理和で
0 | 2048 = 2048
このあとはoutを返して終了です。



まあ単純にHSPの固定長32ビット整数として
1行ずつ説明しましたが、
おそらく元は8ビットの変数から7ビットずつ取り出して
1つの数値に圧縮するのが目的かと思います。

受信か送信かわかりませんが
2048は『00100000000000』(2進数で7ビットが2つで14ビットデータ)で送受信

これを元に戻すには7ビットずつ分割して
『0010000, 0000000』
処理の内容を逆算すると、下位の数値の8ビット目が1になっているはずなので
8ビットに直すと『000100000, 10000000』
この2つの数値が16と-128(符号付8ビット変数の場合)なのがわかる
という事だと思います。



js2hsp

リンク

2020/6/26(Fri) 08:04:24|NO.90875

ありがとうございます。もしできたら
>これを元に戻すには7ビットずつ分割して
>『0010000, 0000000』
>処理の内容を逆算すると、下位の数値の8ビット目が1になっているはずなので
>8ビットに直すと『000100000, 10000000』
>この2つの数値が16と-128(符号付8ビット変数の場合)なのがわかる
>という事だと思います。
この部分のスクリプトを教えてくれないでしょうか。



あらや

リンク

2020/6/26(Fri) 20:42:29|NO.90876

元の数値がいくつなのかを
どこかで判別しなければいけないはずですが。。。

元のソースのように数値が2つで固定されているのならば

dim data, 2; // 戻したデータを代入する配列 data_pre = 2048; // 圧縮(?)されたデータ // 1つ目の数値 data(0) = (data_pre & 0x7F) | 0x80 | 0xFFFFFF00; // 8ビット変数ならば0x80まで、『 | 0xFFFFFF00』は32ビットに合わせる場合 // 上記を省略して『data(0) = data_pre & 0x7F | 0xFFFFFF80』と書いても可 // 2つ目の数値 data(1) = (data_pre >> 7) & 0x7F;
理屈上ではこんな感じになります。

このくらいなら#defineでマクロにも出来そうですが、
元の数値が2つとは限らない場合は上記のソースを応用して

#module // 圧縮(?)データを元に戻す // data = 戻したデータを代入する配列変数 // data_pre = 圧縮されたデータ // num = 元の数値の数 #deffunc return_vu array data, int data_pre, int num _at = 0; repeat num - 1 data(cnt) = (data_pre >> _at) & 0x7F | 0xFFFFFF80; _at += 7; loop data(num - 1) = (data_pre >> _at) & 0x7F; return; #global dim data, 2; data_pre = 2048; return_vu data, data_pre, 2;
このようにモジュール化も出来ます。



js2hsp

リンク

2020/6/27(Sat) 09:15:23|NO.90878

あらやさん、ありがとうございます!



ONION software Copyright 1997-2023(c) All rights reserved.