Пример #1
0
/*******************************************************************************
 *
 * Helper functions.
 *
 ******************************************************************************/
static enum sl_error
ensure_allocated(struct sl_vector* vec, size_t capacity, bool keep_data)
{
  void* buffer = NULL;
  enum sl_error sl_err = SL_NO_ERROR;
  ASSERT(vec);

  if(capacity > vec->capacity) {
    size_t new_capacity = 0;
    NEXT_POWER_OF_2(capacity, new_capacity);
    buffer = MEM_ALIGNED_ALLOC
      (vec->allocator, new_capacity * vec->data_size, vec->data_alignment);
    if(!buffer) {
      sl_err = SL_MEMORY_ERROR;
      goto error;
    }
    if(keep_data) {
      buffer = memcpy(buffer, vec->buffer, vec->capacity * vec->data_size);
    }
    MEM_FREE(vec->allocator, vec->buffer);
    vec->buffer = buffer;
    vec->capacity = new_capacity;
    buffer = NULL;
  }

exit:
  return sl_err;
error:
  if(buffer) {
    MEM_FREE(vec->allocator, buffer);
    buffer = NULL;
  }
  goto exit;
}
Пример #2
0
static void
regular_test(struct mem_allocator* allocator)
{
    char dump[BUFSIZ];
    void* p = NULL;
    void* q[3] = {NULL, NULL, NULL};
    size_t i = 0;

    p = MEM_ALIGNED_ALLOC(allocator, 1024, ALIGNOF(char));
    NCHECK(p, NULL);
    CHECK(IS_ALIGNED((uintptr_t)p, ALIGNOF(char)), 1);
    MEM_FREE(allocator, p);

    q[0] = MEM_ALIGNED_ALLOC(allocator, 10, 8);
    q[1] = MEM_CALLOC(allocator, 1, 58);
    q[2] = MEM_ALLOC(allocator, 78);
    NCHECK(q[0], NULL);
    NCHECK(q[1], NULL);
    NCHECK(q[2], NULL);
    CHECK(IS_ALIGNED((uintptr_t)q[0], 8), 1);

    p = MEM_CALLOC(allocator, 2, 2);
    NCHECK(p, NULL);
    for(i = 0; i < 4; ++i)
        CHECK(((char*)p)[i], 0);
    for(i = 0; i < 4; ++i)
        ((char*)p)[i] = (char)i;

    MEM_DUMP(allocator, dump, BUFSIZ);
    printf("dump:\n%s\n", dump);
    MEM_DUMP(allocator, dump, 16);
    printf("truncated dump:\n%s\n", dump);
    MEM_DUMP(allocator, NULL, 0); /* may not crashed. */

    MEM_FREE(allocator, q[1]);

    p = MEM_REALLOC(allocator, p, 8);
    for(i = 0; i < 4; ++i)
        CHECK(((char*)p)[i], (char)i);
    for(i = 4; i < 8; ++i)
        ((char*)p)[i] = (char)i;

    MEM_FREE(allocator, q[2]);

    p = MEM_REALLOC(allocator, p, 5);
    for(i = 0; i < 5; ++i)
        CHECK(((char*)p)[i], (char)i);

    MEM_FREE(allocator, p);

    p = NULL;
    p = MEM_REALLOC(allocator, NULL, 16);
    NCHECK(p, NULL);
    p = MEM_REALLOC(allocator, p, 0);

    MEM_FREE(allocator, q[0]);

    CHECK(MEM_ALIGNED_ALLOC(allocator, 1024, 0), NULL);
    CHECK(MEM_ALIGNED_ALLOC(allocator, 1024, 3), NULL);
    CHECK(MEM_ALLOCATED_SIZE(allocator), 0);
}
Пример #3
0
EXPORT_SYM enum sl_error
sl_vector_insert_n
  (struct sl_vector* vec,
   size_t id,
   size_t count,
   const void* data)
{
  void* buffer = NULL;
  const void* src = NULL;
  void* dst = NULL;
  size_t i = 0;
  enum sl_error err = SL_NO_ERROR;

  if(!vec || (id > vec->length) || !data) {
    err = SL_INVALID_ARGUMENT;
    goto error;
  }
  if(0 == count) {
    goto exit;
  }
  if(!IS_ALIGNED(data, vec->data_alignment)) {
    err = SL_ALIGNMENT_ERROR;
    goto error;
  }
  if(vec->length == SIZE_MAX) {
    err = SL_OVERFLOW_ERROR;
    goto error;
  }
  if(id == vec->length) {
    err = ensure_allocated(vec, vec->length + count, true);
    if(err != SL_NO_ERROR)
      goto error;

    dst = (void*)((uintptr_t)(vec->buffer) + vec->data_size * id);
    src = data;
    for(i = 0; i < count; ++i) {
      dst = memcpy(dst, src, vec->data_size);
      dst = (void*)((uintptr_t)(dst) + vec->data_size);
    }
  } else {
    if(vec->length + count >= vec->capacity) {
      size_t new_capacity = 0;
      NEXT_POWER_OF_2(vec->length + count, new_capacity);

      buffer = MEM_ALIGNED_ALLOC
        (vec->allocator, new_capacity * vec->data_size, vec->data_alignment);
      if(!buffer) {
        err = SL_MEMORY_ERROR;
        goto error;
      }

      /* Copy the vector data ranging from [0, id[ into the new buffer. */
      if(id > 0)
        memcpy(buffer, vec->buffer, vec->data_size * id);

      if(id < vec->length) {
        /* Copy from the vector data [id, length[ to the new buffer
         * [id+count, length + count[. */
        src = (void*)((uintptr_t)(vec->buffer) + vec->data_size * id);
        dst = (void*)((uintptr_t)(buffer) + vec->data_size * (id + count));
        dst = memcpy(dst, src, vec->data_size * (vec->length - id));
      }

      /* Set the src/dst pointer of the data insertion process. */
      dst = (void*)((uintptr_t)(buffer) + vec->data_size * id);
      src = data;
      for(i = 0; i < count; ++i) {
        dst = memcpy(dst, src, vec->data_size);
        dst = (void*)((uintptr_t)(dst) + vec->data_size);
      }

      /* The data to insert may be contained in vec, i.e. free vec->buffer
       * *AFTER* the insertion. */
      if(vec->buffer)
        MEM_FREE(vec->allocator, vec->buffer);

      vec->buffer = buffer;
      vec->capacity = new_capacity;
      buffer = NULL;

    } else {
      if(id < vec->length) {
        src = (void*)((uintptr_t)(vec->buffer) + vec->data_size * id);
        dst = (void*)((uintptr_t)(vec->buffer) + vec->data_size * (id + count));
        dst = memmove(dst, src, vec->data_size * (vec->length - id));
      }

      /* Set the src/dst pointer of the data insertion process. Note that If the
       * data to insert lies in the vector range [id, vec.length[ then it was
       * previously memoved. Its new address is offseted by count * data_size
       * bytes. */
      dst = (void*)((uintptr_t)(vec->buffer) + vec->data_size * id);
      if(IS_MEMORY_OVERLAPPED
         (data,
          vec->data_size,
          (void*)((uintptr_t)(vec->buffer) + vec->data_size * id),
          (vec->length - id) * vec->data_size)) {
        src = (void*)((uintptr_t)data + count * vec->data_size);
      } else {
        src = data;
      }
      for(i = 0; i < count; ++i) {
        dst = memcpy(dst, src, vec->data_size);
        dst = (void*)((uintptr_t)(dst) + vec->data_size);
      }
    }
  }
  vec->length += count;

exit:
  return err;
error:
  if(buffer)
    MEM_FREE(vec->allocator, buffer);
  goto exit;

}