int ft_swap_chunks_from_native(UINT32_T size, UINT32_T nchans, void *buf) { UINT32_T offset = 0; while (offset + sizeof(ft_chunkdef_t) <= size) { ft_chunk_t *chunk = (ft_chunk_t *) ((char *) buf + offset); offset += sizeof(ft_chunkdef_t) + chunk->def.size; /* chunk definition fault (=too big) ? */ if (offset > size) return -1; switch(chunk->def.type) { case FT_CHUNK_RESOLUTIONS: if (chunk->def.size >= nchans*sizeof(FLOAT64_T)) { ft_swap64(nchans, chunk->data); } break; /* Add other cases here as needed */ } ft_swap32(2, &(chunk->def)); } return 0; }
void ft_swap_data(UINT32_T numel, UINT32_T datatype, void *data) { switch(datatype) { case DATATYPE_CHAR: case DATATYPE_UINT8: case DATATYPE_INT8: return; case DATATYPE_UINT16: case DATATYPE_INT16: ft_swap16(numel, data); return; case DATATYPE_UINT32: case DATATYPE_INT32: case DATATYPE_FLOAT32: ft_swap32(numel, data); return; case DATATYPE_UINT64: case DATATYPE_INT64: case DATATYPE_FLOAT64: ft_swap64(numel, data); return; } }
/** Prepares "start" RDA packet with channel names determined from the corresponding chunk (or empty) Also converts to little-endian if this machine is big endian @param hdr Points to headerdef_t structure, will be filled, may not be NULL @return created start item, or NULL on error (connection / out of memory) */ rda_buffer_item_t *rda_aux_get_hdr_prep_start(int ft_buffer, headerdef_t *hdr) { rda_buffer_item_t *item = NULL; const ft_chunk_t *chunk; rda_msg_start_t *R; char *str; double *dRes; const void *dResSource; size_t bytesTotal; int i,r,numExtraZeros,sizeOrgNames; message_t req, *resp = NULL; messagedef_t msg_def; req.def = &msg_def; req.buf = NULL; msg_def.version = VERSION; msg_def.command = GET_HDR; msg_def.bufsize = 0; r = clientrequest(ft_buffer, &req, &resp); if (r<0 || resp == NULL || resp->def == NULL) { goto cleanup; } if (resp->def->command != GET_OK || resp->def->bufsize < sizeof(headerdef_t) || resp->buf == NULL) { goto cleanup; } memcpy(hdr, resp->buf, sizeof(headerdef_t)); /* Ok, we have the basic header, now look for proper FT_CHUNK_RESOLUTIONS */ chunk = find_chunk(resp->buf, sizeof(headerdef_t), resp->def->bufsize, FT_CHUNK_RESOLUTIONS); if (chunk != NULL && chunk->def.size == hdr->nchans*sizeof(double)) { dResSource = chunk->data; /* fine - we just need a memcpy later on */ } else { dResSource = NULL; /* no suitable chunk found - set defaults later on */ } /* Now see if we can find channel names */ chunk = find_chunk(resp->buf, sizeof(headerdef_t), resp->def->bufsize, FT_CHUNK_CHANNEL_NAMES); if (chunk != NULL && chunk->def.size >= hdr->nchans) { /* The chunk seems ok - check whether we really have N (0-terminated) strings */ int k,nz = 0; for (k = 0; k<chunk->def.size && nz<=hdr->nchans; k++) { if (chunk->data[k] == 0) nz++; } /* Okay, either k is at the end and we have nz<=N, or we have reached N=nz before the end of the chunk. In both cases, it's safe to transmit the first 'k' bytes and add (N-nz) trailing zeros */ numExtraZeros = hdr->nchans - nz; sizeOrgNames = k; } else { sizeOrgNames = 0; numExtraZeros = hdr->nchans; } bytesTotal = sizeof(rda_msg_start_t) + hdr->nchans*(sizeof(double)) + sizeOrgNames + numExtraZeros; item = rda_aux_alloc_item(bytesTotal); if (item == NULL) goto cleanup; R = (rda_msg_start_t *) item->data; memcpy(R->hdr.guid, _rda_guid, sizeof(_rda_guid)); R->hdr.nSize = bytesTotal; R->hdr.nType = RDA_START_MSG; R->nChannels = hdr->nchans; R->dSamplingInterval = 1.0e6/(double) hdr->fsample; /* should be in microseconds */ if (_i_am_big_endian_) { /* take care of hdr.nSize, hdr.nType, nChannels */ ft_swap32(3, &(R->hdr.nSize)); ft_swap64(1, &(R->dSamplingInterval)); } /* R+1 points to first byte after header info */ dRes = (double *) ((void *)(R+1)); if (dResSource == NULL) { /* Fill with resolution = 1.0 -- we have nothing better */ for (i=0;i<hdr->nchans;i++) dRes[i]=1.0; } else { memcpy(dRes, dResSource, hdr->nchans * sizeof(double)); } /* swap byte order if necessary */ if (_i_am_big_endian_) { ft_swap64(hdr->nchans, dRes); } /* Let 'str' point to first byte after the resolution values */ str = (char *) ((void *)(dRes + hdr->nchans)); if (sizeOrgNames > 0) { memcpy(str, chunk->data, sizeOrgNames); } for (i=0;i<numExtraZeros;i++) str[sizeOrgNames + i] = 0; /* done */ cleanup: if (resp) { if (resp->def) free(resp->def); if (resp->buf) free(resp->buf); free(resp); } return item; }