Core Function Vec
Vec( <expression>, <offset>, <bits> )
Contents |
Description
Treats the string in EXPRESSION as a bit vector made up of elements of width bits and returns the value of the element specified by OFFSET as an unsigned integer and optionally sets BITS in the string to a given value.
BITS therefore specifies the number of bits that are reserved for each element in the bit vector. This must be a power of two from 1 to 32.
If BITS is 8, "elements" coincide with bytes of the input string.
If BITS is 16 or more, bytes of the input string are grouped into chunks of size BITS/8, and each group is converted to a number as with pack()/unpack() with big-endian formats n /N (and analogously for BITS==64). See pack for details.
If bits is 4 or less, the string is broken into bytes, then the bits of each byte are broken into 8/BITS groups.
Bits of a byte are numbered in a little-endian-ish way, as in 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80.
For example, breaking the single input byte chr(0x36) into two groups gives a list (0x6, 0x3) ; breaking it into 4 groups gives (0x2, 0x1, 0x3, 0x0) .
vec may also be assigned to, by using the value parameter example:
vec($image, $max_x * $x + $y, 8) = 3; // Settting value 3
If the selected element is outside the string, the value 0 is returned. If an element off the end of the string is written to, Spunik will first extend the string with sufficiently many zero bytes. It is an error to try to write off the beginning of the string (i.e., negative OFFSET).
Strings created with vec can also be manipulated with the logical operators |, & , ^, and ~ .
These operators will assume a bit vector operation is desired when both operands are strings.
Parameters
expression
The string to use.
offset
Offset is the marker for the end of the vector, and it counts back the number of bits specified to find the start.
bits
BITS specifies the number of bits that are reserved for each element in the bit vector.
This must be a power of two from 1 to 32.
Return Value
This function returns the value of the bit field specified by OFFSET.
You must use Vec() if you wish to edit the string at the offset and bits you can't use the return value from a Vec() and expect to edit it hoping to change the bit string this will fail.
You can't use the return value to modify the string.
Remarks
This function is inspired by Perl's Vec() function and any tutorial you find for Perl on that should work on this.
This function is smart enough to know if it should increase the strings size or not therefor it will return/edit the parts of the string you wish to without rebuilding the string each time this is significantly faster than recreating the string every time.
In Sputnik strings are immutable and also not immutable... For most operations a new string will be returned and the old one replaced however that is not the rule there are a number of functions that will modify the string in place and Vec() is one of them.
You can also modify strings in place yourself using the Fixed() statement.
A Vec() has to be on the left side of an operation for it to get SET such as otherwise you can only GET from it.
Technically the Vec() is not a function like most others it's actually more of a language feature similar to an If statement so if you enter wrong number of parameters you will be notified instantly even before execution of your script begins. Since it is a language feature rather than a generic function its structure is parsed literally.
Example
One often undocumented feature of the Vec() is its ability to use Operators such as ++ example:
my $foo = ''; vec($foo, 0, 32) = 0x5065726C; # 'Perl' echo "Vec: $foo\n"; # Perl vec($foo, 1, 8)++; // Increase the second char in the string echo "Vec: $foo\n"; # Pdrl vec($foo, 0, 8)++; // Increase the first char in the string echo "Vec: $foo\n"; # Qdrl vec($foo, 2, 8) += 4; // Increase the third char in the string by 4 echo "Vec: $foo\n"; # Qfvl vec($foo, 0, 8) -= vec($foo, 1, 8); // Sub the second char from first echo "Vec: $foo\n"; # ëfvl vec($foo, 0, 8) ^= @'A'; // Do a Xor operation echo "Vec: $foo\n"; # ªfvl # Note that .= and ..= work differently on Vectors so vec($foo, 0, 8) .= 10; // Is equal to += 10 vec($foo, 0, 8) ..= 10; // Is equal to -= 10
The following code will build up an ASCII string saying 'PerlPerlPerl' . The comments show the string after each step. Note that this code works in the same way on big-endian or little-endian machines.
my $foo = ''; vec($foo, 0, 32) = 0x5065726C; # 'Perl' # $foo eq "Perl" eq "\x50\x65\x72\x6C", 32 bits printf "Char '%1^c' Byte '%1^d'\n", vec($foo, 0, 8); # prints 80 == 0x50 == ord('P') vec($foo, 2, 16) = 0x5065; # 'PerlPe' vec($foo, 3, 16) = 0x726C; # 'PerlPerl' vec($foo, 8, 8) = 0x50; # 'PerlPerlP' vec($foo, 9, 8) = 0x65; # 'PerlPerlPe' vec($foo, 20, 4) = 2; # 'PerlPerlPe' . "\x02" vec($foo, 21, 4) = 7; # 'PerlPerlPer' # 'r' is "\x72" vec($foo, 45, 2) = 3; # 'PerlPerlPer' . "\x0c" vec($foo, 93, 1) = 1; # 'PerlPerlPer' . "\x2c" vec($foo, 94, 1) = 1; # 'PerlPerlPerl' # 'l' is "\x6c" printf "\$foo is '%s'\n", $foo; // Prints // $foo is 'PerlPerlPerl' // Lets replace the middle Perl with Lrep vec($foo, 1, 32) = 0x4C726570; # 'Lrep' printf "\$foo is '%s'\n", $foo; // $foo is 'PerlLrepPerl'
The following code will build up an ASCII string saying 'Sputnik'
my $foo = ''; vec($foo, 0, 32) = 0x53707574; # 'Sput' vec($foo, 1, 32) = 0x6E696B00; # 'nik' printf "\$foo is: %s\n", $foo; // $foo is: Sputnik
To transform a bit vector into a string or list of 0's and 1's, use these:
my $foo = ''; vec($foo, 0, 32) = 0x5065726C; # 'Perl' $bits = unpack("b*", $foo, true); print "$bits\n"; // Prints: 00001010101001100100111000110110 // To get each individual bit $bitsArray = split(unpack("b*", $foo, true), ''); foreach($bitsArray as $b) { echo "Bit '$b'\n"; } // Prints // Bit '0' // Bit '0' // Bit '0' // Bit '0' // Bit '1' // Bit '0' // Bit '1' // Bit '0' // Bit '1' // Bit '0' // Bit '1' // Bit '0' // Bit '0' // Bit '1' // Bit '1' // Bit '0' // Bit '0' // Bit '1' // Bit '0' // Bit '0' // Bit '1' // Bit '1' // Bit '1' // Bit '0' // Bit '0' // Bit '0' // Bit '1' // Bit '1' // Bit '0' // Bit '1' // Bit '1' // Bit '0'