This feature :
- is complex to use
- has some/many limitations
- has performance issue (especially on raw(*) or string())
save_position, goto_position and move_position_... do not work with decoder
Sometimes, the input data is NOT directly usable (using int16, string ...) because it is encoded.
It is necessary to decode the input data before use it.
With decoder command, you can provide a function which decode the data following your rules.
The function must be defined like this :
function void <function_name> (in frame frame, in uint32 nb_of_bits_needed) { ... read some data (using hide) ... do some computation to decode data # Add a decoded data which size is <= 8 bits # It is mandatory that the <decoded_value_on_1_byte_only> # have type = uintX with X <= 8 call frame_append_data (frame, <decoded_value_on_1_byte_only>); ... }
The function must append inside frame the number of bits asked <nb_of_bits_needed>.
Then you must specify when using the function :
struct xxx { ... # the function is NOT called decoder <function_name>; uint16 field_a; # the function will be called with nb_of_bits_needed = 16 uint8 field_b; # the function will be called with nb_of_bits_needed = 8 int24 field_c; # the function will be called with nb_of_bits_needed = 24 decoder nil; ... # the function is NOT called string{decoder=<function_name>}(5) str5; # the function will be called with nb_of_bits_needed = 40 string{decoder=<function_name>} str; # the function will be called many times with nb_of_bits_needed = 8 ... # the function is NOT called }
Decoding rule :
Each time there is a byte which equal 0x10,
it must be ignored and
we must take the following byte ^ 0x20.
Decoding function :
function void decode_stream_0x10 (in frame frame, in uint32 nb_of_bits_needed) { # ATTENTION, following divide is possible only because I'm sure, in this example, # that nb_of_bits_needed is a multiple of 8 hide var uint32 nb_of_bytes_needed = nb_of_bits_needed / 8; while (nb_of_bytes_needed > 0) { hide uint8 byte1; if (byte1 == 0x10) { hide uint8 byte2; set byte1 = byte2 ^ 0x20; } call frame_append_data (frame, byte1); set nb_of_bytes_needed = nb_of_bytes_needed - 1; } }
Using decoding function
struct xxx { uint8 field_before; # decode_stream_0x10 is not called decoder decode_stream_0x10; uint16 field_a; # decode_stream_0x10 will be called with nb_of_bits_needed = 16 enum8 field_b; # decode_stream_0x10 will be called with nb_of_bits_needed = 8 string(3) field_c; # decode_stream_0x10 will be called with nb_of_bits_needed = 24 decoder nil; uint16 field_after; # decode_stream_0x10 is not called }
Example of data to read using the struct xxx :
0x10 0x23 0x10 0xa4 0xd1 0x02 0x03 0x10 0xc2 0x23 0x34
Will give the following result/sequence :
- field_before = 0x10 decode_stream_0x10 not called - field_a decode_stream_0x10 is called with nb_of_bits_needed = 16 read byte1 = 0x23, append it to frame read byte1 = 0x10, read byte2 = 0xa4 set byte1 = 0xa4 ^ 0x20 = 0x84, append it to frame field_a = 0x23 0x84 - field_b decode_stream_0x10 is called with nb_of_bits_needed = 8 read byte1 = 0xd1, append it to frame field_b = 0xd1 - field_c decode_stream_0x10 is called with nb_of_bits_needed = 24 read byte1 = 0x02, append it to frame read byte1 = 0x03, append it to frame read byte1 = 0x10, read byte2 = 0xc2 set byte1 = 0xc2 ^ 0x20 = 0xe2, append it to frame field_c = 0x02 0x03 0xe2 - field_after = 0x23 0x34 decode_stream_0x10 not called
In the previous example, the hexa-dump highlight is working well.
We have the following scheme :
- what I want to read : <field_a><field_b><field_c>
- the real data format : <--field_a--><--field_b--><--field_c-->
Even if the size of the real data is NOT the same, the sequence is identic.
If the sequence is different, the hexa-dump highlight will not work.
Want to read an UTF16 string ?
Wsgd manage only ansi string.
But a decode function could transform UTF16 string to ansi string.
NB: all characters > 255 will be displayed as "."
# this is only an example, this function is now built-in # decoder_utf16be (for Big Endian) is also built-in function void decoder_utf16le (in frame frame, in uint32 nb_of_bits_needed) { if ((nb_of_bits_needed % 8) != 0) { fatal "Only entire byte"; return; } while (nb_of_bits_needed > 0) { hide uint8 byte1; hide uint8 byte2; if (byte2 != 0) { set byte1 = 46; # means "." to say unknow char if ((byte2 & 0xfc) == 0xd8) { hide uint8 byte3; hide uint8 byte4; } } call frame_append_data (frame, byte1); set nb_of_bits_needed = nb_of_bits_needed - 8; } } alias stringUtf16le string{decoder=decoder_utf16le};
Then you can use stringUtf16le where you have a string with UTF16 (little endian) encoding.
Want to read an UTF8 string ?
Wsgd manage only ansi string.
But a decode function could transform UTF8 string to ansi string.
NB: all characters > 127 will be displayed as "."
# this is only an example, this function is now built-in function void decoder_utf8 (in frame frame, in uint32 nb_of_bits_needed) { if ((nb_of_bits_needed % 8) != 0) { fatal "Only entire byte"; return; } while (nb_of_bits_needed > 0) { hide uint8 byte1; if ((byte1 & 0x80) != 0) { if ((byte1 & 0xF0) == 0xF0) { hide uint8 byte2; hide uint8 byte3; hide uint8 byte4; } else { if ((byte1 & 0xE0) == 0xE0) { hide uint8 byte2; hide uint8 byte3; } else { hide uint8 byte2; } } set byte1 = 46; # means "." to say unknow char } call frame_append_data (frame, byte1); set nb_of_bits_needed = nb_of_bits_needed - 8; } } alias stringUtf8 string{decoder=decoder_utf8};
Then you can use stringUtf8 where you have a string with UTF8 encoding.
Silly and useless examples.
# Read each bit and simply put it into the frame function void decode_stream_nothing_bit (in frame frame, in uint32 nb_of_bits_needed) { while (nb_of_bits_needed > 0) { hide uint1 bit1; call frame_append_data (frame, bit1); set nb_of_bits_needed = nb_of_bits_needed - 1; } } # Read each byte and simply put it into the frame function void decode_stream_nothing_byte (in frame frame, in uint32 nb_of_bits_needed) { # ATTENTION, following divide is possible only if you are sure # that nb_of_bits_needed is a multiple of 8 hide var uint32 nb_of_bytes_needed = nb_of_bits_needed / 8; while (nb_of_bytes_needed > 0) { hide uint8 byte1; call frame_append_data (frame, byte1); set nb_of_bytes_needed = nb_of_bytes_needed - 1; } }