summaryrefslogtreecommitdiff
path: root/kit/input_stream.c
blob: 369cf6487f103e8b697c88e434eed64b4b8ed0a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "input_stream.h"

#include <string.h>

enum { KIT_INPUT_STREAM_STR, KIT_INPUT_STREAM_FILE };

typedef struct {
  i64              type;
  kit_allocator_t *alloc;
} kit_is_state_basic_t;

typedef struct {
  i64              type;
  kit_allocator_t *alloc;
  kit_str_t        string;
} kit_is_state_str_t;

typedef struct {
  i64              type;
  kit_allocator_t *alloc;
  FILE            *file;
} kit_is_state_file_t;

static int kit_is_check_type_(void *state, i64 type) {
  kit_is_state_basic_t *basic = (kit_is_state_basic_t *) state;
  return basic != NULL && basic->type == type;
}

static i64 kit_read_str_(void *state, kit_str_t destination) {
  if (!kit_is_check_type_(state, KIT_INPUT_STREAM_STR))
    return 0;

  kit_is_state_str_t *str = (kit_is_state_str_t *) state;
  i64 size = destination.size < str->string.size ? destination.size
                                                 : str->string.size;
  memcpy(destination.values, str->string.values, size);
  str->string.values += size;
  str->string.size -= size;
  return size;
}

static i64 kit_read_file_(void *state, kit_str_t destination) {
  if (!kit_is_check_type_(state, KIT_INPUT_STREAM_FILE))
    return 0;

  kit_is_state_file_t *f = (kit_is_state_file_t *) state;

  if (f->file == NULL || feof(f->file))
    return 0;

  i64 size = (i64) fread(destination.values, 1, destination.size,
                         f->file);

  if (size <= 0)
    return 0;

  return size;
}

kit_is_handle_t kit_is_wrap_string(kit_str_t        string,
                                   kit_allocator_t *alloc) {
  kit_is_handle_t in;
  memset(&in, 0, sizeof in);

  kit_is_state_str_t *state = (kit_is_state_str_t *)
      kit_alloc_dispatch(alloc, KIT_ALLOCATE,
                         sizeof(kit_is_state_str_t), 0, NULL);
  if (state != NULL) {
    memset(state, 0, sizeof *state);
    state->type   = KIT_INPUT_STREAM_STR;
    state->string = string;
    state->alloc  = alloc;
    in.state      = state;
    in.read       = kit_read_str_;
  }
  return in;
}

kit_is_handle_t kit_is_wrap_file(FILE *f, kit_allocator_t *alloc) {
  kit_is_handle_t in;
  memset(&in, 0, sizeof in);

  kit_is_state_file_t *state = (kit_is_state_file_t *)
      kit_alloc_dispatch(alloc, KIT_ALLOCATE,
                         sizeof(kit_is_state_file_t), 0, NULL);

  if (state != NULL) {
    memset(state, 0, sizeof *state);
    state->type  = KIT_INPUT_STREAM_FILE;
    state->file  = f;
    state->alloc = alloc;
    in.state     = state;
    in.read      = kit_read_file_;
  }

  return in;
}

void kit_is_destroy(kit_is_handle_t in) {
  kit_is_state_basic_t *basic = (kit_is_state_basic_t *) in.state;
  if (basic != NULL)
    kit_alloc_dispatch(basic->alloc, KIT_DEALLOCATE, 0, 0, in.state);
}