Next: objects vectors, Previous: objects pairs, Up: objects [Index]
Bytevectors are blocks of memory referenced by machine words tagged as
bytevectors. The first word in the memory block is a fixnum
representing the number of bytes in the data area; a bytevector is
capable of holding at most a number of bytes equal to the return value
of greatest-fixnum
.
When allocating a bytevector capable of holding N bytes, the actual size of the allocated data area is N+1; the additional last byte is not part of the data area and is perpetually set to zero. All Vicare’s functions operating on bytevectors set to zero the byte right after the last used one in the data area. This last byte allows every bytevector to be used as ASCIIZ string at the C language level.
To allow for the same binary layout on both 32-bit and 64-bit platforms, the data area starts 8 bytes after the beginning; on a 32-bit platform the layout is:
1st word 2nd word last byte |----------|----------|-------------------|-----------| length unused data area set to zero
on a 64-bit platform the layout is:
1st word last byte |---------------------|-------------------|-----------| length data area set to zero
Bytevector objects are fully allocated on the heap and subject to garbage collection; to perform the allocation we compute the whole size of the bytevector data area, add to it room for meta data and finally compute the aligned block size:
ikpcb_t * pcb = ik_the_pcb(); ikuword_t bv_len = the_number_of_bytes; ikuword_t block_size = disp_bytevector_data + bv_len + 1; ikuword_t align_size = IK_ALIGN(block_size); ikptr_t bv = ik_safe_alloc(pcb, align_size) | bytevector_tag;
ik_safe_alloc()
returns an ikptr_t
value representing the
aligned pointer, having the 3 least significant bits set to zero;
we add to it the bytevector tag (an integer value fitting in 3
bits) which allows to recognise bytevectors among all the other built in
objects.
We have to explicitly store the bytevector length in the memory block as a fixnum and set the last byte to zero, so usually a full allocation looks like this:
ikptr_t ika_bytevector_alloc (ikpcb_t * pcb, ikuword_t bv_len) { ikuword_t align_size; ikptr_t s_bv; char * data; align_size = IK_ALIGN(disp_bytevector_data + bv_len + 1); s_bv = ik_safe_alloc(pcb, align_size) | bytevector_tag; IK_BYTEVECTOR_LENGTH_FX(s_bv) = IK_FIX(bv_len); data = IK_BYTEVECTOR_DATA_CHARP(s_bv); data[bv_len] = '\0'; return s_bv; }
to acquire the number of bytes we do:
ikptr_t s_bv = the_bytevector; ikuword_t bv_len = IK_BYTEVECTOR_LENGTH(s_bv);
and to access the data area we do:
ikptr_t s_bv = the_bytevector; uint8_t * octets = IK_BYTEVECTOR_DATA_UINT8P(s_bv);
An integer used to tag ikptr_t
references to bytevector memory blocks.
Displacement of length. The number of bytes to add to an untagged pointer to bytevector to get the pointer to the first byte in the machine word holding the bytevector length as fixnum.
Displacement of data area. The number of bytes to add to an untagged pointer to bytevector to get the pointer to the first byte in the data area.
An integer to add to a tagged ikptr_t
bytevector reference to retrieve
the pointer to the first byte of the fixnum representing the bytevector
length.
An integer to add to a tagged ikptr_t
bytevector reference to retrieve
the pointer to the first byte of the data area.
Notice that on both 32-bit and 64-bit platforms: the first byte of the data area is at the same byte offset from the first byte of the bytevector memory block.
Evaluate to true if obj is a bytevector.
Return the number of bytes in the data area of bv.
Return a fixnum representing the number of bytes in the data area of bv.
Return an integer representing the memory address of the first byte in the data area of bv.
Return a pointer referencing the first byte in the data area of bv.
Allocate, initialise and return a new bytevector capable of holding the specified number of bytes. The contents of the data area are unspecified. The requested bytevector length must be in the range of fixnums.
Allocate, initialise and return a new bytevector and copy the contents
of the ASCIIZ string referenced by cstr in the data area. As
special case: if cstr is NULL
, this function allocates and
returns an empty bytevector.
NOTE If the string length is greater than the maximum positive fixnum: the string is silently truncated to a length equal to the maximum positive fixnum.
Allocate, initialise and return a new bytevector and copy the len bytes of the ASCII string referenced by cstr in the data area.
NOTE If the string length is greater than the maximum positive fixnum: the string is silently truncated to a length equal to the maximum positive fixnum.
Allocate, initialise and return a new bytevector and copy in the data area length bytes from of the memory block referenced by memory.
NOTE If the memory block length is greater than the maximum positive fixnum: the block is silently truncated to a length equal to the maximum positive fixnum.
Build and return a new bytevector from a memory block referencing a UTF-16 string terminated with two consecutive zeros starting at even offset:
char char char char 0 0 |----+----|----+----|----+----|----+----|----+----| byte byte byte byte byte byte byte byte byte byte
If the the end of the string is not found before the byte index reaches the maximum fixnum: return the false object.
Copy count bytes from bytevector src starting at offset src_start, to bytevector dst starting at offset dst_start; src_start, dst_start and count must be non–negative fixnums. Return unspecified values.
Next: objects vectors, Previous: objects pairs, Up: objects [Index]