Plan 9 from Bell Labs’s /usr/web/sources/contrib/de0u/root/sys/src/cmd/divergefs/array.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.



#include <u.h>
#include <libc.h>
#include "common.h"
#include "function.h"
#include "collection.h"
#include "array.h"

static void array_allocate(Array *self, uint capacity);
static void array_grow(Array *self);
static void array_grow_by_factor(Array *self, uint factor);

enum 
{ 
  ARRAY_DEFAULT_SIZE = COLLECTION_DEFAULT_SIZE,
  ARRAY_GROWTH_FACTOR = 2
};

static void array_init_size(Array *self, uint size)
{
  assert_valid(self);
  memset(self, 0, sizeof(*self));
  array_allocate(self, size);
}

static void array_init(Array *self)
{
  assert_valid(self);
  array_init_size(self, ARRAY_DEFAULT_SIZE);
}

Array *array_new(void)
{
  Array *result = (Array *)emalloc_fs(sizeof(*result));
  array_init(result);
  return result;
}

Array *array_new_size(uint size)
{
  Array *result = (Array *)emalloc_fs(sizeof(*result));
  array_init_size(result, size);
  return result;
}

static void array_destroy(Array *self)
{
  assert_valid(self);

  free(self->elements);
  self->elements = nil;
  self->total = 0;
  self->capacity = 0;
}

void array_free(Array *self)
{
  if(self == nil)
  {
    return;
  }
  array_destroy(self);
  free(self);
}

void array_free_with(Array *self, functionunary free_each)
{
  array_unary_do(self, free_each);
  array_free(self);
}

static void array_allocate(Array *self, uint capacity)
{
  assert_valid(self);
  self->capacity = capacity;
  self->elements = erealloc_fs(self->elements, 
    sizeof(self->elements[0]) * self->capacity);
}

void array_clear(Array *self)
{
  assert_valid(self);
  self->total = 0;
}

void array_clear_with(Array *self, functionunary clear)
{
  assert_valid(self);
  assert_valid(clear);
  array_unary_do(self, clear);
  array_clear(self);
}

void *array_at(Array *self, uint index)
{
  assert_valid(self);
  assert_valid(self->elements);
  assert(index < array_size(self));
  return self->elements[index];
}

void array_put(Array *self, uint index, void *p)
{
  assert_valid(self);
  assert(index < array_size(self));
  self->elements[index] = p;
}

static bool array_isfull(Array *self)
{
  assert_valid(self);
  return self->total == self->capacity;
}

static void array_grow_if_full(Array *self)
{
  if(array_isfull(self))
  {
    array_grow(self);
  }
}

void array_add(Array *self, void *p)
{
  assert_valid(self);
  assert_valid(self->elements);

  array_grow_if_full(self);
  assert(array_size(self) < self->capacity);
  self->elements[self->total] = p;
  ++(self->total);
}

uint array_size(Array *self)
{
  assert_valid(self);
  return self->total;
}

void *array_default_nil_value(void)
{
  return nil;
}

void array_resize(Array *self, uint size)
{
  array_resize_with(self, size, array_default_nil_value);
}

void array_resize_with(Array *self, uint size, generator default_value)
{
  assert_valid(self);
  assert_valid(default_value);

  while(array_size(self) < size)
  {
    array_add(self, default_value());
  }

  self->total = size;
}

static void array_grow(Array *self)
{
  assert_valid(self);
  array_grow_by_factor(self, ARRAY_GROWTH_FACTOR);
}

static void array_grow_by_factor(Array *self, uint factor)
{
  assert_valid(self);
  array_allocate(self, self->capacity * factor);
}

void array_do(Array *self, collectioneach each, void *arg)
{
  int i;
  assert_valid(self);
  assert_valid(each);
  assert_valid(self->elements);

  for(i = 0; i < array_size(self); ++i)
  {
    if(each(self->elements[i], arg) == COLLECTION_DO_STOP)
    {
      break;
    }
  }
}

void array_unary_do(Array *self, functionunary each)
{
  int i;
  assert_valid(self);
  assert_valid(each);

  for(i = 0; i < array_size(self); ++i)
  {
    each(self->elements[i]);
  }
}


typedef struct ArrayDetectData
{
  collectiondetect detect;
  bool found;
  void *result;
  void *arg;
} ArrayDetectData;

static collection_do_ret array_detect_each(void *p, void *arg)
{
  ArrayDetectData *data = (ArrayDetectData *)arg;
  assert_valid(data);

  if(data->detect(p, data->arg))
  {
    data->found = true;
    data->result = p;
    return COLLECTION_DO_STOP;
  }
  return COLLECTION_DO_CONTINUE;
}

bool array_detect(Array *self, 
  collectiondetect detect, void **result, void *arg)
{
  ArrayDetectData data = (ArrayDetectData){detect, false, nil, arg};
  assert_valid(self);
  assert_valid(detect);

  array_do(self, array_detect_each, &data);

  if(result != nil)
  {
    *result = data.result;
  }
  return data.found;
}


void array_push(Array *self, void *p)
{
  array_add(self, p);
}

void *array_last(Array *self)
{
  assert_valid(self);
  assert(array_notempty(self));
  return array_at(self, array_size(self) - 1);
}

void *array_pop(Array *self)
{
  void *result = array_last(self);

  --(self->total);
  return result;
}

bool array_isempty(Array *self)
{
  assert_valid(self);
  return self->total == 0;
}

bool array_notempty(Array *self)
{
  return !array_isempty(self);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].