"Sputnik" help  
Sputnik Help
vec( <variable>, <offset>, <bits>, <directOffset>, <endian> ) <eq> <expr>
vec( <variable>, <offset>, <bits> ) <eq> <expr>
vec( <variable>, <offset>, <bits> )++
vec( <variable>, <offset>, <bits> )--

Description

Treats the binary variable 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 binary variable to a given value.

BITS therefore specifies the number of bits that are reserved for each element in the bit vector. This must from 1 to 64 however if it ranges from higher than 8 it must be in a power of two (below 8 does not have this limit).

If BITS is 8, "elements" coincide with bytes of the input binary variable.

If BITS is 16 or more, bytes of the input binary variable 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 binary variable 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 binary variable, the value 0 is returned. If an element off the end of the binary variable is written to, Spunik will first extend the binary variable with sufficiently many zero bytes. It is an error to try to write off the beginning of the binary variable (i.e., negative OFFSET).

Binary variables 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 binary variables.

Parameters

<variable> The variable to use so it can be written to and stored it will be converted to binary if it is not already.

The binary variable will be increased in size as you demand so in the OFFSET.

The binary variable will be MODIFIED IN PLACE and is not reconstructed at each edit this provides maximal speed the only time this does not apply is if you are resizing the binary variable then it has no choice but to copy it.

You can also preallocate the binary variable a given length (See examples for how to).

<offset> Offset is the marker for the end of the vector, and it counts back the number of bits specified to find the start.

Unlike in Perl you may use a Negative offset and it will cause the operation to take place that many characters from the end of the binary variable.

<bits> BITS specifies the number of bits that are reserved for each element in the bit vector.

This must be a power of two IF the number is from 8 to 64 however numbers BELOW 8 are not required to be a power of two.

<directOffset>

Optional; A boolean to say if the offset should be a direct offset or a bit shifted offset.

Default: false

<endian>

Optional; The Endian to use.

Default: @EndianBig.

<eq>

The operation to do such as += and -= etc etc. You can also just do ++ and -- etc.

You do not need to include the <expr> if the <eq> is just ++ or -- however.

<expr> Optional; A numeric value to set to the Vec().

If it is a floating point it will be rounded.

If it is a string or anything else it will be converted to an Integer (Int64).

If it is a Binary variable Vec() will try convert it to an integer of up to Int64 size (Any bytes in excess of 8 will be ignored).

The return value still takes effect even you set a value to the Vec().

Return Value

This function returns the value of the bit field specified by OFFSET.

You must use Vec() if you wish to edit the binary variable at the offset and bits you can't use the return value from a Vec() and expect to edit it hoping to change the binary variable this will fail.

You can't use the return value to modify the binary variable.

Remarks

This function is inspired by Perl's Vec() function and any tutorial you find for Perl one that should work on this however this is not a normal function and instead is it coded directly into the core language thus it does things other functions cannot do nor can they make use of such as the <eq> part.

This function is smart enough to know if it should increase the binary variables size or not therefor it will return/edit the parts of the binary variable you wish to without rebuilding the binary variable each time this is significantly faster than recreating the binary variable every time.

In Sputnik binary variable are not immutable. For most operations a binary variable will be modified in place and the Vec() also modifies binary variables in place.

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.

To display what is inside a Vec()'s binary variable it is recommened to the use BinaryExpand() function.

Vec() is often used when dealing with sockets since it very good at reading and creating all kinds of headers etc.

This is a powerful function in Sputnik that allows you to manipulate binary variables with ease. It treats a binary variable as a bit vector and provides various operations to retrieve and set values at specific offsets. The function supports different bit sizes and can handle big-endian and little-endian formats. It's particularly useful when working with sockets or dealing with binary data. The ability to use logical operators with binary variables adds to its versatility. Overall, Vec() is a core language feature that offers efficient and flexible binary manipulation capabilities. If you're new to Vec(), be sure to explore the provided examples for a better understanding of its usage.

Related

VecEx

Example

Bits example:

