Skip to content

Commit ec9009d

Browse files
committed
Some fixes and new b2nd_copy_buffer2 API func
1 parent 6d504a4 commit ec9009d

File tree

8 files changed

+138
-45
lines changed

8 files changed

+138
-45
lines changed

RELEASE_NOTES.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
Release notes for C-Blosc2
22
==========================
33

4-
Changes from 2.16.0 to 2.16.1
4+
Changes from 2.16.0 to 2.17.0
55
=============================
66

7-
#XXX version-specific blurb XXX#
7+
* New b2nd_copy_buffer2() function for copying buffers with typesizes
8+
larger than 255. The previous b2nd_copy_buffer() function is now
9+
deprecated and will be removed in a future release.
10+
11+
### Deprecated Functions
12+
13+
- `int b2nd_copy_buffer(...)` is deprecated and will be removed in
14+
a future release. Please use `b2nd_copy_buffer2(...)` instead.
815

916

1017
Changes from 2.15.2 to 2.16.0

blosc/b2nd.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ int get_set_slice(void *buffer, int64_t buffersize, const int64_t *start, const
775775
BLOSC_ERROR(BLOSC2_ERROR_INVALID_PARAM);
776776
}
777777

778-
uint8_t *buffer_b = (uint8_t *) buffer;
778+
uint8_t *buffer_b = buffer;
779779
const int64_t *buffer_start = start;
780780
const int64_t *buffer_stop = stop;
781781
const int64_t *buffer_shape = shape;
@@ -1069,13 +1069,13 @@ int get_set_slice(void *buffer, int64_t buffersize, const int64_t *start, const
10691069
}
10701070

10711071
if (set_slice) {
1072-
b2nd_copy_buffer(ndim, array->sc->typesize,
1073-
src, src_pad_shape, src_start, src_stop,
1074-
dst, dst_pad_shape, dst_start);
1072+
b2nd_copy_buffer2(ndim, array->sc->typesize,
1073+
src, src_pad_shape, src_start, src_stop,
1074+
dst, dst_pad_shape, dst_start);
10751075
} else {
1076-
b2nd_copy_buffer(ndim, array->sc->typesize,
1077-
dst, dst_pad_shape, dst_start, dst_stop,
1078-
src, src_pad_shape, src_start);
1076+
b2nd_copy_buffer2(ndim, array->sc->typesize,
1077+
dst, dst_pad_shape, dst_start, dst_stop,
1078+
src, src_pad_shape, src_start);
10791079
}
10801080
}
10811081

@@ -2103,13 +2103,15 @@ b2nd_create_ctx(const blosc2_storage *b2_storage, int8_t ndim, const int64_t *sh
21032103
}
21042104

21052105
if (dtype == NULL) {
2106-
ctx->dtype = strdup(B2ND_DEFAULT_DTYPE);
2107-
ctx->dtype_format = 0; // The default is NumPy format
2106+
// ctx->dtype = strdup(B2ND_DEFAULT_DTYPE);
2107+
char buf[16] = {0};
2108+
snprintf(buf, sizeof(buf), "|S%d", cparams->typesize);
2109+
ctx->dtype = strdup(buf);
21082110
}
21092111
else {
21102112
ctx->dtype = strdup(dtype);
2111-
ctx->dtype_format = dtype_format;
21122113
}
2114+
ctx->dtype_format = dtype_format;
21132115

21142116
params_b2_storage->cparams = cparams;
21152117
ctx->b2_storage = params_b2_storage;

blosc/b2nd_utils.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include "b2nd.h"
1212

1313
#include <stdint.h>
14-
#include <string.h>
1514

1615
// copyNdim where N = {2-8} - specializations of copy loops to be used by b2nd_copy_buffer
1716
// since we don't have c++ templates, substitute manual specializations for up to known B2ND_MAX_DIM (8)
@@ -253,12 +252,12 @@ void copy_ndim_fallback(const int8_t ndim,
253252
}
254253
}
255254

