labcomm_mem_writer.c 4.53 KB
Newer Older
Oscar Olsson's avatar
Oscar Olsson committed
1
2
#include "labcomm_mem_writer.h"

3
4
#include <stddef.h>  // For size_t.
#include <stdarg.h>
5
#include <stdlib.h>
Oscar Olsson's avatar
Oscar Olsson committed
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
#include <errno.h>

#include "labcomm.h"
#include "cppmacros.h"

#define BUFFER_SIZE 150 // Suitable size is at least the size of a fully encoded message. Found by inspecting size of file genreated from the labcomm_fs_reader_writer.c on the same message type.

// Put encdoded data directly in mcontext->mbuf or malloc new temporary memory.
// 1 == Allocate new memory.
// 2 == Use mcontext->buf directly. But _beware_; you can not then later change 
// mcontext->buf to something else since the writer gets a reference to this 
// buffer!
#if defined(MEM_WRITER_ENCODED_BUFFER) && (EMPTY(MEM_WRITER_ENCODED_BUFFER) != 1)
  #define ENCODED_BUFFER MEM_WRITER_ENCODED_BUFFER
#else
  #define ENCODED_BUFFER 1
#endif

static int get_writer_available(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext);
static void copy_data(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext, unsigned char *mbuf);

/*
 * Write encoded messages to memory. w->context is assumed to be a pointer to a
 * labcomm_mem_writer_context_t structure.
 */
Sven Robertz's avatar
Sven Robertz committed
31
int labcomm_mem_writer(labcomm_writer_t *w, labcomm_writer_action_t action, ...)
Oscar Olsson's avatar
Oscar Olsson committed
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
{
  int result = 0;
  // Unwrap pointers for easy access.
  labcomm_mem_writer_context_t *mcontext = (labcomm_mem_writer_context_t *) w->context;
  unsigned char *mbuf = mcontext->buf;

  switch (action) {
  case labcomm_writer_alloc: {
#if (ENCODED_BUFFER == 1)
    w->data = malloc(BUFFER_SIZE); // Buffer that LabComm will use for putting the encoded data.
    if (w->data == NULL) {
      result = -ENOMEM;
      w->data_size = 0;
      w->count = 0;
      w->pos = 0;
    } else {
      w->data_size = BUFFER_SIZE;
      w->count = BUFFER_SIZE;
      w->pos = 0;
    }
#elif (ENCODED_BUFFER == 2)
    w->data = mbuf;
    int bytes_left = (mcontext->length - mcontext->write_pos);
    w->data_size = bytes_left;
    w->count = bytes_left;
    w->pos = mcontext->write_pos;
#endif
     } break;
  case labcomm_writer_free:{
#if (ENCODED_BUFFER == 1)
    free(w->data);
#endif
    w->data = 0;
    w->data_size = 0;
    w->count = 0;
    w->pos = 0;
   } break;
69
70
  case labcomm_writer_start:
    case labcomm_writer_start_signature: {
Oscar Olsson's avatar
Oscar Olsson committed
71
72
73
74
75
76
#if (ENCODED_BUFFER == 1)
    w->pos = 0;
#elif (ENCODED_BUFFER == 2)
    w->pos = mcontext->write_pos;
#endif
    } break;
77
78
79
  case labcomm_writer_continue:
  case labcomm_writer_continue_signature: { 
    // Encode-buffer(w->data) is full; empty/handle it. (w->pos == w->count) most likely.
Oscar Olsson's avatar
Oscar Olsson committed
80
81
82
83
84
85
86
87
#if (ENCODED_BUFFER == 1)
    copy_data(w, mcontext, mbuf);
    result = w->pos; // Assume result here should be number of bytes written.
    w->pos = 0;
#elif (ENCODED_BUFFER == 2)
    mcontext->write_pos = w->pos;
#endif
     result = 0;
88
89
90
    } break;
  case labcomm_writer_end:
  case labcomm_writer_end_signature:{ // Nothing more to encode, handle encode-buffer(w->data).
Oscar Olsson's avatar
Oscar Olsson committed
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#if (ENCODED_BUFFER == 1)
    copy_data(w, mcontext, mbuf);
    result = w->pos;
    w->pos = 0;
#elif (ENCODED_BUFFER == 2)
    mcontext->write_pos = w->pos;
#endif
    result = 0;
    } break;
  }
  return result;
}

labcomm_mem_writer_context_t *labcomm_mem_writer_context_t_new(size_t init_pos, size_t length, unsigned char *buf)
{
  labcomm_mem_writer_context_t *mcontext = (labcomm_mem_writer_context_t *) malloc(sizeof(labcomm_mem_writer_context_t));
  if (mcontext == NULL) {
    //fprintf(stderr, "error: Can not allocate labcomm_mem_writer_context_t.\n");
  } else {
    mcontext->write_pos = init_pos;
    mcontext->length = length;
    mcontext->buf = buf;
  }
  return mcontext;
}

void labcomm_mem_writer_context_t_free(labcomm_mem_writer_context_t **mcontext)
{
  free(*mcontext);
  *mcontext = NULL;
}

// Get the number of available bytes in the mcontext->buf buffer.
static int get_writer_available(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext)
{
  return (mcontext->length - mcontext->write_pos);
}

// Copy data from encoded buffer to mbuf.
static void copy_data(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext, unsigned char *mbuf)
{
        int writer_available = get_writer_available(w, mcontext);
  if (( writer_available - w->pos) < 0) {
    w->on_error(LABCOMM_ERROR_ENC_BUF_FULL, 3, "labcomm_writer_t->pos=%i, but available in mcontext is %i", w->pos, writer_available); 
  } else {
    int i;
    for (i = 0; i < w->pos; ++i, mcontext->write_pos++) {
      mbuf[mcontext->write_pos] = w->data[i];
    }
  }
}

void test_copy_data(labcomm_writer_t *w, labcomm_mem_writer_context_t *mcontext, unsigned char *mbuf)
{
  copy_data(w, mcontext, mbuf); 
}