my $vec = null;
vec($vec,  3, 4) = 1;  // bits 0 to 3
vec($vec,  7, 4) = 10; // bits 4 to 7
vec($vec, 11, 4) = 3;  // bits 8 to 11
vec($vec, 15, 4) = 15; // bits 12 to 15
// As there are 4 bits per number this can
// be decoded by unpack() as a hex number
my $hex = UnpackSingle("h*", $vec);
say "vec() Has a created a string of nybbles, in hex: $hex";
// PRINTS:
// vec() Has a created a string of nybbles, in hex: 0001000A0003000F

Example of packing two floating point numbers into a bit vector then retrieving them later:

my $foo = null;
vec($foo, 0, 32) = Pack("f", 133.7);
vec($foo, 1, 32) = Pack("f", 777.42);
// This works because Vec() will read the binary array similar to how
// Unpack() would read it with with C s i q format Vec() will choose
// what it thinks is the correct format to read based on how big the
// binary array is and it will pad 0 bytes to the end if its off like
// 3 bytes or 7 bytes etc. 
say "\$foo is '$foo'"; 
say "First float is: " . Unpack("f", vec($foo, 0, 32), 3);
say "Second float is: " . Unpack("f", vec($foo, 1, 32), 3);
// PRINTS
// $foo is 'C³3DBZá'
// First float is: 133.7
// Second float is: 777.42

Print a bit vector:

my $foo = null;
vec($foo, 0, 64) = 0x537075746E696B00;
printf "\$foo is: %s\n", (string)$foo;
printr $foo;
// PRINTS
// $foo is: Sputnik
// Binary
// (
//     [0] => 0x53 [83] (S)
//     [1] => 0x70 [112] (p)
//     [2] => 0x75 [117] (u)
//     [3] => 0x74 [116] (t)
//     [4] => 0x6E [110] (n)
//     [5] => 0x69 [105] (i)
//     [6] => 0x6B [107] (k)
//     [7] => 0x00 [0] (.)
// )

Print a bit vector (Alternative method):

my $foo = null;
vec($foo, 0, 64) = 0x537075746E696B00;
printf "\$foo is: %s\n", (string)$foo;
say BinaryExpand($foo);
// PRINTS
// $foo is: Sputnik
// 00 | 53 70 75 74 6E 69 6B 00 -- -- -- -- -- -- -- -- Sputnik.

Binary and Vec vectors are the same thing:

// Create a binary variable
$vec = Pack("A*", "Zputnik"); 
// Edit the first character
vec($vec, 0, 8) = 'S'; 
// Add a period to the end
vec($vec, strlen($vec), 8) = '.'; 
say $vec; // Sputnik.
// PRINTS
// Sputnik.

Looking for a way to spawn a binary variable of a specific size to be used as a Vec() then try these:

// Vec() can work on an empty binary variable just fine
// it will increase the binary variables size as it needs to
// there is no need to ever preallocate the binary variable.
 
// However if you find you want to then this is how to.
 
// So a 100 byte long binary variable is same as
$vec = BinNew(100, 'T'); // Make a binary variable 100 bytes long filled with 'T' chars
$vec = BinNew(100, 'A'); // Make a binary variable 50 bytes long filled with 'A' chars
$vec = StrNew(100, ' '); // Make a binary variable 50 bytes long filled with ' ' (space) chars
$vec = BinNew(100, 0); // Make a binary variable 50 bytes long filled with null chars (0x00 null byte)
$vec = BinNew(100, 077); // Use Octal to define the byte for the new binary variable to be filled with
$vec = BinNew(100, 0x31); // Use Hex to define the byte for the new binary variable to be filled with
$vec = BinNew(100, 65); // Use Decimal to define the byte for the new binary variable to be filled with
 
// Once you have created the binary variable of the size you need
// you can begin using Vec() on it example
 
