sample

#include <stdio.h>
#include "closure.h"
#include "vclosures.h"

void f(void*)
{
  printf("hello closure!\n");
}

void f2(struct closure_void_str* p)
{
  printf("hello %s!\n", p->text);
}

int main()
{
  vclosures vclosures = VCLOSURES_INIT;

  vclosures_append(&vclosures, closure_void_new(&f));
  vclosures_append(&vclosures, closure_void_str_new(&f2, "thiago"));

  for (size_t i = 0; i < vclosures_size(&vclosures); i++)
  {
    closure_void_call(vclosures_get(&vclosures, i));
  }

  vclosures_destructor(&vclosures);
  return 0;
}

header

#ifndef _vclosures_H
#define _vclosures_H

#include "closure.h"

typedef struct vclosures_t
{
  size_t    size;
  size_t    capacity;
  closure_void** data;
} vclosures;

#define VCLOSURES_INIT { 0, 0, 0 }

void           vclosures_destructor(vclosures* p);
size_t         vclosures_reserve(vclosures* p, size_t size);
void           vclosures_erase_n(vclosures* p, size_t index, size_t count);
size_t         vclosures_append(vclosures* p, closure_void* pItem);
closure_void*  vclosures_get(const vclosures* p, size_t index);
size_t         vclosures_size(vclosures* p);
closure_void*  vclosures_back(vclosures* p);
closure_void*  vclosures_front(vclosures* p);
bool           vclosures_empty(vclosures* p);
void           vclosures_clear(vclosures* p);
void           vclosures_erase(vclosures* p, size_t index);
size_t         vclosures_capacity(vclosures* p);
closure_void** vclosures_data(vclosures* p);

#endif  //_vclosures_H


source

#include "stdafx.h"
#include "vclosures.h"
#include <stdlib.h>


inline void delete_elements(closure_void** p, size_t nelements)
{
  for (size_t i = 0; i < nelements; i++)
  {
    closure_void_delete(p[i]);
  }
}

size_t vclosures_reserve(vclosures* p, size_t nelements)
{
  if (nelements > p->capacity)
  {
    size_t nelem = nelements;

    if (p->data == NULL)
    {
      p->data = (closure_void**)malloc(nelem * sizeof(closure_void*));
    }
    else
    {
      p->data = (closure_void**)realloc((void*)p->data, nelem * sizeof(closure_void*));
    }
    p->capacity = nelements;
  }

  return (p->data != 0) ? nelements : 0;
}

static size_t vclosures_grow(vclosures* p, size_t nelements)
{
  const size_t INITIAL_CAPACITY = 4;
  const size_t MAX_CAPACITY = (size_t)(UINT_MAX / sizeof(closure_void*));
  if (nelements > p->capacity)
  {
    size_t newCap = p->capacity == 0 ? INITIAL_CAPACITY : p->capacity;
    while (newCap < nelements)
    {
      newCap *= 2;

      if (newCap < nelements ||
        newCap > MAX_CAPACITY)
      {
        /*overflow check*/
        newCap = MAX_CAPACITY;
      }
    }
    return vclosures_reserve(p, newCap);
  }
  return p->capacity;
}

void vclosures_destructor(vclosures* p)
{
  vclosures_clear(p);
  free(p->data);
  p->data = 0;
}

static size_t vclosures_insert_n(vclosures* p,
  size_t index,
  closure_void** pSource,
  size_t nelements)
{
  size_t result = vclosures_grow(p, p->size + nelements);

  if (result == 0)
  {
    delete_elements(pSource, nelements);
    return 0;
  }

  if (index < p->size)
  {
    memmove(&p->data[index + nelements],
      &p->data[index],
      (sizeof(closure_void*)) * (p->size - index));
  }

  memcpy((void*)&p->data[index], &pSource[0], sizeof(closure_void*) * nelements);
  
  p->size += nelements;

  return nelements;
}

void vclosures_erase_n(vclosures* p,
  size_t position,
  size_t nelements)
{
  if (nelements > 0)
  {
    delete_elements(&p->data[position], nelements);
    memmove(p->data + position,
      p->data + position + nelements,
      sizeof(closure_void*) * nelements);

    p->size = p->size - nelements;
  }
}

size_t vclosures_append(vclosures* p, closure_void* pItem)
{
  return vclosures_insert_n(p, p->size, &pItem, 1);
}

closure_void* vclosures_get(const vclosures* p, size_t index)
{
  return p->data[index];
}

size_t vclosures_size(vclosures* p)
{
  return p->size;
}

closure_void* vclosures_back(vclosures* p)
{
  return vclosures_get(p, vclosures_size(p) - 1);
}

closure_void* vclosures_front(vclosures* p)
{
  return vclosures_get(p, 0);
}

bool vclosures_empty(vclosures* p)
{
  return vclosures_size(p) == 0;
}

void vclosures_clear(vclosures* p)
{
  vclosures_erase_n(p, 0, p->size);
}

void vclosures_erase(vclosures* p, size_t index)
{
  vclosures_erase_n(p, index, 1);
}

size_t vclosures_capacity(vclosures* p)
{
  return p->capacity;
}

closure_void** vclosures_data(vclosures* p)
{
  return p->data;
}