blob: 5e53c1ff0e2e62b93e4f5075ef9c77f54fa1fcb9 [file] [log] [blame]
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include <u.h>
#include <libc.h>
#include "go.h"
enum {
DEFAULTCAPACITY = 16,
};
struct Array
{
int32 length; // number of elements
int32 size; // element size
int32 capacity; // size of data in elements
char *data; // element storage
};
Array*
arraynew(int32 capacity, int32 size)
{
Array *result;
if(capacity < 0)
fatal("arraynew: capacity %d is not positive", capacity);
if(size < 0)
fatal("arraynew: size %d is not positive\n", size);
result = malloc(sizeof(*result));
if(result == nil)
fatal("arraynew: malloc failed\n");
result->length = 0;
result->size = size;
result->capacity = capacity == 0 ? DEFAULTCAPACITY : capacity;
result->data = malloc(result->capacity * result->size);
if(result->data == nil)
fatal("arraynew: malloc failed\n");
return result;
}
void
arrayfree(Array *array)
{
if(array == nil)
return;
free(array->data);
free(array);
}
int32
arraylength(Array *array)
{
return array->length;
}
void*
arrayget(Array *array, int32 index)
{
if(array == nil)
fatal("arrayget: array is nil\n");
if(index < 0 || index >= array->length)
fatal("arrayget: index %d is out of bounds for length %d\n", index, array->length);
return array->data + index * array->size;
}
void
arrayset(Array *array, int32 index, void *element)
{
if(array == nil)
fatal("arrayset: array is nil\n");
if(element == nil)
fatal("arrayset: element is nil\n");
if(index < 0 || index >= array->length)
fatal("arrayget: index %d is out of bounds for length %d\n", index, array->length);
memmove(array->data + index * array->size, element, array->size);
}
static void
ensurecapacity(Array *array, int32 capacity)
{
int32 newcapacity;
char *newdata;
if(array == nil)
fatal("ensurecapacity: array is nil\n");
if(capacity < 0)
fatal("ensurecapacity: capacity %d is not positive", capacity);
if(capacity >= array->capacity) {
newcapacity = capacity + (capacity >> 1);
newdata = realloc(array->data, newcapacity * array->size);
if(newdata == nil)
fatal("ensurecapacity: realloc failed\n");
array->capacity = newcapacity;
array->data = newdata;
}
}
void
arrayadd(Array *array, void *element)
{
if(array == nil)
fatal("arrayset: array is nil\n");
if(element == nil)
fatal("arrayset: element is nil\n");
ensurecapacity(array, array->length + 1);
array->length++;
arrayset(array, array->length - 1, element);
}
int32
arrayindexof(Array *array, void *element)
{
void *p;
int32 i;
for(i = 0; i < array->length; i++) {
p = arrayget(array, i);
if(memcmp(p, &element, array->size) == 0)
return i;
}
return -1;
}
void
arraysort(Array *array, int (*cmp)(const void*, const void*))
{
qsort(array->data, array->length, array->size, cmp);
}