void print_f64(cbuf_t* in, int n) { int i; for (i = 0; i < n; i++) { double val; get_float64(in, &val); printf("%f ", val); } printf("\n"); }
/* given a return value in OCaml land, translate it to the return_val_t C structure */ return_val_t translate_return_value(value ocaml_result) { CAMLparam1(ocaml_result); CAMLlocal5(ocaml_shape, ocaml_strides, ocaml_data, ocaml_cur, ocaml_type); CAMLlocal1(v); return_val_t ret; if (Is_long(ocaml_result)) { // In this case, we know that the return code must have been Pass, // since the other two return codes have data. ret.return_code = RET_PASS; ret.results_len = 0; } else if (Tag_val(ocaml_result) == RET_FAIL) { ret.return_code = RET_FAIL; ret.results_len = caml_string_length(Field(ocaml_result, 0)); ret.error_msg = malloc(ret.results_len + 1); strcpy(ret.error_msg, String_val(Field(ocaml_result, 0))); } else if (Tag_val(ocaml_result) == RET_SUCCESS) { ocaml_cur = Field(ocaml_result, 0); ret.return_code = RET_SUCCESS; ret.results_len = ocaml_list_length(ocaml_cur); ret.results = (ret_t*)malloc(sizeof(ret_t) * ret.results_len); int i, j; host_val h; for (i = 0; i < ret.results_len; ++i) { v = Field(ocaml_cur, 0); h = create_host_val(v); ocaml_cur = Field(ocaml_cur, 1); // returning a scalar if (value_is_scalar(h)) { ret.results[i].is_scalar = 1; ocaml_type = (scalar_type)value_type_of(h); ret.results[i].data.scalar.ret_type = get_scalar_element_type(ocaml_type); // WARNING: // Tiny Memory Leak Ahead // ----------------------- // When scalar data is returned to the host language // on the heap, it should be manually deleted by the // host frontend if (type_is_bool(ocaml_type)) { ret.results[i].data.scalar.ret_scalar_value.boolean = get_bool(h); } else if (type_is_int32(ocaml_type)) { ret.results[i].data.scalar.ret_scalar_value.int32 = get_int32(h); } else if (type_is_int64(ocaml_type)) { ret.results[i].data.scalar.ret_scalar_value.int64 = get_int64(h); } else if (type_is_float32(ocaml_type)) { ret.results[i].data.scalar.ret_scalar_value.float32 = get_float64(h); } else if (type_is_float64(ocaml_type)) { ret.results[i].data.scalar.ret_scalar_value.float64 = get_float64(h); } else { caml_failwith("Unable to return scalar of this type\n"); } } else { // Pass the type ret.results[i].is_scalar = 0; ret.results[i].data.array.ret_type = array_type_of(h); // Pass the data ret.results[i].data.array.data = get_array_data(h); // Build the shape array ocaml_shape = value_get_shape(h); int shape_len = Wosize_val(ocaml_shape); ret.results[i].data.array.shape = (int*)malloc(shape_len * sizeof(int)); ret.results[i].data.array.shape_len = shape_len; for (j = 0; j < shape_len; ++j) { ret.results[i].data.array.shape[j] = Int_val(Field(ocaml_shape, j)); } // Build the strides array ocaml_strides = value_get_strides(h); int strides_len = Wosize_val(ocaml_strides); ret.results[i].data.array.strides_len = strides_len; ret.results[i].data.array.strides = (int*)malloc(strides_len * sizeof(int)); for (j = 0; j < strides_len; ++j) { ret.results[i].data.array.strides[j] = Int_val(Field(ocaml_strides, j)); } } } } CAMLreturnT(return_val_t, ret); }
static int decode_data(double **data, const xmlChar * input, dataFormat data_format, codingTypes coding, byteOrder byte_order, int max_input_len) { GArray *data_stream, *debase64_buf, *decoded_data; char *p, *end_ptr; unsigned int i; double val; int data_count = 0; gwy_debug("start."); if (input == NULL) { g_warning("SPML: decode_data(): NULL input"); *data = NULL; return 0; } switch (coding) { case ZLIB_COMPR_BASE64: /*/ XXX: strlen() may not be nice there */ if (decode_b64((char *)input, &debase64_buf, strlen(input)) != 0) { if (debase64_buf != NULL) { g_array_free(debase64_buf, TRUE); } g_warning("Cannot decode data in BASE64 code."); *data = NULL; return 0; } if (inflate_dynamic_array(debase64_buf, &data_stream) != 0) { g_warning("Cannot inflate compressed data."); g_array_free(debase64_buf, TRUE); if (data_stream != NULL) { g_array_free(data_stream, TRUE); } *data = NULL; return 0; } g_array_free(debase64_buf, TRUE); break; case BASE64: /*/ XXX: strlen() may not be nice there */ if (decode_b64((char *)input, &data_stream, strlen(input)) != 0) { g_warning("Cannot decode data in BASE64 code."); if (data_stream != NULL) { g_array_free(data_stream, TRUE); } *data = NULL; return 0; } break; case ASCII: p = (char *)input; data_stream = g_array_new(FALSE, FALSE, sizeof(double)); while (p != NULL) { double num; if (*p == ' ' || *p == '\n' || *p == '\r' || *p == '\t') { p++; continue; } num = g_ascii_strtod(p, &end_ptr); if (num == 0 && end_ptr == p) { g_warning("SPML: decode_data(): No conversion performed " "from ASCII string."); break; } g_array_append_val(data_stream, num); p = end_ptr; data_count++; } break; /*/ TODO: */ case HEX: case BINARY: g_warning("SPML: decode_data(): Data coding 'HEX' and 'BINARY' " "not supported."); break; case UNKNOWN_CODING: break; } if (coding == ASCII) { /* we have already decoded data */ if (max_input_len != -1 && data_count != max_input_len) { /* not enough input data to fill array defined by length * max_input_len */ g_warning("SPML: decode_data():\n" "Input has not the same length as declared in " "dimensions\n" "(max:%d vs read:%d). Has the channel attribute\n" "'channelReadMethodName'? The channel may be one\n" "dimensional data used for axis values but not as\n" "a source of data for Gwyddion.", max_input_len, data_count); g_array_free(data_stream, TRUE); *data = NULL; return 0; } else { *data = (double *)data_stream->data; /* we can free dynamic array, but not */ g_array_free(data_stream, FALSE); /* containing data. */ gwy_debug("Datacount: %d", data_count); return data_count; } } decoded_data = g_array_new(FALSE, FALSE, sizeof(double)); p = data_stream->data; i = 0; switch (data_format) { case FLOAT32: while (i < data_stream->len) { val = get_float32(&p, byte_order); g_array_append_val(decoded_data, val); data_count++; i += sizeof(float); } break; case FLOAT64: while (i < data_stream->len) { val = get_float64(&p, byte_order); g_array_append_val(decoded_data, val); i += sizeof(double); } break; case INT8: while (i < data_stream->len) { val = get_int8(&p); g_array_append_val(decoded_data, val); i += sizeof(gint8); } break; case INT16: while (i < data_stream->len) { val = get_int16(&p, byte_order); g_array_append_val(decoded_data, val); i += sizeof(gint16); } break; case INT32: while (i < data_stream->len) { val = get_int32(&p, byte_order); g_array_append_val(decoded_data, val); i += sizeof(gint32); } break; case UINT32: while (i < data_stream->len) { val = get_uint32(&p, byte_order); g_array_append_val(decoded_data, val); i += sizeof(guint32); } break; case UINT8: while (i < data_stream->len) { val = get_uint8(&p); g_array_append_val(decoded_data, val); i += sizeof(guint8); } break; case UINT16: while (i < data_stream->len) { val = get_uint16(&p, byte_order); g_array_append_val(decoded_data, val); i += sizeof(guint16); } break; case STRING: g_warning ("SPML: decode_data(): Data format 'String' not supported."); break; case UNKNOWN_DATAFORMAT: g_warning("SPML: decode_data(): Unknown dataformat."); break; } g_array_free(data_stream, TRUE); data_count = decoded_data->len; if (max_input_len != -1 && data_count != max_input_len) { g_warning("SPML: decode_data():\n" "Input has not the same length as declared in dimensions\n" "(max:%d vs read:%d). Has the channel attribute\n" "'channelReadMethodName'? The channel may be one\n" "dimensional data used for axis values but not as\n" "a source of data for Gwyddion.", max_input_len, data_count); g_array_free(decoded_data, TRUE); *data = NULL; return 0; } *data = (double *)decoded_data->data; g_array_free(decoded_data, FALSE); /* we can free dynamic array, but not */ /* containing data. */ gwy_debug("Datacount: %d", data_count); return data_count; }