// Pre-allocate the binary variable
$vec = BinNew(10, '-');
say (string)$vec; // ----------
vec($vec, 0, 8) = 'S'; // Use '' which is the Sputnik CharLiteral
vec($vec, 1, 8) = 'P'; // It would be a bad idea to just use '' since that is a string!
vec($vec, 2, 8) = 'U';
vec($vec, 3, 8) = 'T';
vec($vec, 4, 8) = 'N';
vec($vec, 5, 8) = 'I';
vec($vec, 6, 8) = 'K';
say (string)$vec; // SPUTNIK---

// PRINTS
// ----------
// SPUTNIK---

One often undocumented feature of the Vec() is its ability to use Operators such as ++ example:

my $foo = null;
vec($foo, 0, 32) = 0x5065726C; //'Perl'
say "Vec: $foo"; // Perl
vec($foo, 1, 8)++; // Increase the second char in the binary variable
say "Vec: $foo"; // Pfrl
vec($foo, 0, 8)++; // Increase the first char in the binary variable
say "Vec: $foo"; // Qfrl
vec($foo, 2, 8) += 4; // Increase the third char in the binary variable by 4
say "Vec: $foo"; // Qfvl
vec($foo, 0, 8) -= vec($foo, 1, 8); // Sub the second char from first
say "Vec: $foo"; // ëfvl
vec($foo, 0, 8) ^= 'A'; // Do a Xor operation
say "Vec: $foo"; // ªfvl 
// Note that .= and ..= work differently on Vectors so
vec($foo, 0, 8) .= 10; // Is equal to += 10
// PRINTS
// Vec: Perl
// Vec: Pfrl
// Vec: Qfrl
// Vec: Qfvl
// Vec: ëfvl
// Vec: ªfvl

The following code will build up an ASCII (in binary format) 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 = null;
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", (string)$foo;
// Prints
// $foo is 'PerlPerlPerl'
 
// Lets replace the middle Perl with Lrep
vec($foo, 1, 32) = 0x4C726570; //'Lrep'
printf "\$foo is '%s'\n", (string)$foo;
// $foo is 'PerlLrepPerl'

// PRINTS
// Char 'P' Byte '80'
// $foo is 'PerlPerlPerl'
// $foo is 'PerlLrepPerl'

The following code will build up an ASCII (in binary format) saying 'Sputnik' (using 32-Bits):

my $foo = null;
vec($foo, 0, 32) = 0x53707574; //'Sput'
vec($foo, 1, 32) = 0x6E696B00; // 'nik'
printf "\$foo is: %s\n", (string)$foo;
// PRINTS
// $foo is: Sputnik

The following code will build up an ASCII (in binary format) saying 'Sputnik' (using 64-Bits):

my $foo = null;
vec($foo, 0, 64) = 0x537075746E696B00;
printf "\$foo is: %s\n", (string)$foo;
// PRINTS
// $foo is: Sputnik

To transform a bit vector into a list of 0's and 1's, use these:

my $foo = null;
vec($foo, 0, 32) = 0x5065726C; // 'Perl'
 
$bits = unpack("b*", $foo, @UnpackString);
print "$bits\n"; // Prints: 00001010101001100100111000110110
 
// To get each individual bit
foreach(my $b in unpack("b*", $foo, @UnpackString))
{
    say "Bit '$b'";
}
// 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'

Using a bit vector to find prime numbers:

my $max = 50;
 
my $sieve = null;
vec($sieve, $max, 1) = 0;
$sieve = ~$sieve;
 
for (my $i = 2; $i <= sqrt($max); $i++)
{
    if(!vec($sieve, $i, 1))
        continue;
    for (my $x = $i * 2; $x <= $max; $x += $i)
        vec($sieve, $x, 1) = 0;
}
 
for (2 rr $max)
{
    if(vec($sieve, @_, 1))
        say @_;
}

// PRINTS
// 2
// 3
// 5
// 7
// 11
// 13
// 17
// 19
// 23
// 29
// 31
// 37
// 41
// 43
// 47

Are you wondering how to place Floating points into a Vec()? Here is how:

// Convert a Float to an Integer (32-bits)
Function FpuToInt($value)
{
    return UnpackSingle('i', PackSingle('f', $value));
}
// Convert a Integer to an Float (32-bits)
Function IntToFpu($value)
{
    return UnpackSingle('f', PackSingle('i', $value));
}
 