256-
int b2nd_copy_buffer(int8_t ndim,
257-
uint8_t itemsize,
258-
const void *src, const int64_t *src_pad_shape,
259-
const int64_t *src_start, const int64_t *src_stop,
260-
void *dst, const int64_t *dst_pad_shape,
261-
const int64_t *dst_start) {
255+
int b2nd_copy_buffer2(int8_t ndim,
256+
int32_t itemsize,
257+
const void *src, const int64_t *src_pad_shape,
258+
const int64_t *src_start, const int64_t *src_stop,
259+
void *dst, const int64_t *dst_pad_shape,
260+
const int64_t *dst_start) {
262261
// Compute the shape of the copy
263262
int64_t copy_shape[B2ND_MAX_DIM] = {0};
264263
for (int i = 0; i < ndim; ++i) {
@@ -325,3 +324,23 @@ int b2nd_copy_buffer(int8_t ndim,
325324

326325
return BLOSC2_ERROR_SUCCESS;
327326
}
327+
328+
329+
// Keep the old signature for API compatibility
330+
int b2nd_copy_buffer(int8_t ndim,
331+
uint8_t itemsize,
332+
const void *src, const int64_t *src_pad_shape,
333+
const int64_t *src_start, const int64_t *src_stop,
334+
void *dst, const int64_t *dst_pad_shape,
335+
const int64_t *dst_start) __attribute__((deprecated("Use b2nd_copy_buffer2 instead")));
336+
337+
int b2nd_copy_buffer(int8_t ndim,
338+
uint8_t itemsize,
339+
const void *src, const int64_t *src_pad_shape,
340+
const int64_t *src_start, const int64_t *src_stop,
341+
void *dst, const int64_t *dst_pad_shape,
342+
const int64_t *dst_start) {
343+
// Simply cast itemsize to int32_t and delegate
344+
return b2nd_copy_buffer2(ndim, (int32_t)itemsize, src, src_pad_shape,
345+
src_start, src_stop, dst, dst_pad_shape, dst_start);
346+
}

blosc/blosc2.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -725,14 +725,18 @@ int read_chunk_header(const uint8_t* src, int32_t srcsize, bool extended_header,
725725

726726
int32_t special_type = (header->blosc2_flags >> 4) & BLOSC2_SPECIAL_MASK;
727727
if (special_type != 0) {
728-
if (header->nbytes % header->typesize != 0) {
729-
BLOSC_TRACE_ERROR("`nbytes` is not a multiple of typesize");
730-
return BLOSC2_ERROR_INVALID_HEADER;
731-
}
732728
if (special_type == BLOSC2_SPECIAL_VALUE) {
733-
if (header->cbytes < BLOSC_EXTENDED_HEADER_LENGTH + header->typesize) {
734-
BLOSC_TRACE_ERROR("`cbytes` is too small for run length encoding");
735-
return BLOSC2_ERROR_READ_BUFFER;
729+
// In this case, the actual type size must be derived from the cbytes
730+
int32_t typesize = header->cbytes - BLOSC_EXTENDED_HEADER_LENGTH;
731+
if (header->nbytes % typesize != 0) {
732+
BLOSC_TRACE_ERROR("`nbytes` is not a multiple of typesize");
733+
return BLOSC2_ERROR_INVALID_HEADER;
734+
}
735+
}
736+
else {
737+
if (header->nbytes % header->typesize != 0) {
738+
BLOSC_TRACE_ERROR("`nbytes` is not a multiple of typesize");
739+
return BLOSC2_ERROR_INVALID_HEADER;
736740
}
737741
}
738742
}
@@ -1581,6 +1585,10 @@ static int blosc_d(
15811585
if (rc < 0) {
15821586
return rc;
15831587
}
1588+
if (context->special_type == BLOSC2_SPECIAL_VALUE) {
1589+
// We need the actual typesize in this case, but it cannot be encoded in the header, so derive it from cbytes
1590+
typesize = chunk_cbytes - context->header_overhead;
1591+
}
15841592

15851593
// In some situations (lazychunks) the context can arrive uninitialized
15861594
// (but BITSHUFFLE needs it for accessing the format of the chunk)
@@ -1674,7 +1682,7 @@ static int blosc_d(
16741682
switch (context->special_type) {
16751683
case BLOSC2_SPECIAL_VALUE:
16761684
// All repeated values
1677-
rc = set_values(context->typesize, context->src, _dest, bsize_);
1685+
rc = set_values(typesize, context->src, _dest, bsize_);
16781686
if (rc < 0) {
16791687
BLOSC_TRACE_ERROR("set_values failed");
16801688
return BLOSC2_ERROR_DATA;
@@ -1749,7 +1757,7 @@ static int blosc_d(
17491757

17501758
/* The number of compressed data streams for this block */
17511759
if (!dont_split && !leftoverblock) {
1752-
nstreams = (int32_t)typesize;
1760+
nstreams = context->typesize;
17531761
}
17541762
else {
17551763
nstreams = 1;

doc/reference/b2nd.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,4 @@ Utilities
109109
These functions may be used for working with plain C buffers representing multidimensional arrays.
110110

111111
.. doxygenfunction:: b2nd_copy_buffer
112+
.. doxygenfunction:: b2nd_copy_buffer2

include/b2nd.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,9 @@ BLOSC_EXPORT int b2nd_deserialize_meta(const uint8_t *smeta, int32_t smeta_len,
562562
*
563563
* @return An error code.
564564
*
565+
* @note This is kept for backward compatibility with existing code out there. New code should use
566+
* b2nd_copy_buffer2 instead.
567+
*
565568
* @note Please make sure that slice boundaries fit within the source and
566569
* destination arrays before using this function, as it does not perform these
567570
* checks itself.
@@ -574,6 +577,40 @@ BLOSC_EXPORT int b2nd_copy_buffer(int8_t ndim,
574577
const int64_t *dst_start);
575578

576579

580+
/**
581+
* @brief Copy a slice of a source array into another array. The arrays have
582+
* the same number of dimensions (though their shapes may differ), the same
583+
* item size, and they are stored as C buffers with contiguous data (any
584+
* padding is considered part of the array).
585+
*
586+
* @param ndim The number of dimensions in both arrays.
587+
* @param itemsize The size of the individual data item in both arrays.
588+
* @param src The buffer for getting the data from the source array.
589+
* @param src_pad_shape The shape of the source array, including padding.
590+
* @param src_start The source coordinates where the slice will begin.
591+
* @param src_stop The source coordinates where the slice will end.
592+
* @param dst The buffer for setting the data into the destination array.
593+
* @param dst_pad_shape The shape of the destination array, including padding.
594+
* @param dst_start The destination coordinates where the slice will be placed.
595+
*
596+
* @return An error code.
597+
*
598+
* @note This is a version of b2nd_copy_buffer that uses signed 32-bit integers for
599+
* copying data. This is useful when the data is stored in a buffer that uses
600+
* itemsizes that are larger than 255 bytes.
601+
*
602+
* @note Please make sure that slice boundaries fit within the source and
603+
* destination arrays before using this function, as it does not perform these
604+
* checks itself.
605+
*/
606+
BLOSC_EXPORT int b2nd_copy_buffer2(int8_t ndim,
607+
int32_t itemsize,
608+
const void *src, const int64_t *src_pad_shape,
609+
const int64_t *src_start, const int64_t *src_stop,
610+
void *dst, const int64_t *dst_pad_shape,
611+
const int64_t *dst_start);
612+
613+
577614
#ifdef __cplusplus
578615
}
579616
#endif

tests/b2nd/test_b2nd_copy_buffer.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ CUTEST_TEST_TEST(copy_buffer) {
6464
CUTEST_ASSERT("Elements are not equal!", a == b);
6565
}
6666

67+
int32_t itemsize2 = itemsize;
68+
B2ND_TEST_ASSERT(b2nd_copy_buffer2(ndim, itemsize2,
69+
chunk0x, chunk_shape, chunk0s_start, chunk0s_stop,
70+
dest, dest_shape, chunk0s_dest));
71+
B2ND_TEST_ASSERT(b2nd_copy_buffer2(ndim, itemsize2,
72+
chunk1x, chunk_shape, chunk1s_start, chunk1s_stop,
73+
dest, dest_shape, chunk1s_dest));
74+
75+
for (int i = 0; i < result_length; ++i) {
76+
uint8_t a = dest[i];
77+
uint8_t b = result[i];
78+
CUTEST_ASSERT("Elements are not equal!", a == b);
79+
}
80+
6781
return 0;
6882
}
6983

tests/b2nd/test_b2nd_full.c

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,23 @@ CUTEST_TEST_SETUP(full) {
1818
// Add parametrizations
1919
CUTEST_PARAMETRIZE(typesize, int32_t, CUTEST_DATA(
2020
//1, 2, 4, 8,
21-
256, // 256, 257, 256 * 256,
22-
// 256*256*256, 256*256*256*8 # these should work for small shapes as well, but are too slow
21+
256, //257, 256 * 256,
22+
// 256*256*256, 256*256*256*8, // these should work for small shapes as well, but are too slow
2323
));
2424
CUTEST_PARAMETRIZE(shapes, _test_shapes, CUTEST_DATA(
25-
{1, {3}, {3}, {3}}, // 1-idim
26-
// {0, {0}, {0}, {0}}, // 0-dim
27-
//{1, {5}, {3}, {2}}, // 1-idim
28-
// {2, {20, 0}, {7, 0}, {3, 0}}, // 0-shape
29-
// {2, {20, 10}, {7, 5}, {3, 5}}, // 0-shape
30-
// {2, {14, 10}, {8, 5}, {2, 2}}, // general,
31-
// {3, {12, 10, 14}, {3, 5, 9}, {3, 4, 4}}, // general
32-
// {3, {10, 21, 20, 5}, {8, 7, 15, 3}, {5, 5, 10, 1}}, // general,
25+
// {0, {0}, {0}, {0}}, // 0-dim
26+
// {1, {5}, {3}, {2}}, // 1-idim
27+
// {2, {20, 0}, {7, 0}, {3, 0}}, // 0-shape
28+
//{2, {20, 10}, {20, 10}, {10, 10}}, // funciona sempre
29+
//{2, {20, 10}, {10, 5}, {10, 5}}, // falla
30+
//{2, {4, 1}, {2, 1}, {2, 1}}, // falla
31+
{2, {1, 3}, {1, 2}, {1, 2}}, // falla
32+
//{1, {4}, {2}, {2}}, // funciona sempre
33+
//{2, {20, 10}, {8, 6}, {7, 5}}, // falla
34+
//{2, {20, 10}, {7, 5}, {3, 5}}, // falla
35+
//{2, {14, 10}, {8, 5}, {2, 2}}, // general,
36+
//{3, {12, 10, 14}, {3, 5, 9}, {3, 4, 4}}, // general
37+
//{3, {10, 21, 20, 5}, {8, 7, 15, 3}, {5, 5, 10, 1}}, // general,
3338
));
3439
CUTEST_PARAMETRIZE(backend, _test_backend, CUTEST_DATA(
3540
{false, false},
@@ -47,14 +52,14 @@ CUTEST_TEST_SETUP(full) {
4752
CUTEST_TEST_TEST(full) {
4853
CUTEST_GET_PARAMETER(backend, _test_backend);
4954
CUTEST_GET_PARAMETER(shapes, _test_shapes);
50-
CUTEST_GET_PARAMETER(typesize, uint32_t);
55+
CUTEST_GET_PARAMETER(typesize, int32_t);
5156
CUTEST_GET_PARAMETER(fill_value, int8_t);
5257

5358
char *urlpath = "test_full.b2frame";
5459
blosc2_remove_urlpath(urlpath);
5560

5661
blosc2_cparams cparams = BLOSC2_CPARAMS_DEFAULTS;
57-
cparams.nthreads = 2;
62+
cparams.nthreads = 1;
5863
cparams.typesize = typesize;
5964
blosc2_storage b2_storage = {.cparams=&cparams};
6065

@@ -121,16 +126,16 @@ CUTEST_TEST_TEST(full) {
121126
break;
122127
default:
123128
// Fill a buffer with fill_value and compare with buffer_dest
124-
for (int j = 0; j < typesize; ++j) {
129+
for (uint32_t j = 0; j < typesize; ++j) {
125130
buffer_fill[j] = fill_value;
126131
}
127132
// Compare buffer_fill with buffer_dest
128133
is_true = memcmp(buffer_fill, buffer_dest, typesize) == 0;
129134
// print the 10 first bytes of buffer_fill and buffer_dest
130-
printf("buffer_fill: ");
131-
for (int j = 0; j < 10; ++j) {
132-
printf("%d vs %d ", buffer_fill[j], buffer_dest[j]);
133-
}
135+
// printf("buffer_fill: ");
136+
// for (int j = 0; j < 10; ++j) {
137+
// printf("%d vs %d ", buffer_fill[j], buffer_dest[j]);
138+
// }
134139
free(buffer_fill);
135140
break;
136141
}

0 commit comments

Comments
 (0)