IODA Bundle
encode.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 1996-2012 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation nor
8  * does it submit to any jurisdiction.
9  */
10 
11 #include <memory>
12 #include <cstring>
13 
14 // TODO: unneeded
15 #include <fcntl.h>
16 #include <unistd.h>
17 
18 #include "eckit/filesystem/TmpFile.h"
19 #include "eckit/io/Buffer.h"
20 #include "eckit/testing/Test.h"
21 
22 #include "odc/api/odc.h"
23 
24 using namespace eckit::testing;
25 
26 // Specialise custom deletion
27 
28 #define CHECK_RETURN(x) EXPECT((x) == ODC_SUCCESS)
29 
30 namespace std{
31 template <> struct default_delete<odc_encoder_t> {
32  void operator() (odc_encoder_t* e) { CHECK_RETURN(odc_free_encoder(e)); }
33 };
34 
35 template <> struct default_delete<odc_reader_t> {
36  void operator() (odc_reader_t* o) { CHECK_RETURN(odc_close(o)); }
37 };
38 
39 template <> struct default_delete<odc_frame_t> {
40  void operator() (odc_frame_t* t) { CHECK_RETURN(odc_free_frame(t)); }
41 };
42 
43 template <> struct default_delete<odc_decoder_t> {
44  void operator() (odc_decoder_t* t) { CHECK_RETURN(odc_free_decoder(t)); }
45 };
46 }
47 
48 // ------------------------------------------------------------------------------------------------------
49 
50 
51 // TODO: Row-major
52 // TODO: Column major
53 
54 CASE("Encode data in standard tabular form") {
55 
57 
58  const int nrows = 15;
59  const int ncols = 8;
60  double data[nrows][ncols];
61 
62  // Construct some data to encode
63 
64  for (int row = 0; row < nrows; ++row) {
65  for (int col = 0; col < 4; ++col) {
66  data[row][col] = (1000 * row) + (3 * col);
67  }
68  data[row][4] = 0;
69  data[row][5] = 0;
70  ::strncpy(reinterpret_cast<char*>(&data[row][4]), "abcdefghijkl", 2*sizeof(double));
71  for (int col = 6; col < ncols; ++col) {
72  data[row][col] = (1000 * row) + (3 * col);
73  }
74  }
75 
76  // Configure the encoder to encode said data
77 
78  odc_encoder_t* enc = nullptr;
80  std::unique_ptr<odc_encoder_t> enc_deleter(enc);
81 
82  bool columnMajor = false;
84  CHECK_RETURN(odc_encoder_set_data_array(enc, data, ncols * sizeof(double), nrows, columnMajor));
90  int elementSize = 2 * sizeof(double);
91  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 4, elementSize, 0, 0));
94  CHECK_RETURN(odc_encoder_column_add_bitfield(enc, 6, "bits1", 2));
95  CHECK_RETURN(odc_encoder_column_add_bitfield(enc, 6, "bits2", 3));
96  CHECK_RETURN(odc_encoder_column_add_bitfield(enc, 6, "bits3", 1));
97 
98  // Do the encoding
99 
100  eckit::Buffer encoded(1024 * 1024);
101  long sz;
102  CHECK_RETURN(odc_encode_to_buffer(enc, encoded.data(), encoded.size(), &sz));
103 
104  // Check that the table contains what we expect
105 
106  odc_reader_t* reader = nullptr;
107  CHECK_RETURN(odc_open_buffer(&reader, encoded.data(), sz));
108  EXPECT(reader);
109  std::unique_ptr<odc_reader_t> reader_deleter(reader);
110 
111  odc_frame_t* frame = nullptr;
112  CHECK_RETURN(odc_new_frame(&frame, reader));
113  EXPECT(frame);
114  std::unique_ptr<odc_frame_t> frame_deleter(frame);
115 
117 
118  int column_count;
119  CHECK_RETURN(odc_frame_column_count(frame, &column_count));
120  EXPECT(column_count == ncols-1);
121 
122  long row_count;
123  CHECK_RETURN(odc_frame_row_count(frame, &row_count));
124  EXPECT(row_count == nrows);
125 
126  const char* column_names[] = {"col1", "col2", "col3", "col4", "col5", "col6", "col7"};
128  const char* bitfield_names[] = {"bits1", "bits2", "bits3"};
129  int bitfield_sizes[] = {2, 3, 1};
130  int bitfield_offsets[] = {0, 2, 5};
131 
132  for (int col = 0; col < 7; ++col) {
133 
134  const char* name;
135  int type;
136  int elementSize;
137  int bitfieldCount;
138  CHECK_RETURN(odc_frame_column_attributes(frame, col, &name, &type, &elementSize, &bitfieldCount));
139  EXPECT(name);
140  EXPECT(::strcmp(name, column_names[col]) == 0);
141  EXPECT(type == column_types[col]);
142  EXPECT(elementSize == (col == 4 ? 2 : 1) * int(sizeof(double)));
143  EXPECT(bitfieldCount == (col == 6 ? 3 : 0));
144 
145  if (col == 6) {
146  for (int bf = 0; bf < 3; ++bf) {
147  const char* bf_name;
148  int bfSize;
149  int bfOffset;
150  CHECK_RETURN(odc_frame_bitfield_attributes(frame, col, bf, &bf_name, &bfOffset, &bfSize));
151  EXPECT(bf_name);
152  EXPECT(::strcmp(bf_name, bitfield_names[bf]) == 0);
153  EXPECT(bfSize == bitfield_sizes[bf]);
154  EXPECT(bfOffset == bitfield_offsets[bf]);
155  }
156  }
157  }
158 
159  // Test that the data is correctly encoded
160 
161  odc_decoder_t* decoder;
162  CHECK_RETURN(odc_new_decoder(&decoder));
163  EXPECT(decoder);
164  std::unique_ptr<odc_decoder_t> decoder_deleter(decoder);
165 
167 
168  long rows_decoded;
169  CHECK_RETURN(odc_decode(decoder, frame, &rows_decoded));
170  EXPECT(rows_decoded == nrows);
171 
172  const void* p;
173  CHECK_RETURN(odc_decoder_column_data_array(decoder, 0, 0, 0, &p));
174  const void* pdata;
175  long row_stride;
176  bool decodeColumnMajor;
177  CHECK_RETURN(odc_decoder_data_array(decoder, &pdata, &row_stride, 0, &decodeColumnMajor));
178  EXPECT(!decodeColumnMajor);
179  EXPECT(p != nullptr);
180  EXPECT(pdata != nullptr);
181  EXPECT(p == pdata);
182  EXPECT(row_stride == 8*sizeof(double));
183 
184  double vals1[] = {0, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000};
185  double vals2[] = {3, 1003, 2003, 3003, 4003, 5003, 6003, 7003, 8003, 9003, 10003, 11003, 12003, 13003, 14003};
186  double vals3[] = {6, 1006, 2006, 3006, 4006, 5006, 6006, 7006, 8006, 9006, 10006, 11006, 12006, 13006, 14006};
187  double vals4[] = {9, 1009, 2009, 3009, 4009, 5009, 6009, 7009, 8009, 9009, 10009, 11009, 12009, 13009, 14009};
188  double vals6[] = {18, 1018, 2018, 3018, 4018, 5018, 6018, 7018, 8018, 9018, 10018, 11018, 12018, 13018, 14018};
189  double vals7[] = {21, 1021, 2021, 3021, 4021, 5021, 6021, 7021, 8021, 9021, 10021, 11021, 12021, 13021, 14021};
190 
191  const double (*row_data)[8] = reinterpret_cast<const double (*)[8]>(pdata);
192 
193  for (size_t row = 0; row < nrows; ++row) {
194  EXPECT(vals1[row] == row_data[row][0]);
195  EXPECT(vals2[row] == row_data[row][1]);
196  EXPECT(vals3[row] == row_data[row][2]);
197  EXPECT(vals4[row] == row_data[row][3]);
198  EXPECT(::strncmp("abcdefghijkl", reinterpret_cast<const char*>(&row_data[row][4]), 2*sizeof(double)) == 0);
199  EXPECT(vals6[row] == row_data[row][6]);
200  EXPECT(vals7[row] == row_data[row][7]);
201  }
202 
203  EXPECT(odc_next_frame(frame) == ODC_ITERATION_COMPLETE);
204 }
205 
206 
207 CASE("Encode from columnar data") {
208 
210 
211  const int nrows = 10;
212  const int ncols = 5;
213 
214  // Construct some source data
215 
216  long icol[nrows] = {1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 0};
217  long bcol[nrows] = {1101, 2202, 3303, 4404, 5505, 6606, 7707, 8808, 9909, 0};
218  char scol[nrows][3 * sizeof(double)] = {0};
219  double dcol[nrows] = {1131, 2232, 3333, 4434, 5535, 6636, 7737, 8838, 9939, 0};
220  double rcol[nrows] = {1141, 2242, 3343, 4444, 5545, 6646, 7747, 8848, 9949, 0};
221  for (size_t i = 0; i < nrows; ++i) {
222  ::strncpy(&scol[i][0], "abcdefghhgfedcbazzzz", 3*sizeof(double));
223  }
224 
225  // Configure the encoder to encode said data
226 
227  odc_encoder_t* enc = nullptr;
229  std::unique_ptr<odc_encoder_t> enc_deleter(enc);
230 
237 
238  int elementSizeCol2 = 3 * sizeof(double);
239  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 0, 0, 0, icol));
240  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 1, 0, 0, bcol));
241  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 2, elementSizeCol2, 0, scol));
242  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 3, 0, 0, dcol));
243  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 4, 0, 0, rcol));
244 
245  // Do the encoding
246 
247  eckit::Buffer encoded(1024 * 1024);
248  long sz;
249  CHECK_RETURN(odc_encode_to_buffer(enc, encoded.data(), encoded.size(), &sz));
250 
251  // Check that we have encoded what we think we have encoded
252 
253  odc_reader_t* reader = nullptr;
254  CHECK_RETURN(odc_open_buffer(&reader, encoded.data(), sz));
255  EXPECT(reader);
256  std::unique_ptr<odc_reader_t> reader_deleter(reader);
257 
258  odc_frame_t* frame = nullptr;
259  CHECK_RETURN(odc_new_frame(&frame, reader));
260  EXPECT(frame);
261  std::unique_ptr<odc_frame_t> frame_deleter(frame);
262 
264 
265  int column_count;
266  CHECK_RETURN(odc_frame_column_count(frame, &column_count));
267  EXPECT(column_count == ncols);
268 
269  long row_count;
270  CHECK_RETURN(odc_frame_row_count(frame, &row_count));
271  EXPECT(row_count == nrows);
272 
273  // Test that the data is correctly encoded
274 
275  odc_decoder_t* decoder;
276  CHECK_RETURN(odc_new_decoder(&decoder));
277  EXPECT(decoder);
278  std::unique_ptr<odc_decoder_t> decoder_deleter(decoder);
279 
281 
282  long rows_decoded;
283  CHECK_RETURN(odc_decode(decoder, frame, &rows_decoded));
284  EXPECT(rows_decoded == nrows);
285 
286  const void* pdata;
287  long row_stride;
288  bool decodeColumnMajor;
289  CHECK_RETURN(odc_decoder_data_array(decoder, &pdata, &row_stride, 0, &decodeColumnMajor));
290  EXPECT(!decodeColumnMajor);
291  EXPECT(pdata != nullptr);
292  EXPECT(row_stride == 7*sizeof(double));
293 
294  const double (*row_data)[7] = reinterpret_cast<const double (*)[7]>(pdata);
295 
296  for (size_t row = 0; row < nrows; ++row) {
297  EXPECT(reinterpret_cast<const long&>(row_data[row][0]) == icol[row]);
298  EXPECT(reinterpret_cast<const long&>(row_data[row][1]) == bcol[row]);
299  EXPECT(::strncmp("abcdefghhgfedcbazzzz", reinterpret_cast<const char*>(&row_data[row][2]), 3*sizeof(double)) == 0);
300  EXPECT(row_data[row][5] == dcol[row]);
301  EXPECT(row_data[row][6] == rcol[row]);
302  }
303 
304  EXPECT(odc_next_frame(frame) == ODC_ITERATION_COMPLETE);
305 }
306 
307 //// ------------------------------------------------------------------------------------------------------
308 
309 CASE("Encode data with custom stride") {
310 
312 
313  const int nrows = 5;
314  const int ncols = 5;
315 
316  // Construct some source data
317 
318  long icol[2*nrows] = {1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 0};
319  long bcol[2*nrows] = {1101, 2202, 3303, 4404, 5505, 6606, 7707, 8808, 9909, 0};
320  char scol[2*nrows][3 * sizeof(double)] = {0};
321  double dcol[2*nrows] = {1131, 2232, 3333, 4434, 5535, 6636, 7737, 8838, 9939, 0};
322  double rcol[2*nrows] = {1141, 2242, 3343, 4444, 5545, 6646, 7747, 8848, 9949, 0};
323  for (size_t i = 0; i < 2*nrows; ++i) {
324  ::strncpy(&scol[i][0], "abcdefghhgfedcbazzzz", 3*sizeof(double));
325  }
326 
327  // Configure the encoder to encode said data
328 
329  odc_encoder_t* enc = nullptr;
331  std::unique_ptr<odc_encoder_t> enc_deleter(enc);
332 
339 
340  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 0, 0, 2*sizeof(icol[0]), icol));
341  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 1, 0, 2*sizeof(bcol[0]), bcol));
342  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 2, sizeof(scol[0]), 2*sizeof(scol[0]), scol));
343  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 3, 0, 2*sizeof(dcol[0]), dcol));
344  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 4, 0, 2*sizeof(rcol[0]), rcol));
345 
346  // Do the encoding
347 
348  eckit::Buffer encoded(1024 * 1024);
349  long sz;
350  CHECK_RETURN(odc_encode_to_buffer(enc, encoded.data(), encoded.size(), &sz));
351 
352  // Check that we have encoded what we think we have encoded
353 
354  odc_reader_t* reader = nullptr;
355  CHECK_RETURN(odc_open_buffer(&reader, encoded.data(), sz));
356  EXPECT(reader);
357  std::unique_ptr<odc_reader_t> reader_deleter(reader);
358 
359  odc_frame_t* frame = nullptr;
360  CHECK_RETURN(odc_new_frame(&frame, reader));
361  EXPECT(frame);
362  std::unique_ptr<odc_frame_t> frame_deleter(frame);
363 
365 
366  int column_count;
367  CHECK_RETURN(odc_frame_column_count(frame, &column_count));
368  EXPECT(column_count == ncols);
369 
370  long row_count;
371  CHECK_RETURN(odc_frame_row_count(frame, &row_count));
372  EXPECT(row_count == nrows);
373 
374  // Test that the data is correctly encoded
375 
376  odc_decoder_t* decoder;
377  CHECK_RETURN(odc_new_decoder(&decoder));
378  EXPECT(decoder);
379  std::unique_ptr<odc_decoder_t> decoder_deleter(decoder);
380 
382 
383  long rows_decoded;
384  CHECK_RETURN(odc_decode(decoder, frame, &rows_decoded));
385  EXPECT(rows_decoded == nrows);
386 
387  const void* pdata;
388  long row_stride;
389  bool decodeColumnMajor;
390  CHECK_RETURN(odc_decoder_data_array(decoder, &pdata, &row_stride, 0, &decodeColumnMajor));
391  EXPECT(!decodeColumnMajor);
392  EXPECT(pdata != nullptr);
393  EXPECT(row_stride == 7*sizeof(double));
394 
395  const double (*row_data)[7] = reinterpret_cast<const double (*)[7]>(pdata);
396 
397  for (size_t row = 0; row < nrows; ++row) {
398  EXPECT(reinterpret_cast<const long&>(row_data[row][0]) == icol[2*row]);
399  EXPECT(reinterpret_cast<const long&>(row_data[row][1]) == bcol[2*row]);
400  EXPECT(::strncmp("abcdefghhgfedcbazzzz", reinterpret_cast<const char*>(&row_data[row][2]), 3*sizeof(double)) == 0);
401  EXPECT(row_data[row][5] == dcol[2*row]);
402  EXPECT(row_data[row][6] == rcol[2*row]);
403  }
404 
405  EXPECT(odc_next_frame(frame) == ODC_ITERATION_COMPLETE);
406 }
407 
408 // ------------------------------------------------------------------------------------------------------
409 
410 CASE("Encode with more rows that fit inside a table") {
411 
413 
414  const int nrows = 10;
415  const int ncols = 5;
416 
417  // Construct some source data
418 
419  long icol[nrows] = {1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 0};
420  long bcol[nrows] = {1101, 2202, 3303, 4404, 5505, 6606, 7707, 8808, 9909, 0};
421  char scol[nrows][3 * sizeof(double)] = {0};
422  double dcol[nrows] = {1131, 2232, 3333, 4434, 5535, 6636, 7737, 8838, 9939, 0};
423  double rcol[nrows] = {1141, 2242, 3343, 4444, 5545, 6646, 7747, 8848, 9949, 0};
424  for (size_t i = 0; i < nrows; ++i) {
425  ::strncpy(&scol[i][0], "abcdefghhgfedcbazzzz", 3*sizeof(double));
426  }
427 
428  // Configure the encoder to encode said data
429 
430  odc_encoder_t* enc = nullptr;
432  std::unique_ptr<odc_encoder_t> enc_deleter(enc);
433 
440 
441  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 0, 0, 0, icol));
442  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 1, 0, 0, bcol));
443  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 2, sizeof(scol[0]), 0, scol));
444  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 3, 0, 0, dcol));
445  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 4, 0, 0, rcol));
446 
447  // Set reduced number of lines per frame
448 
449  int maxPerFrame = 5;
450  CHECK_RETURN(odc_encoder_set_rows_per_frame(enc, maxPerFrame));
451 
452  // Do the encoding
453 
454  eckit::Buffer encoded(1024 * 1024);
455  long sz;
456  CHECK_RETURN(odc_encode_to_buffer(enc, encoded.data(), encoded.size(), &sz));
457 
458  // Check that we have encoded what we think we have encoded
459 
460  odc_reader_t* reader = nullptr;
461  CHECK_RETURN(odc_open_buffer(&reader, encoded.data(), sz));
462  EXPECT(reader);
463  std::unique_ptr<odc_reader_t> reader_deleter(reader);
464 
465  odc_frame_t* frame = nullptr;
466  CHECK_RETURN(odc_new_frame(&frame, reader));
467  EXPECT(frame);
468  std::unique_ptr<odc_frame_t> frame_deleter(frame);
469 
470  // We now expect two frames
471 
472  for (int frame_idx = 0; frame_idx < 2; ++frame_idx) {
473 
475  int row_offset = (frame_idx * maxPerFrame);
476 
477  int column_count;
478  CHECK_RETURN(odc_frame_column_count(frame, &column_count));
479  EXPECT(column_count == ncols);
480 
481  long row_count;
482  CHECK_RETURN(odc_frame_row_count(frame, &row_count));
483  EXPECT(row_count == (frame_idx ? nrows-maxPerFrame : maxPerFrame));
484 
485  // Test that the data is correctly encoded
486 
487  odc_decoder_t* decoder;
488  CHECK_RETURN(odc_new_decoder(&decoder));
489  EXPECT(decoder);
490  std::unique_ptr<odc_decoder_t> decoder_deleter(decoder);
491 
493 
494  long rows_decoded;
495  CHECK_RETURN(odc_decode(decoder, frame, &rows_decoded));
496  EXPECT(rows_decoded == row_count);
497 
498  const void* pdata;
499  long row_stride;
500  bool decodeColumnMajor;
501  CHECK_RETURN(odc_decoder_data_array(decoder, &pdata, &row_stride, 0, &decodeColumnMajor));
502  EXPECT(!decodeColumnMajor);
503  EXPECT(pdata != nullptr);
504  EXPECT(row_stride == 7*sizeof(double));
505 
506  const double (*row_data)[7] = reinterpret_cast<const double (*)[7]>(pdata);
507 
508  for (int row = 0; row < row_count; ++row) {
509  EXPECT(reinterpret_cast<const long&>(row_data[row][0]) == icol[row+row_offset]);
510  EXPECT(reinterpret_cast<const long&>(row_data[row][1]) == bcol[row+row_offset]);
511  EXPECT(::strncmp("abcdefghhgfedcbazzzz", reinterpret_cast<const char*>(&row_data[row][2]), 3*sizeof(double)) == 0);
512  EXPECT(row_data[row][5] == dcol[row+row_offset]);
513  EXPECT(row_data[row][6] == rcol[row+row_offset]);
514  }
515  }
516 
517  EXPECT(odc_next_frame(frame) == ODC_ITERATION_COMPLETE);
518 }
519 
520 // ------------------------------------------------------------------------------------------------------
521 
522 CASE("Encode to a file descriptor") {
523 
524  // Do some trivial encoding
525 
527 
528  const int nrows = 10;
529  long icol[nrows] = {1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 0};
530 
531  // Configure the encoder to encode said data
532 
533  odc_encoder_t* enc = nullptr;
535  std::unique_ptr<odc_encoder_t> enc_deleter(enc);
536 
539  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 0, 0, 0, icol));
540 
541  // Do the encoding
542 
543  eckit::TmpFile tf;
544  int fd = ::open(tf.asString().c_str(), O_CREAT|O_WRONLY, 0666);
545  ASSERT(fd != -1);
546  long sz;
547  try {
549  } catch(...) {
550  ::close(fd);
551  throw;
552  }
553  EXPECT(sz > 0);
554  EXPECT(sz == tf.size());
555  ::close(fd);
556 
557  // Check that we have encoded what we think we have encoded
558 
559  odc_reader_t* reader = nullptr;
560  CHECK_RETURN(odc_open_path(&reader, tf.asString().c_str()));
561  EXPECT(reader);
562  std::unique_ptr<odc_reader_t> reader_deleter(reader);
563 
564  odc_frame_t* frame = nullptr;
565  CHECK_RETURN(odc_new_frame(&frame, reader));
566  EXPECT(frame);
567  std::unique_ptr<odc_frame_t> frame_deleter(frame);
568 
570 
571  int column_count;
572  CHECK_RETURN(odc_frame_column_count(frame, &column_count));
573  EXPECT(column_count == 1);
574 
575  long row_count;
576  CHECK_RETURN(odc_frame_row_count(frame, &row_count));
577  EXPECT(row_count == nrows);
578 
579  // Test that the data is correctly encoded
580 
581  odc_decoder_t* decoder;
582  CHECK_RETURN(odc_new_decoder(&decoder));
583  EXPECT(decoder);
584  std::unique_ptr<odc_decoder_t> decoder_deleter(decoder);
585 
587 
588  long rows_decoded;
589  CHECK_RETURN(odc_decode(decoder, frame, &rows_decoded));
590  EXPECT(rows_decoded == nrows);
591 
592  const void* pdata;
593  CHECK_RETURN(odc_decoder_data_array(decoder, &pdata, 0, 0, 0));
594  EXPECT(::memcmp(icol, pdata, sizeof(icol)) == 0);
595 
596  EXPECT(odc_next_frame(frame) == ODC_ITERATION_COMPLETE);
597 }
598 
599 // ------------------------------------------------------------------------------------------------------
600 
602  char* data;
603  size_t pos;
604  size_t size;
605 };
606 
607 typedef long (*write_fn)(void* handle, const void* buffer, long length);
608 long custom_buffer_write(custom_buffer_t* handle, const void* buffer, long length) {
609  ASSERT(handle);
610  ASSERT(length + handle->pos <= handle->size);
611  ::memcpy(handle->data + handle->pos, buffer, length);
612  handle->pos += length;
613  return length;
614 }
615 
616 CASE("Encode to a custom output stream") {
617 
618  // Do some trivial encoding
619 
621 
622  const int nrows = 10;
623  long icol[nrows] = {1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999, 0};
624 
625  // Configure the encoder to encode said data
626 
627  odc_encoder_t* enc = nullptr;
629  std::unique_ptr<odc_encoder_t> enc_deleter(enc);
630 
633  CHECK_RETURN(odc_encoder_column_set_data_array(enc, 0, 0, 0, icol));
634 
635  // Do the encoding
636 
637  eckit::Buffer encoded(1024 * 1024);
638  custom_buffer_t handle = { (char*)encoded, 0, encoded.size() };
639 
640  long sz;
642  EXPECT(sz > 0);
643  EXPECT(size_t(sz) == handle.pos);
644 
645  // Check that we have encoded what we think we have encoded
646 
647  odc_reader_t* reader = nullptr;
648  CHECK_RETURN(odc_open_buffer(&reader, encoded.data(), sz));
649  EXPECT(reader);
650  std::unique_ptr<odc_reader_t> reader_deleter(reader);
651 
652  odc_frame_t* frame = nullptr;
653  CHECK_RETURN(odc_new_frame(&frame, reader));
654  EXPECT(frame);
655  std::unique_ptr<odc_frame_t> frame_deleter(frame);
656 
658 
659  int column_count;
660  CHECK_RETURN(odc_frame_column_count(frame, &column_count));
661  EXPECT(column_count == 1);
662 
663  long row_count;
664  CHECK_RETURN(odc_frame_row_count(frame, &row_count));
665  EXPECT(row_count == nrows);
666 
667  // Test that the data is correctly encoded
668 
669  odc_decoder_t* decoder;
670  CHECK_RETURN(odc_new_decoder(&decoder));
671  EXPECT(decoder);
672  std::unique_ptr<odc_decoder_t> decoder_deleter(decoder);
673 
675 
676  long rows_decoded;
677  CHECK_RETURN(odc_decode(decoder, frame, &rows_decoded));
678  EXPECT(rows_decoded == nrows);
679 
680  const void* pdata;
681  CHECK_RETURN(odc_decoder_data_array(decoder, &pdata, 0, 0, 0));
682  EXPECT(::memcmp(icol, pdata, sizeof(icol)) == 0);
683 
684  EXPECT(odc_next_frame(frame) == ODC_ITERATION_COMPLETE);
685 }
686 
687 // ------------------------------------------------------------------------------------------------------
688 
689 int main(int argc, char* argv[]) {
690  return run_tests(argc, argv);
691 }
int odc_encoder_add_column(odc_encoder_t *encoder, const char *name, int type)
Definition: api/odc.cc:778
int odc_free_encoder(const odc_encoder_t *encoder)
Definition: api/odc.cc:728
int odc_decoder_defaults_from_frame(odc_decoder_t *decoder, const odc_frame_t *frame)
Definition: api/odc.cc:453
int odc_frame_column_count(const odc_frame_t *frame, int *count)
Definition: api/odc.cc:396
int odc_encode_to_stream(odc_encoder_t *encoder, void *handle, odc_stream_write_t write_fn, long *bytes_encoded)
Definition: api/odc.cc:949
int odc_encoder_set_row_count(odc_encoder_t *encoder, long nrows)
Definition: api/odc.cc:741
int odc_free_frame(const odc_frame_t *frame)
Definition: api/odc.cc:352
int odc_next_frame(odc_frame_t *frame)
Definition: api/odc.cc:359
int odc_decode(odc_decoder_t *decoder, const odc_frame_t *frame, long *rows_decoded)
Definition: api/odc.cc:714
int odc_encoder_set_data_array(odc_encoder_t *encoder, const void *data, long width, long height, int columnMajorWidth)
Definition: api/odc.cc:755
int odc_encoder_column_add_bitfield(odc_encoder_t *encoder, int col, const char *name, int nbits)
Definition: api/odc.cc:807
int odc_open_buffer(odc_reader_t **reader, const void *data, long length)
Definition: api/odc.cc:302
int odc_frame_column_attributes(const odc_frame_t *frame, int col, const char **name, int *type, int *element_size, int *bitfield_count)
Definition: api/odc.cc:404
int odc_encode_to_file_descriptor(odc_encoder_t *encoder, int fd, long *bytes_encoded)
Definition: api/odc.cc:982
int odc_integer_behaviour(int integerBehaviour)
Definition: api/odc.cc:226
int odc_decoder_data_array(const odc_decoder_t *decoder, const void **data, long *width, long *height, bool *columnMajor)
Definition: api/odc.cc:508
int odc_new_encoder(odc_encoder_t **encoder)
Definition: api/odc.cc:722
int odc_open_path(odc_reader_t **reader, const char *filename)
Definition: api/odc.cc:285
int odc_new_decoder(odc_decoder_t **decoder)
Definition: api/odc.cc:441
int odc_decoder_column_data_array(const odc_decoder_t *decoder, int col, int *element_size, int *stride, const void **data)
Definition: api/odc.cc:566
int odc_encoder_column_set_data_array(odc_encoder_t *encoder, int col, int element_size, int stride, const void *data)
Definition: api/odc.cc:795
int odc_frame_bitfield_attributes(const odc_frame_t *frame, int col, int field, const char **name, int *offset, int *size)
Definition: api/odc.cc:423
int odc_frame_row_count(const odc_frame_t *frame, long *count)
Definition: api/odc.cc:388
int odc_new_frame(odc_frame_t **frame, odc_reader_t *reader)
Definition: api/odc.cc:345
int odc_close(const odc_reader_t *reader)
Definition: api/odc.cc:332
int odc_encoder_set_rows_per_frame(odc_encoder_t *encoder, long rows_per_frame)
Definition: api/odc.cc:748
int odc_encode_to_buffer(odc_encoder_t *encoder, void *buffer, long length, long *bytes_encoded)
Definition: api/odc.cc:992
int odc_free_decoder(const odc_decoder_t *decoder)
Definition: api/odc.cc:447
int main(int argc, char *argv[])
Definition: encode.cc:689
#define CHECK_RETURN(x)
Definition: encode.cc:28
long custom_buffer_write(custom_buffer_t *handle, const void *buffer, long length)
Definition: encode.cc:608
long(* write_fn)(void *handle, const void *buffer, long length)
Definition: encode.cc:607
CASE("Encode data in standard tabular form")
Definition: encode.cc:54
Definition: encode.cc:30
const int ODC_INTEGERS_AS_LONGS
@ ODC_ITERATION_COMPLETE
const int ODC_INTEGERS_AS_DOUBLES
@ ODC_INTEGER
@ ODC_REAL
@ ODC_BITFIELD
@ ODC_STRING
@ ODC_DOUBLE
char * data
Definition: encode.cc:602
size_t pos
Definition: encode.cc:603
size_t size
Definition: encode.cc:604