// Now we get started
 
// Create a variable to hold the Vec
// NULL is fine since it at least created
// the variable
my $vec = null;
// Add some floating points to the vec
Vec($vec, 0, 32) = FpuToInt(133.42);
Vec($vec, 1, 32) = FpuToInt(777.42);
Vec($vec, 2, 32) = FpuToInt(@PI);
Vec($vec, 3, 32) = FpuToInt(@FloatMax);
 
// Read the floating points from the vec
say IntToFpu(Vec($vec, 0, 32));
say IntToFpu(Vec($vec, 1, 32));
say IntToFpu(Vec($vec, 2, 32));
say IntToFpu(Vec($vec, 3, 32));
 
// PRINTS:
// 133.42
// 777.42
// 3.141593
// 3.402823E+38

Same as above but this time for double precision floating points:

// First we define some helper functions
 
// Convert a Float to an Integer (64-bits)
Function FpuDToInt($value)
{
    return UnpackSingle('q', PackSingle('d', $value));
}
// Convert a Integer to an Float (64-bits)
Function IntToFpuD($value)
{
    return UnpackSingle('d', PackSingle('q', $value));
}
 
// Now we get started
 
// Create a variable to hold the Vec
// NULL is fine since it at least created
// the variable
my $vec = null;
// Add some floating points to the vec
Vec($vec, 0, 64) = FpuDToInt(133.42);
Vec($vec, 1, 64) = FpuDToInt(777.42);
Vec($vec, 2, 64) = FpuDToInt(@PI);
Vec($vec, 3, 64) = FpuDToInt(@DoubleMax);
 
// Read the floating points from the vec
say IntToFpuD(Vec($vec, 0, 64));
say IntToFpuD(Vec($vec, 1, 64));
say IntToFpuD(Vec($vec, 2, 64));
say IntToFpuD(Vec($vec, 3, 64));
 
// PRINTS:
// 133.42
// 777.42
// 3.14159265358979
// 1.79769313486232E+308

Example of using a bit value lower than 8 to set the bits instead of bytes:

// Enum to store the privs
Enum Privs
{
    $DeleteFile         = 0,
    $UploadFile         = 1,
    $DownloadFile       = 2,
    $RenameFile         = 3,
    $MoveFile           = 4,
    $CreateFolder       = 5,
    $DeleteFolder       = 6,
    $RenameFolder       = 7,
    $MoveFolder         = 8,
    $ReadChat           = 9,
    $SendChat           = 10,
    $CreateChat         = 11,
    $CloseChat          = 12
};
// A simple function to print what privs are enabled
Function PrintPrivs( $data )
{
    foreach( my $Key => my $Value in Enumerate("Privs") )
    {
        my $Status = Vec($data, $Value, 1);
        if($Status) // Only show privs we can use
            say "Priv '$Key' Access is '$Status'";
    }
}
// Define a variable to hold the bit vector
my $Access = null;
// Set privs in the bit vector
Vec($Access, Privs->$UploadFile, 1) = true;
Vec($Access, Privs->$CreateFolder, 1) = true;
Vec($Access, Privs->$ReadChat, 1) = true;
Vec($Access, Privs->$CloseChat, 1) = true;
// Print the privs from the bit vector
say "Print Privs";
PrintPrivs($Access);
// Print the binary of the bit vector
printr $access;
// PRINTS
// Print Privs
// Priv 'uploadfile' Access is '1'
// Priv 'createfolder' Access is '1'
// Priv 'readchat' Access is '1'
// Priv 'closechat' Access is '1'
// Binary
// (
//     [0] => 0x22 [34] (")
//     [1] => 0x12 [18] (.)
// )

Hopefully these examples explain how useful vec can be.

Theres some other interesting examples of Vec to be found in the Enum (Bit Flags) section.


Contact
Cheryl (uberfox@hotmail.com)
Homepage
http://ubersoft.org