! . */
| 9869 | |
| 9870 | /*! . */ |
| 9871 | int GMT_Write_Data (void *V_API, unsigned int family, unsigned int method, unsigned int geometry, unsigned int mode, double wesn[], const char *outfile, void *data) { |
| 9872 | /* Function to write data directly from program memory as a set (not record-by-record). |
| 9873 | * We can combine the <register resource - export resource > sequence in |
| 9874 | * one combined function. See GMT_Register_IO for details on arguments. |
| 9875 | * Here, *data is the pointer to the data object to save (CPT, dataset, Grid) |
| 9876 | * Case 1: outfile != NULL: Register this as the destination and export data. |
| 9877 | * Case 2: outfile == NULL: Register stdout as the destination and export data. |
| 9878 | * Case 3: geometry == 0: Use a previously registered single destination. |
| 9879 | * While only one output destination is allowed, for DATASETS one can |
| 9880 | * have the tables and even segments be written to individual files (see the mode |
| 9881 | * description in the documentation for how to enable this feature.) |
| 9882 | * Return: false if all is well, true if there was an error (and set API->error). |
| 9883 | */ |
| 9884 | unsigned int n_reg; |
| 9885 | int out_ID; |
| 9886 | char *output = NULL; |
| 9887 | struct GMTAPI_CTRL *API = NULL; |
| 9888 | |
| 9889 | if (V_API == NULL) return_error (V_API, GMT_NOT_A_SESSION); |
| 9890 | if (data == NULL) return_error (V_API, GMT_PTR_IS_NULL); |
| 9891 | API = gmtapi_get_api_ptr (V_API); |
| 9892 | API->error = GMT_NOERROR; |
| 9893 | if (outfile) output = strdup (outfile); |
| 9894 | |
| 9895 | if (output) { /* Case 1: Save to a single specified destination (file or memory). Register it first. */ |
| 9896 | if ((out_ID = gmtapi_memory_registered (API, family, GMT_OUT, output)) != GMT_NOTSET) { |
| 9897 | /* Output is a memory resource, passed via a @GMTAPI@-###### file name, and ###### is the out_ID. |
| 9898 | In this case we must make some further checks. We need to find the API object that holds data. |
| 9899 | We do this below and get in_ID (the id of the data to write), while out_ID is the id of where |
| 9900 | things go (the output "memory"). Having the in_ID we get the array index in_item that matches |
| 9901 | this ID and of the correct family. We set direction to GMT_NOTSET since otherwise we may be |
| 9902 | denied a hit as we don't really know what the direction is for in_ID. Once in_item has been |
| 9903 | secured we transfer ownership of this data from the in_ID object to the out_ID object. That |
| 9904 | way we avoid accidental premature freeing of the data object via the in_ID object since it now |
| 9905 | will live on via out_ID and outlive the current module. |
| 9906 | */ |
| 9907 | int in_ID = GMT_NOTSET, in_item = GMT_NOTSET; |
| 9908 | in_ID = gmtapi_get_object (API, family, data); /* Get the object ID of the input source */ |
| 9909 | if (in_ID != GMT_NOTSET) in_item = gmtlib_validate_id (API, family, in_ID, GMT_NOTSET, GMT_NOTSET); /* Get the item in the API array; pass dir = GMT_NOTSET to bypass status check */ |
| 9910 | if (in_item != GMT_NOTSET) { |
| 9911 | int out_item = gmtlib_validate_id (API, GMT_NOTSET, out_ID, GMT_OUT, GMT_NOTSET); /* Get the item in the API array; pass family = GMT_NOTSET to bypass status check */ |
| 9912 | GMT_Report (API, GMT_MSG_DEBUG, "GMT_Write_Data: Writing %s to memory object %d from object %d which transfers ownership\n", GMT_family[family], out_ID, in_ID); |
| 9913 | if (API->object[out_item]->method == GMT_IS_REFERENCE) API->object[in_item]->no_longer_owner = true; /* Since we have passed the content onto an output object */ |
| 9914 | if (!API->object[out_item]->filename) API->object[out_item]->filename = strdup (output); |
| 9915 | } |
| 9916 | } /* else it is a regular file and we just register it and get the new out_ID needed below */ |
| 9917 | else if ((out_ID = GMT_Register_IO (API, family, method, geometry, GMT_OUT, wesn, output)) == GMT_NOTSET) { |
| 9918 | gmt_M_str_free (output); /* Done with this variable */ |
| 9919 | return_error (API, API->error); |
| 9920 | } |
| 9921 | } |
| 9922 | else if (output == NULL && geometry) { /* Case 2: Save to stdout. Register stdout first. */ |
| 9923 | if (family == GMT_IS_GRID) return_error (API, GMT_STREAM_NOT_ALLOWED); /* Cannot write grids to stream */ |
| 9924 | if ((out_ID = GMT_Register_IO (API, family, GMT_IS_STREAM, geometry, GMT_OUT, wesn, API->GMT->session.std[GMT_OUT])) == GMT_NOTSET) return_error (API, API->error); /* Failure to register std??? */ |
| 9925 | } |
| 9926 | else { /* Case 3: output == NULL && geometry == 0, so use the previously registered destination */ |
| 9927 | if ((n_reg = gmtlib_count_objects (API, family, geometry, GMT_OUT, &out_ID)) != 1) { |
| 9928 | gmt_M_str_free (output); /* Done with this variable */ |