Next: , Previous: , Up: objects   [Index]


13.7 Bytevector objects

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

Basic operations

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);
Preprocessor Symbol: bytevector_tag

An integer used to tag ikptr_t references to bytevector memory blocks.

Preprocessor Symbol: disp_bytevector_length

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.

Preprocessor Symbol: disp_bytevector_data

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.

Preprocessor Symbol: off_bytevector_length

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.

Preprocessor Symbol: off_bytevector_data

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.

Convenience preprocessor macros

Function: Preprocessor Macro IK_IS_BYTEVECTOR (ikptr_t obj)

Evaluate to true if obj is a bytevector.

Preprocessor Macro: ikuword_t IK_BYTEVECTOR_LENGTH (ikptr_t bv)

Return the number of bytes in the data area of bv.

Preprocessor Macro: ikptr_t IK_BYTEVECTOR_LENGTH_FX (ikptr_t bv)

Return a fixnum representing the number of bytes in the data area of bv.

Preprocessor Macro: ikuword_t IK_BYTEVECTOR_DATA (ikptr_t bv)

Return an integer representing the memory address of the first byte in the data area of bv.

Preprocessor Macro: void * IK_BYTEVECTOR_DATA_VOIDP (ikptr_t bv)
Preprocessor Macro: char * IK_BYTEVECTOR_DATA_CHARP (ikptr_t bv)
Preprocessor Macro: uint8_t * IK_BYTEVECTOR_DATA_UINT8P (ikptr_t bv)

Return a pointer referencing the first byte in the data area of bv.

Operations on bytevectors

Function: ikptr_t ika_bytevector_alloc (ikpcb_t * pcb, ikuword_t requested_number_of_bytes)

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.

Function: ikptr_t ika_bytevector_from_cstring (ikpcb_t * pcb, const char * cstr)

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.

Function: ikptr_t ika_bytevector_from_cstring_len (ikpcb_t * pcb, const char * cstr, size_t len)

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.

Function: ikptr_t ika_bytevector_from_memory_block (ikpcb_t * pcb, const void * memory, size_t length)

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.

Function: ikptr_t ika_bytevector_from_utf16z (ikpcb_t * pcb, const void * data);

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.

Function: ikptr_t ikrt_bytevector_copy (ikptr_t dst, ikptr_t dst_start, ikptr_t src, ikptr_t src_start, ikptr_t count)

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: , Previous: , Up: objects   [Index]