@@ -1330,6 +1330,101 @@ int b2nd_copy(b2nd_context_t *ctx, const b2nd_array_t *src, b2nd_array_t **array
13301330}
13311331
13321332
1333+ int b2nd_concatenate (b2nd_context_t * ctx , b2nd_array_t * * array , const b2nd_array_t * src1 ,
1334+ const b2nd_array_t * src2 , int axis ) {
1335+ BLOSC_ERROR_NULL (src1 , BLOSC2_ERROR_NULL_POINTER );
1336+ BLOSC_ERROR_NULL (src2 , BLOSC2_ERROR_NULL_POINTER );
1337+ BLOSC_ERROR_NULL (array , BLOSC2_ERROR_NULL_POINTER );
1338+
1339+ ctx -> ndim = src1 -> ndim ;
1340+ // Compute the new shape while checking that the shapes are compatible with the other axes
1341+ for (int i = 0 ; i < src1 -> ndim ; ++ i ) {
1342+ if (i == axis ) {
1343+ ctx -> shape [i ] = src1 -> shape [i ] + src2 -> shape [i ];
1344+ } else {
1345+ if (src1 -> shape [i ] != src2 -> shape [i ]) {
1346+ BLOSC_TRACE_ERROR ("The shapes of the arrays are not compatible in axis %d" , i );
1347+ BLOSC_ERROR (BLOSC2_ERROR_INVALID_PARAM );
1348+ }
1349+ ctx -> shape [i ] = src1 -> shape [i ];
1350+ }
1351+ }
1352+
1353+ // Use the same chunkshape and blockshape as src1
1354+ for (int i = 0 ; i < src1 -> ndim ; ++ i ) {
1355+ ctx -> chunkshape [i ] = src1 -> chunkshape [i ];
1356+ ctx -> blockshape [i ] = src1 -> blockshape [i ];
1357+ }
1358+
1359+ // Create a container for the new array
1360+ BLOSC_ERROR (b2nd_empty (ctx , array ));
1361+
1362+ // Copy the data from the first array
1363+ int64_t start [B2ND_MAX_DIM ] = {0 };
1364+ int64_t stop [B2ND_MAX_DIM ];
1365+ for (int i = 0 ; i < src1 -> ndim ; ++ i ) {
1366+ stop [i ] = src1 -> shape [i ];
1367+ }
1368+ // Copy src1 data chunk by chunk
1369+ void * buffer = malloc (src1 -> sc -> typesize * src1 -> extchunknitems );
1370+ BLOSC_ERROR_NULL (buffer , BLOSC2_ERROR_MEMORY_ALLOC );
1371+ for (int64_t nchunk = 0 ; nchunk < src1 -> sc -> nchunks ; ++ nchunk ) {
1372+ BLOSC_ERROR (blosc2_schunk_decompress_chunk (src1 -> sc , nchunk , buffer ,
1373+ src1 -> sc -> typesize * src1 -> extchunknitems ));
1374+ BLOSC_ERROR (b2nd_set_slice_cbuffer (buffer , src1 -> chunkshape , src1 -> sc -> typesize * src1 -> extchunknitems ,
1375+ start , stop , * array ));
1376+ }
1377+ free (buffer );
1378+
1379+ // Copy the data from the second array
1380+ for (int i = 0 ; i < src2 -> ndim ; ++ i ) {
1381+ if (i == axis ) {
1382+ start [i ] = src1 -> shape [i ];
1383+ stop [i ] = start [i ] + src2 -> shape [i ];
1384+ } else {
1385+ start [i ] = 0 ;
1386+ stop [i ] = src2 -> shape [i ];
1387+ }
1388+ }
1389+ // Copy src2 data chunk by chunk
1390+ buffer = malloc (src2 -> sc -> typesize * src2 -> extchunknitems );
1391+ BLOSC_ERROR_NULL (buffer , BLOSC2_ERROR_MEMORY_ALLOC );
1392+ for (int64_t nchunk = 0 ; nchunk < src2 -> sc -> nchunks ; ++ nchunk ) {
1393+ BLOSC_ERROR (blosc2_schunk_decompress_chunk (src2 -> sc , nchunk , buffer ,
1394+ src2 -> sc -> typesize * src2 -> extchunknitems ));
1395+ BLOSC_ERROR (b2nd_set_slice_cbuffer (buffer , src2 -> chunkshape , src2 -> sc -> typesize * src2 -> extchunknitems ,
1396+ start , stop , * array ));
1397+ }
1398+ free (buffer );
1399+
1400+ // Copy the metalayers from src1
1401+ blosc2_storage * b2_storage = ctx -> b2_storage ;
1402+ blosc2_schunk * schunk = src1 -> sc ;
1403+ blosc2_schunk * new_schunk = (* array )-> sc ;
1404+ for (int nmeta = 0 ; nmeta < schunk -> nmetalayers ; ++ nmeta ) {
1405+ blosc2_metalayer * meta = schunk -> metalayers [nmeta ];
1406+ if (blosc2_meta_add (new_schunk , meta -> name , meta -> content , meta -> content_len ) < 0 ) {
1407+ BLOSC_TRACE_ERROR ("Can not add %s `metalayer`." , meta -> name );
1408+ return BLOSC2_ERROR_FAILURE ;
1409+ }
1410+ }
1411+
1412+ // Copy the vlmetalayers from src1
1413+ for (int nvlmeta = 0 ; nvlmeta < schunk -> nvlmetalayers ; ++ nvlmeta ) {
1414+ uint8_t * content ;
1415+ int32_t content_len ;
1416+ if (blosc2_vlmeta_get (schunk , schunk -> vlmetalayers [nvlmeta ]-> name , & content ,
1417+ & content_len ) < 0 ) {
1418+ BLOSC_ERROR (BLOSC2_ERROR_FAILURE );
1419+ }
1420+ BLOSC_ERROR (blosc2_vlmeta_add (new_schunk , schunk -> vlmetalayers [nvlmeta ]-> name , content ,
1421+ content_len , b2_storage -> cparams ));
1422+ free (content );
1423+ }
1424+
1425+ return BLOSC2_ERROR_SUCCESS ;
1426+ }
1427+
13331428int b2nd_save (const b2nd_array_t * array , char * urlpath ) {
13341429 BLOSC_ERROR_NULL (array , BLOSC2_ERROR_NULL_POINTER );
13351430 BLOSC_ERROR_NULL (urlpath , BLOSC2_ERROR_NULL_POINTER );
0 commit comments