Skip to content
16 changes: 13 additions & 3 deletions src/gmt_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -3632,9 +3632,10 @@ GMT_LOCAL struct GMT_DATASET * gmtapi_import_dataset (struct GMTAPI_CTRL *API, i
struct GMT_DATASEGMENT *S = NULL;
struct GMT_MATRIX *M_obj = NULL;
struct GMT_VECTOR *V_obj = NULL;
struct GMT_DATASET_HIDDEN *DH = NULL;
struct GMT_DATASET_HIDDEN *DH = NULL, *DHi = NULL;
struct GMT_DATATABLE_HIDDEN *TH = NULL;
struct GMT_DATASEGMENT_HIDDEN *SH = NULL;
struct GMT_MATRIX_HIDDEN *MH = NULL;
struct GMTAPI_DATA_OBJECT *S_obj = NULL;
struct GMT_CTRL *GMT = API->GMT;

Expand Down Expand Up @@ -3757,19 +3758,25 @@ GMT_LOCAL struct GMT_DATASET * gmtapi_import_dataset (struct GMTAPI_CTRL *API, i
if (GMT->common.q.mode == GMT_RANGE_ROW_IN || GMT->common.q.mode == GMT_RANGE_DATA_IN)
GMT_Report (API, GMT_MSG_WARNING, "Row-selection via -qi is not implemented for GMT_IS_REFERENCE with GMT_IS_DATASET external memory objects\n");
GMT_Report (API, GMT_MSG_INFORMATION, "Referencing data table from GMT_DATASET memory location\n");
DHi = gmt_get_DD_hidden (Din_obj);
if ((tbl + Din_obj->n_tables) >= n_alloc) { /* Need more space to hold these new tables */
n_alloc += Din_obj->n_tables;
D_obj->table = gmt_M_memory (GMT, D_obj->table, n_alloc, struct GMT_DATATABLE *);
}
for (tbl_in = 0; tbl_in < Din_obj->n_tables; tbl_in++, tbl++) /* Pass over the pointers only */
for (tbl_in = 0; tbl_in < Din_obj->n_tables; tbl_in++, tbl++) { /* Pass over the pointers only */
D_obj->table[tbl] = Din_obj->table[tbl_in];
Din_obj->table[tbl_in] = NULL; /* Since passed to D_obj */
}
Din_obj->n_tables = 0; /* Only the husk remains of this fruit */
D_obj->n_tables = tbl;
D_obj->geometry = S_obj->geometry; /* Since provided when registered */
DH->alloc_mode = DHi->alloc_mode; /* Must use whatever alloc_mode the input reference had */
DH->alloc_level = DHi->alloc_level; /* Must use whatever alloc_level the input reference had */
check_col_switch = true;
update = regit = via = true; /* Have reason to update min/max as well as registering D_obj when done */
break;

case GMT_IS_DUPLICATE|GMT_VIA_MATRIX:
case GMT_IS_DUPLICATE|GMT_VIA_MATRIX: /* There is no difference since in both cases we must allocate dataset arrays */
case GMT_IS_REFERENCE|GMT_VIA_MATRIX:
/* Each matrix source becomes a separate table with a single segment unless there are NaN-records as segment headers */
if ((M_obj = S_obj->resource) == NULL) {
Expand Down Expand Up @@ -3916,6 +3923,7 @@ GMT_LOCAL struct GMT_DATASET * gmtapi_import_dataset (struct GMTAPI_CTRL *API, i
gmt_M_free (GMT, D_obj); return_null (API, GMT_PTR_IS_NULL);
}
if (V_obj->type[0] != GMT_DOUBLE) {
GMT_Report (API, GMT_MSG_ERROR, "Only double-precision vectors can be passed via reference to datasets\n");
gmt_M_free (GMT, D_obj); return_null (API, GMT_NOT_A_VALID_TYPE);
}
if (GMT->common.q.mode == GMT_RANGE_ROW_IN || GMT->common.q.mode == GMT_RANGE_DATA_IN)
Expand Down Expand Up @@ -3994,6 +4002,8 @@ GMT_LOCAL struct GMT_DATASET * gmtapi_import_dataset (struct GMTAPI_CTRL *API, i
return_null (API, GMT_OBJECT_NOT_FOUND); /* Some internal error... */
API->object[new_item]->resource = D_obj;
API->object[new_item]->status = GMT_IS_USED; /* Mark as read */
API->object[new_item]->alloc_mode = DH->alloc_mode; /* Clarify allocation mode for this object */
API->object[new_item]->alloc_level = DH->alloc_level;
}
if (D_obj->n_tables == 0) { /* Only found empty files (e.g., /dev/null) and we have nothing to show for our efforts. Return an single empty table with no segments. */
D_obj->table = gmt_M_memory (GMT, D_obj->table, 1, struct GMT_DATATABLE *);
Expand Down
16 changes: 11 additions & 5 deletions src/gmt_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -7746,22 +7746,30 @@ double *gmtlib_assign_vector (struct GMT_CTRL *GMT, uint64_t n_rows, uint64_t co

struct GMT_DATASET * gmt_get_dataset (struct GMT_CTRL *GMT) {
struct GMT_DATASET *D = NULL;
struct GMT_DATASET_HIDDEN *DH = NULL;
D = gmt_M_memory (GMT, NULL, 1, struct GMT_DATASET);
D->hidden = gmt_M_memory (GMT, NULL, 1, struct GMT_DATASET_HIDDEN);
D->hidden = DH = gmt_M_memory (GMT, NULL, 1, struct GMT_DATASET_HIDDEN);
DH->alloc_mode = GMT_ALLOC_INTERNALLY; /* So GMT_* modules can free this memory */
DH->alloc_level = GMT->hidden.func_level; /* Must be freed at this level */
return (D);
}

struct GMT_DATATABLE * gmt_get_table (struct GMT_CTRL *GMT) {
struct GMT_DATATABLE *T = NULL;
struct GMT_DATATABLE_HIDDEN *TH = NULL;
T = gmt_M_memory (GMT, NULL, 1, struct GMT_DATATABLE);
T->hidden = gmt_M_memory (GMT, NULL, 1, struct GMT_DATATABLE_HIDDEN);
T->hidden = TH = gmt_M_memory (GMT, NULL, 1, struct GMT_DATATABLE_HIDDEN);
TH->alloc_mode = GMT_ALLOC_INTERNALLY; /* So GMT_* modules can free this memory */
TH->alloc_level = GMT->hidden.func_level; /* Must be freed at this level */
return (T);
}

struct GMT_DATASEGMENT * gmt_get_segment (struct GMT_CTRL *GMT) {
struct GMT_DATASEGMENT *S = NULL;
struct GMT_DATASEGMENT_HIDDEN *SH = NULL;
S = gmt_M_memory (GMT, NULL, 1, struct GMT_DATASEGMENT);
S->hidden = gmt_M_memory (GMT, NULL, 1, struct GMT_DATASEGMENT_HIDDEN);
S->hidden = SH = gmt_M_memory (GMT, NULL, 1, struct GMT_DATASEGMENT_HIDDEN);
SH->alloc_mode = GMT_ALLOC_INTERNALLY; /* So GMT_* modules can free this memory */
return (S);
}

Expand Down Expand Up @@ -7825,8 +7833,6 @@ struct GMT_DATASET * gmtlib_create_dataset (struct GMT_CTRL *GMT, uint64_t n_tab
for (tbl = 0; tbl < n_tables; tbl++)
if ((D->table[tbl] = gmt_create_table (GMT, n_segments, n_rows, n_columns, mode, alloc_only)) == NULL)
return (NULL);
DH->alloc_level = GMT->hidden.func_level; /* Must be freed at this level. */
DH->alloc_mode = GMT_ALLOC_INTERNALLY; /* So GMT_* modules can free this memory. */
DH->id = GMT->parent->unique_var_ID++; /* Give unique identifier */

return (D);
Expand Down
85 changes: 50 additions & 35 deletions src/pslegend.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,31 @@ GMT_LOCAL void pslegend_maybe_realloc_table (struct GMT_CTRL *GMT, struct GMT_DA
TH->n_alloc += GMT_SMALL_CHUNK;
}

GMT_LOCAL void pslegend_free_unused_segments (struct GMT_CTRL *GMT, struct GMT_DATATABLE *T, uint64_t k) {
/* Must finalize the number of allocated segments */
struct GMT_DATATABLE_HIDDEN *TH = gmt_get_DT_hidden (T);
if (k == TH->n_alloc) return; /* Exact match */
T->n_segments = k;
for (unsigned int seg = T->n_segments; seg < TH->n_alloc; seg++) {
gmt_free_segment (GMT, &(T->segment[seg]));
}
T->segment = gmt_M_memory (GMT, T->segment, T->n_segments, struct GMT_DATASEGMENT *);
TH->n_alloc = T->n_segments;
}

GMT_LOCAL void pslegend_free_unused_rows (struct GMT_CTRL *GMT, struct GMT_DATASEGMENT *S, uint64_t k) {
/* Must finalize the number of allocated rows */
struct GMT_DATASEGMENT_HIDDEN *SH = gmt_get_DS_hidden (S);
if (k == SH->n_alloc) return; /* Not yet */
S->n_rows = k;
if (S->n_columns) { /* Numerical data */
uint64_t col;
for (col = 0; col < S->n_columns; col++)
S->data[col] = gmt_M_memory (GMT, S->data[col], S->n_rows, double);
}
if (S->text) S->text = gmt_M_memory (GMT, S->text, S->n_rows, char *);
}

GMT_LOCAL void pslegend_maybe_realloc_segment (struct GMT_CTRL *GMT, struct GMT_DATASEGMENT *S) {
struct GMT_DATASEGMENT_HIDDEN *SH = gmt_get_DS_hidden (S);
if (S->n_rows < SH->n_alloc) return; /* Not yet */
Expand Down Expand Up @@ -1824,9 +1849,14 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
/* Time to plot any symbols, text, fronts, quoted lines, and paragraphs we collected in the loop */

if (D[FRONT]) {
TH = gmt_get_DT_hidden (D[FRONT]->table[0]);
/* Create option list, register D[FRONT] as input source */
D[FRONT]->table[0]->n_segments = n_fronts; /* Set correct number of fronts */
pslegend_free_unused_segments (GMT, D[FRONT]->table[0], n_fronts);
#ifdef DEBUG
if (Ctrl->DBG.active) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_IO_RESET, NULL, "dump_front.txt", D[FRONT]) != GMT_NOERROR) {
Return (API->error);
}
}
#endif
if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_IN|GMT_IS_REFERENCE, D[FRONT], string) != GMT_NOERROR) {
Return (API->error);
}
Expand All @@ -1838,19 +1868,17 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
if (GMT_Close_VirtualFile (API, string) != GMT_NOERROR) {
Return (API->error);
}
}
if (D[QLINE]) {
pslegend_free_unused_segments (GMT, D[QLINE]->table[0], n_quoted_lines);
#ifdef DEBUG
if (Ctrl->DBG.active) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_IO_RESET, NULL, "dump_front.txt", D[FRONT]) != GMT_NOERROR) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_IO_RESET, NULL, "dump_qline.txt", D[QLINE]) != GMT_NOERROR) {
Return (API->error);
}
}
#endif
D[FRONT]->table[0]->n_segments = TH->n_alloc; /* Reset to allocation limit */
}
if (D[QLINE]) {
TH = gmt_get_DT_hidden (D[QLINE]->table[0]);
/* Create option list, register D[QLINE] as input source */
D[QLINE]->table[0]->n_segments = n_quoted_lines; /* Set correct number of lines */
if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_IN|GMT_IS_REFERENCE, D[QLINE], string) != GMT_NOERROR) {
Return (API->error);
}
Expand All @@ -1862,19 +1890,17 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
if (GMT_Close_VirtualFile (API, string) != GMT_NOERROR) {
Return (API->error);
}
}
if (D[DLINE]) {
pslegend_free_unused_segments (GMT, D[DLINE]->table[0], n_decorated_lines);
#ifdef DEBUG
if (Ctrl->DBG.active) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_IO_RESET, NULL, "dump_qline.txt", D[QLINE]) != GMT_NOERROR) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_IO_RESET, NULL, "dump_dline.txt", D[DLINE]) != GMT_NOERROR) {
Return (API->error);
}
}
#endif
D[QLINE]->table[0]->n_segments = TH->n_alloc; /* Reset to allocation limit */
}
if (D[DLINE]) {
TH = gmt_get_DT_hidden (D[DLINE]->table[0]);
/* Create option list, register D[DLINE] as input source */
D[DLINE]->table[0]->n_segments = n_decorated_lines; /* Set correct number of lines */
if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_LINE, GMT_IN|GMT_IS_REFERENCE, D[DLINE], string) != GMT_NOERROR) {
Return (API->error);
}
Expand All @@ -1886,18 +1912,16 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
if (GMT_Close_VirtualFile (API, string) != GMT_NOERROR) {
Return (API->error);
}
}
if (D[SYM]) {
pslegend_free_unused_segments (GMT, D[SYM]->table[0], n_symbols);
#ifdef DEBUG
if (Ctrl->DBG.active) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_LINE, GMT_IO_RESET, NULL, "dump_dline.txt", D[DLINE]) != GMT_NOERROR) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_POINT, GMT_IO_RESET, NULL, "dump_sym.txt", D[SYM]) != GMT_NOERROR) {
Return (API->error);
}
}
#endif
D[DLINE]->table[0]->n_segments = TH->n_alloc; /* Reset to allocation limit */
}
if (D[SYM]) {
TH = gmt_get_DT_hidden (D[SYM]->table[0]);
D[SYM]->table[0]->n_segments = n_symbols; /* Set correct number of segments */
/* Create option list, register D[SYM] as input source */
if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_POINT, GMT_IN|GMT_IS_REFERENCE, D[SYM], string) != GMT_NOERROR) {
Return (API->error);
Expand All @@ -1911,18 +1935,17 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
if (GMT_Close_VirtualFile (API, string) != GMT_NOERROR) {
Return (API->error);
}
}
if (D[TXT]) {
pslegend_free_unused_rows (GMT, D[TXT]->table[0]->segment[0], krow[TXT]);
D[TXT]->n_records = krow[TXT];
#ifdef DEBUG
if (Ctrl->DBG.active) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_POINT, GMT_IO_RESET, NULL, "dump_sym.txt", D[SYM]) != GMT_NOERROR) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_NONE, GMT_IO_RESET, NULL, "dump_txt.txt", D[TXT]) != GMT_NOERROR) {
Return (API->error);
}
}
#endif
D[SYM]->table[0]->n_segments = TH->n_alloc; /* Reset to allocation limit */
}
if (D[TXT]) {
TH = gmt_get_DT_hidden (D[TXT]->table[0]);
D[TXT]->table[0]->segment[0]->n_rows = D[TXT]->n_records = krow[TXT];
/* Create option list, register D[TXT] as input source */
if (GMT_Open_VirtualFile (API, GMT_IS_DATASET, GMT_IS_NONE, GMT_IN|GMT_IS_REFERENCE, D[TXT], string) != GMT_NOERROR) {
Return (API->error);
Expand All @@ -1935,14 +1958,6 @@ EXTERN_MSC int GMT_pslegend (void *V_API, int mode, void *args) {
if (GMT_Close_VirtualFile (API, string) != GMT_NOERROR) {
Return (API->error);
}
#ifdef DEBUG
if (Ctrl->DBG.active) {
if (GMT_Write_Data (API, GMT_IS_DATASET, GMT_IS_FILE, GMT_IS_NONE, GMT_IO_RESET, NULL, "dump_txt.txt", D[TXT]) != GMT_NOERROR) {
Return (API->error);
}
}
#endif
D[TXT]->table[0]->segment[0]->n_rows = D[TXT]->n_records = TH->n_alloc; /* To free what we allocated */
}
if (D[PAR]) {
if (n_para >= 0) { /* End of last paragraph for sure */
Expand Down