generator.c


1
#include "generator.h"
2
#include <string.h>
3
#include <stdlib.h>
4
5
static int generator_count_sub(void* arg, void* result){
6
  (void)result;
7
  (*(ssize_t*)arg) += 1;
8
  return 0;
9
}
10
11
int generator_count( const generic_generator_callback generator, const void*const args ){
12
  ssize_t result = 0;
13
  if(generator(&result, generator_count_sub, args))
14
    result = -1;
15
  return result;
16
}
17
18
struct generator_to_array_params {
19
  const size_t n, result_size;
20
  const bool reverse;
21
  size_t i;
22
  char* mem;
23
};
24
25
static int generator_to_array_sub(void* args, void* result){
26
  struct generator_to_array_params* a = args;
27
  if(a->i >= a->n || !result)
28
    return -1;
29
  memcpy(a->mem, result, a->result_size);
30
  a->i += 1;
31
  if(a->reverse){
32
    a->mem -= a->result_size;
33
  }else{
34
    a->mem += a->result_size;
35
  }
36
  return 0;
37
}
38
39
int generator_to_array( const generic_generator_callback generator, const void*const args, size_t result_size, size_t* res_n, void** result, bool reverse ){
40
  ssize_t n = generator_count(generator, args);
41
  if(n < 0)
42
    return -1;
43
  if(n == 0){
44
    *result = 0;
45
    *res_n = 0;
46
    return 0;
47
  }
48
  void* result_array = malloc(n * result_size);
49
  if(!result_array)
50
    return -1;
51
52
  struct generator_to_array_params params = {
53
    .result_size = result_size,
54
    .reverse = reverse,
55
    .mem = (char*)result_array + (n-1) * result_size,
56
    .n = n,
57
  };
58
  if(generator(&params, generator_to_array_sub, args) || params.i != params.n){
59
    free(result_array);
60
    return -1;
61
  }
62
63
  *result = result_array;
64
  *res_n = n;
65
  return 0;
66
}