/*-------------------------------------------------------------------- * $Id: gmt_io.c,v 1.3.4.2 2002/02/14 22:56:03 pwessel Exp $ * * Copyright (c) 1991-2002 by P. Wessel and W. H. F. Smith * See COPYING file for copying and redistribution conditions. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * Contact info: gmt.soest.hawaii.edu *--------------------------------------------------------------------*/ /* * Table input/output in GMT can be either ascii or binary (where supported) * and ASCII tables may consist of single or multiple segments. When the * latter is the case usually there is a -M option to signal this case. * The structure GMT_IO holds parameters that are used during the reading * and processing of ascii tables. For compliance with a wide variety of * binary data formats for grids and their internal nesting the GMT_Z_IO * structure and associated functions are used (in xyz2grd and grd2xyz) * * The following functions are here: * * GMT_fopen: Open a file * GMT_fclose: Close a file * GMT_io_init: Init GMT_IO structure * GMT_io_selection: Decode the -b switch * GMT_multisegment: Decode the -M switch * GMT_write_segmentheader Write header record for multisegment files * GMT_ascii_input: Decode ascii input record * GMT_scanf: Robust scanf function with optional dd:mm:ss conversion * GMT_bin_double_input: Decode binary double precision record * GMT_bin_float_input: Decode binary single precision record * GMT_ascii_output: Write ascii record * GMT_bin_double_output: Write binary double precision record * GMT_bin_float_output: Write binary single precision record * GMT_init_z_io: Initialize GMT_Z_IO structure * GMT_parse_z_io: Parse the -Z switch * GMT_set_z_io: Set GMT_Z_IO structure based on -Z * GMT_check_z_io: Fill in implied missing row/column * GMT_a_read: Read 1 ascii item * GMT_c_read: Read 1 binary char item * GMT_u_read: Read 1 binary unsigned char item * GMT_h_read: Read 1 binary short int item * GMT_H_read: Read 1 binary unsigned short int item * GMT_i_read: Read 1 binary int item * GMT_I_read: Read 1 binary unsigned int item * GMT_l_read: Read 1 binary long int item * GMT_f_read: Read 1 binary float item * GMT_d_read: Read 1 binary double item * GMT_a_write: Write 1 ascii item * GMT_c_write: Write 1 binary char item * GMT_u_write: Write 1 binary unsigned char item * GMT_h_write: Write 1 binary short int item * GMT_H_write: Write 1 binary unsigned short int item * GMT_i_write: Write 1 binary int item * GMT_I_write: Write 1 binary unsigned int item * GMT_l_write: Write 1 binary long int item * GMT_f_write: Write 1 binary float item * GMT_d_write: Write 1 binary double item * GMT_col_ij: Convert index to column format * GMT_row_ij: Convert index to row format * * Author: Paul Wessel * Date: 14-JUL-2000 * Version: 3.4.1 */ #include "gmt.h" #define GMT_I_60 (1.0 / 60.0) /* Convert minutes to degrees */ #define GMT_I_3600 (1.0 / 3600.0) /* Convert seconds to degrees */ BOOLEAN GMT_do_swab = FALSE; /* Used to indicate swab'ing during binary read */ int GMT_a_read (FILE *fp, double *d); int GMT_c_read (FILE *fp, double *d); int GMT_u_read (FILE *fp, double *d); int GMT_h_read (FILE *fp, double *d); int GMT_H_read (FILE *fp, double *d); int GMT_i_read (FILE *fp, double *d); int GMT_I_read (FILE *fp, double *d); int GMT_l_read (FILE *fp, double *d); int GMT_f_read (FILE *fp, double *d); int GMT_d_read (FILE *fp, double *d); int GMT_a_write (FILE *fp, double d); int GMT_c_write (FILE *fp, double d); int GMT_u_write (FILE *fp, double d); int GMT_h_write (FILE *fp, double d); int GMT_H_write (FILE *fp, double d); int GMT_i_write (FILE *fp, double d); int GMT_I_write (FILE *fp, double d); int GMT_l_write (FILE *fp, double d); int GMT_f_write (FILE *fp, double d); int GMT_d_write (FILE *fp, double d); void GMT_col_ij (struct GMT_Z_IO *r, int ij, int *gmt_ij); void GMT_row_ij (struct GMT_Z_IO *r, int ij, int *gmt_ij); int GMT_ascii_input (FILE *fp, int *n, double **ptr); /* Decode Ascii input records */ int GMT_bin_double_input (FILE *fp, int *n, double **ptr); /* Decode binary double input records */ int GMT_bin_float_input (FILE *fp, int *n, double **ptr); /* Decode binary float input records */ int GMT_ascii_output (FILE *fp, int n, double *ptr); /* Write Ascii output records */ int GMT_bin_double_output (FILE *fp, int n, double *ptr); /* Write binary double output records */ int GMT_bin_float_output (FILE *fp, int n, double *ptr); /* Write binary float output records */ void GMT_adjust_periodic (); /* Add/sub 360 as appropriate */ /* Table I/O routines for ascii and binary io */ FILE *GMT_fopen (const char* filename, const char* mode) { return (fopen (filename, mode)); } int GMT_fclose (FILE *stream) { return (fclose (stream)); } void GMT_io_init (void) { /* No need to init the structure as this is done in gmt_init.h directoy */ GMT_input = GMT_input_ascii = GMT_ascii_input; GMT_output = GMT_ascii_output; GMT_io.give_report = TRUE; GMT_io.skip_bad_records = TRUE; } int GMT_io_selection (char *text) { /* Syntax: -b[i][o][s][d][#cols] */ int i, id = 0; BOOLEAN i_or_o = FALSE, ok = TRUE, error = FALSE; for (i = 0; ok && text[i]; i++) { switch (text[i]) { case 'i': /* Settings apply to input */ id = 0; GMT_io.binary[id] = i_or_o = TRUE; break; case 'o': /* Settings apply to output */ id = 1; GMT_io.binary[id] = i_or_o = TRUE; break; case 's': /* Single Precision */ GMT_io.single_precision[id] = TRUE; break; case 'd': /* Double Precision */ GMT_io.single_precision[id] = FALSE; break; case '0': /* Number of columns */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': GMT_io.ncol[id] = atoi (&text[i]); while (text[i] && isdigit ((int)text[i])) i++; i--; break; default: /* Stop scanning */ error = TRUE; fprintf (stderr, "%s: GMT Error: Malformed -b argument [%s]\n", GMT_program, text); break; } } if (!i_or_o) { /* Specified neither i or o so let settings apply to both */ GMT_io.binary[0] = GMT_io.binary[1] = TRUE; GMT_io.single_precision[1] = GMT_io.single_precision[0]; GMT_io.ncol[1] = GMT_io.ncol[0]; } if (GMT_io.binary[0]) { GMT_input = (GMT_io.single_precision[0]) ? GMT_bin_float_input : GMT_bin_double_input; strcpy (GMT_io.r_mode, "rb"); } if (GMT_io.binary[1]) { GMT_output = (GMT_io.single_precision[1]) ? GMT_bin_float_output : GMT_bin_double_output; strcpy (GMT_io.w_mode, "wb"); } return (error); } void GMT_multisegment (char *text) { /* Turns multisegment on and sets flag, if given. * flag is only used for ASCII data sets */ GMT_io.multi_segments = TRUE; if (text[0]) GMT_io.EOF_flag = text[0]; } int GMT_ascii_input (FILE *fp, int *n, double **ptr) { char line[BUFSIZ], *p; int i, len, n_convert; BOOLEAN done = FALSE, bad_record; double val; /* GMT_ascii_input will skip blank lines and cshell comment lines which start * with # except when -M# is used of course. Fields may be separated by * spaces, tabs, or commas. The routine returns the actual * number of items read [or 0 for segment header and -1 for EOF] * If *n is passed as BUFSIZ it will be reset to the actual number of fields */ while (!done) { /* First read until we get a non-blank, non-comment record or reach EOF */ GMT_io.rec_no++; while ((p = fgets (line, BUFSIZ, fp)) && (line[0] == '\n' || (line[0] == '#' && GMT_io.EOF_flag != '#'))) GMT_io.rec_no++; if (!p) { GMT_io.status = GMT_IO_EOF; if (GMT_io.give_report && GMT_io.n_bad_records) { /* Report summary and reset */ fprintf (stderr, "%s: This file had %d records with invalid x and/or y values\n", GMT_program, GMT_io.n_bad_records); GMT_io.n_bad_records = GMT_io.rec_no = 0; } return (-1); } if (GMT_io.multi_segments && line[0] == GMT_io.EOF_flag) { GMT_io.status = GMT_IO_SEGMENT_HEADER; strcpy (GMT_io.segment_header, line); return (0); } /* Normal data record */ /* First chop off trailing whitespace and commas */ len = strlen (line); #ifndef _WIN32 if (len >= (BUFSIZ-1)) { fprintf (stderr, "%s: This file appears to be in DOS format - reformat with dos2unix\n", GMT_program); exit (EXIT_FAILURE); } #endif for (i = len - 1; i >= 0 && strchr (" \t,\n", (int)line[i]); i--); line[++i] = '\n'; line[++i] = '\0'; bad_record = FALSE; strcpy (GMT_io.current_record, line); line[i-1] = '\0'; /* Chop off newline */ p = strtok(line, " \t,"); i = 0; while (!bad_record && p && i < *n) { if ((n_convert = GMT_scanf (p, &val)) == 1) { /* Decoded string to a number */ GMT_data[i] = val; } else { GMT_data[i] = GMT_d_NaN; if (i < 2) bad_record = TRUE; /* If x and/or y is NaN then set bad */ } p = strtok(CNULL, " \t,"); i++; } if (GMT_io.skip_bad_records && bad_record) { GMT_io.n_bad_records++; if (GMT_io.give_report && (GMT_io.n_bad_records == 1)) { /* Report 1st occurence */ fprintf (stderr, "%s: Encountered first invalid x and/or y values near record # %d\n", GMT_program, GMT_io.rec_no); } } else done = TRUE; } *ptr = GMT_data; GMT_io.status = (i == *n || *n == BUFSIZ) ? 0 : GMT_IO_MISMATCH; if (*n == BUFSIZ) *n = i; if (gmtdefs.xy_toggle) d_swap (GMT_data[0], GMT_data[1]); /* Got lat/lon instead of lon/lat */ if (GMT_geographic_in) { GMT_adjust_periodic (); /* Must account for periodicity in 360 */ } return (i); } int GMT_scanf (char *p, double *val) { /* Converts text to double if certain conditions are met: p must be of the form [+|-][0-9][.][0-9][E|e|D|e][+|-][0-9] OR [+|-][dd:mm[:ss][WESN] If it is the former we look for d or D which is FORTRASH for exponent and convert to e and then call atof. If it is the latter we do a straight conversion. */ int i, k, c, colons, suffix; BOOLEAN error, period, exponent, sign, flip_sign; double degree, minute, second; for (i = colons = 0; p[i]; i++) if (p[i] == ':') colons++; /* Colons indicate dd:mm:ss format */ k = --i; c = (int)p[k]; /* Last character in string */ suffix = toupper (c); /* Last character in string, forced upper case */ if (colons == 0) { /* Regular ASCII representation of an integer or floating point number */ if (suffix == 'W' || suffix == 'S') { /* Sign was given implicitly as -ve */ p[k] = 0; /* Temporarily hide the suffix - will restore below */ flip_sign = TRUE; } else if (suffix == 'E' || suffix == 'N') { /* Sign was given implicitly as +ve */ p[k] = 0; /* Temporarily hide the suffix - will restore below */ flip_sign = FALSE; } else /* No suffix or unrecognized suffix */ flip_sign = FALSE; i = 0; /* Reset to 1st character */ while (p[i] == ' ') i++; /* Skip leading blanks */ if (p[i] == '-' || p[i] == '+') i++; /* Leading sign is OK */ error = period = exponent = sign = FALSE; while (p[i] && !error) { if (p[i] == '.') { /* One period is OK */ if (period) error = TRUE; period = TRUE; } else if (p[i] == 'D' || p[i] == 'd') { /* Fortran Double Precision Fix */ p[i] = 'e'; /* 'd' is not understood outside Fortran i/o */ if (exponent) error = TRUE; exponent = TRUE; } else if (p[i] == 'E' || p[i] == 'e') { /* Normal exponentional notation */ if (exponent) error = TRUE; exponent = TRUE; } else if (p[i] == '-' || p[i] == '+') { /* One more sign only ok after exponential */ if (sign || !exponent) error = TRUE; sign = TRUE; } else if (p[i] < '0' || p[i] > '9') /* Other non-digits are not allowed */ error = TRUE; i++; } if (error) return (0); /* Failed format check */ *val = atof (p); /* Safe to convert */ if (flip_sign) { /* Flip sign and restore missing suffix in text string */ *val = -(*val); p[k] = suffix; } return (1); } /* Here we know we need to deal with dd:mm[:ss] strings */ if (colons == 2) { /* dd:mm:ss format */ sscanf (p, "%lf:%lf:%lf", °ree, &minute, &second); if (suffix == 'W' || suffix == 'w' || suffix == 'S' || suffix == 's') degree = -degree; /* Sign was given implicitly */ *val = degree + copysign (minute * GMT_I_60 + second * GMT_I_3600, degree); } else if (colons == 1) { /* dd:mm format */ sscanf (p, "%lf:%lf", °ree, &minute); if (suffix == 'W' || suffix == 'w' || suffix == 'S' || suffix == 's') degree = -degree; /* Sign was given implicitly */ *val = degree + copysign (minute * GMT_I_60, degree); } else /* Unrecognized */ return (0); return (1); } char *GMT_fgets (char *record, int maxlength, FILE *fp) { return (fgets (record, maxlength, fp)); } int GMT_bin_double_input (FILE *fp, int *n, double **ptr) { int n_read; GMT_io.status = 0; if ((n_read = fread ((void *) GMT_data, sizeof (double), (size_t)(*n), fp)) != (*n)) { GMT_io.status = (feof (fp)) ? GMT_IO_EOF : GMT_IO_MISMATCH; } *ptr = GMT_data; /* Read ok, how about multisegment? */ if (!GMT_io.status && GMT_io.multi_segments) { /* Must have n_read NaNs */ int i; BOOLEAN is_bad = TRUE; for (i = 0; i < n_read && is_bad; i++) is_bad = GMT_is_dnan (GMT_data[i]); if (is_bad) { GMT_io.status = GMT_IO_SEGMENT_HEADER; strcpy (GMT_io.segment_header, "> Binary multisegment header\n"); return (0); } } if (gmtdefs.xy_toggle) d_swap (GMT_data[0], GMT_data[1]); /* Got lat/lon instead of lon/lat */ if (GMT_geographic_in) { GMT_adjust_periodic (); /* Must account for periodicity in 360 */ } return (n_read); } int GMT_bin_float_input (FILE *fp, int *n, double **ptr) { int i, n_read; static float GMT_f[BUFSIZ]; GMT_io.status = 0; if ((n_read = fread ((void *) GMT_f, sizeof (float), (size_t)(*n), fp)) != (*n)) { GMT_io.status = (feof (fp)) ? GMT_IO_EOF : GMT_IO_MISMATCH; } else { for (i = 0; i < n_read; i++) GMT_data[i] = (double)GMT_f[i]; } *ptr = GMT_data; /* Read ok, how about multisegment? */ if (!GMT_io.status && GMT_io.multi_segments) { /* Must have n_read NaNs */ BOOLEAN is_bad = TRUE; for (i = 0; i < n_read && is_bad; i++) is_bad = GMT_is_dnan (GMT_data[i]); if (is_bad) { GMT_io.status = GMT_IO_SEGMENT_HEADER; strcpy (GMT_io.segment_header, "> Binary multisegment header\n"); return (0); } } if (gmtdefs.xy_toggle) d_swap (GMT_data[0], GMT_data[1]); /* Got lat/lon instead of lon/lat */ if (GMT_geographic_in) { GMT_adjust_periodic (); /* Must account for periodicity in 360 */ } return (n_read); } void GMT_adjust_periodic (void) { /* while (GMT_data[0] > project_info.e) GMT_data[0] -= 360.0; while (GMT_data[0] < project_info.w) GMT_data[0] += 360.0; */ while (GMT_data[0] > project_info.e && (GMT_data[0] - 360.0) >= project_info.w) GMT_data[0] -= 360.0; while (GMT_data[0] < project_info.w && (GMT_data[0] + 360.0) <= project_info.w) GMT_data[0] += 360.0; /* If data is not inside the given range it will satisfy (lon > east) */ /* Now it will be outside the region on the same side it started out at */ } int GMT_ascii_output (FILE *fp, int n, double *ptr) { int i, e = 0, wn = 0; if (gmtdefs.xy_toggle) d_swap (ptr[0], ptr[1]); /* Write lat/lon instead of lon/lat */ n--; for (i = 0; i < n && e >= 0; i++) { (GMT_is_dnan (ptr[i])) ? (e = fprintf (fp, "NaN\t")) : (e = fprintf (fp, gmtdefs.d_format, ptr[i]), putc ('\t', fp)); wn += e; } (GMT_is_dnan (ptr[n])) ? (e = fprintf (fp, "NaN\n")) : (e = fprintf (fp, gmtdefs.d_format, ptr[n]), putc ('\n', fp)); wn += e; return ((e < 0) ? e : wn); } int GMT_bin_double_output (FILE *fp, int n, double *ptr) { if (gmtdefs.xy_toggle) d_swap (ptr[0], ptr[1]); /* Write lat/lon instead of lon/lat */ return (fwrite ((void *) ptr, sizeof (double), (size_t)n, fp)); } int GMT_bin_float_output (FILE *fp, int n, double *ptr) { int i; static float GMT_f[BUFSIZ]; if (gmtdefs.xy_toggle) d_swap (ptr[0], ptr[1]); /* Write lat/lon instead of lon/lat */ for (i = 0; i < n; i++) GMT_f[i] = (float)ptr[i]; return (fwrite ((void *) GMT_f, sizeof (float), (size_t)n, fp)); } void GMT_write_segmentheader (FILE *fp, int n) { /* Output ASCII or binary multisegment header */ int i; if (GMT_io.binary[1]) for (i = 0; i < n; i++) GMT_output (fp, 1, &GMT_d_NaN); else fprintf (fp, "%s", GMT_io.segment_header); } void GMT_init_z_io (struct GMT_Z_IO *r, BOOLEAN input) { memset ((void *) r, 0, sizeof (struct GMT_Z_IO)); r->input = input; /* Set default format if no arguments are given to be TLf */ if (input) r->read_item = GMT_a_read; else r->write_item = GMT_a_write; r->binary = FALSE; r->format = GMT_ROW_FORMAT; r->y_step = r->x_step = 1; } int GMT_parse_z_io (char *txt, struct GMT_Z_IO *r, BOOLEAN input) { BOOLEAN first = TRUE; int i; /* BOOLEAN input: currently unused */ for (i = 0; txt[i]; i++) { /* Loop over flags */ switch (txt[i]) { /* These 4 cases will set the format orientation for input */ case 'T': if (first) r->format = GMT_ROW_FORMAT; r->y_step = 1; first = FALSE; break; case 'B': if (first) r->format = GMT_ROW_FORMAT; r->y_step = -1; first = FALSE; break; case 'L': if (first)r->format = GMT_COLUMN_FORMAT; r->x_step = 1; first = FALSE; break; case 'R': if (first)r->format = GMT_COLUMN_FORMAT; r->x_step = -1; first = FALSE; break; /* Set this if file is periodic, is grid registrered, but repeating column or row is missing from input */ case 'x': r->x_missing = 1; break; case 'y': r->y_missing = 1; break; /* Optionally skip the given number of bytes before reading data */ case 's': i++; if (txt[i]) { r->skip = atoi (&txt[i]); while (txt[i] && isdigit ((int)txt[i])) i++; i--; } break; case 'w': r->swab = TRUE; break; /* Set read pointer depending on data format */ case 'a': /* ASCII */ r->read_item = GMT_a_read; r->write_item = GMT_a_write; r->binary = FALSE; break; case 'c': /* Binary signed char */ r->read_item = GMT_c_read; r->write_item = GMT_c_write; r->binary = TRUE; break; case 'u': /* Binary unsigned char */ r->read_item = GMT_u_read; r->write_item = GMT_u_write; r->binary = TRUE; break; case 'h': /* Binary short 2-byte integer */ r->read_item = GMT_h_read; r->write_item = GMT_h_write; r->binary = TRUE; break; case 'H': /* Binary unsigned short 2-byte integer */ r->read_item = GMT_H_read; r->write_item = GMT_H_write; r->binary = TRUE; break; case 'i': /* Binary 4-byte integer */ r->read_item = GMT_i_read; r->write_item = GMT_i_write; r->binary = TRUE; break; case 'I': /* Binary 4-byte unsigned integer */ r->read_item = GMT_I_read; r->write_item = GMT_I_write; r->binary = TRUE; break; case 'l': /* Binary 4(or8)-byte integer, machine dependent! */ r->read_item = GMT_l_read; r->write_item = GMT_l_write; r->binary = TRUE; break; case 'f': /* Binary 4-byte float */ r->read_item = GMT_f_read; r->write_item = GMT_f_write; r->binary = TRUE; break; case 'd': /* Binary 8-byte double */ r->read_item = GMT_d_read; r->write_item = GMT_d_write; r->binary = TRUE; break; default: fprintf (stderr, "%s: GMT SYNTAX ERROR -Z: %c not a valid modifier!\n", GMT_program, txt[i]); exit (EXIT_FAILURE); break; } } if (r->binary) { strcpy (GMT_io.r_mode, "rb"); strcpy (GMT_io.w_mode, "wb"); } return (FALSE); } void GMT_set_z_io (struct GMT_Z_IO *r, struct GRD_HEADER *h) { if ((r->x_missing || r->y_missing) && h->node_offset == 1) { fprintf (stderr, "%s: Pixel format grids do not have repeating rows or columns!\n", GMT_program); exit (EXIT_FAILURE); } r->start_col = (r->x_step == 1) ? 0 : h->nx - 1 - r->x_missing; r->start_row = (r->y_step == 1) ? r->y_missing : h->ny - 1; r->get_gmt_ij = (r->format == GMT_COLUMN_FORMAT) ? GMT_col_ij : GMT_row_ij; r->nx = h->nx; r->ny = h->ny; r->x_period = h->nx - r->x_missing; r->y_period = h->ny - r->y_missing; r->n_expected = r->x_period * r->y_period; GMT_do_swab = r->swab; } void GMT_check_z_io (struct GMT_Z_IO *r, float *a) { /* Routine to fill in the implied periodic row or column that was missing */ int i, j, k; if (r->x_missing) for (j = 0; j < r->ny; j++) a[(j+1)*r->nx-1] = a[j*r->nx]; if (r->y_missing) for (i = 0, k = (r->ny-1)*r->nx; i < r->nx; i++) a[i] = a[k+i]; } int GMT_a_read (FILE *fp, double *d) { char line[64]; if (fgets (line, 64, fp)) { *d = (line[0] == 'N' || line[0] == 'n') ? GMT_d_NaN : atof (line); return (1); } return (0); } int GMT_c_read (FILE *fp, double *d) { char c; if (fread ((void *)&c, sizeof (char), 1, fp)) { *d = (double) c; return (1); } return (0); } int GMT_u_read (FILE *fp, double *d) { unsigned char u; if (fread ((void *)&u, sizeof (unsigned char), 1, fp)) { *d = (double) u; return (1); } return (0); } int GMT_h_read (FILE *fp, double *d) { short int h; if (fread ((void *)&h, sizeof (short int), 1, fp)) { if (GMT_do_swab) h = GMT_swab2 (h); *d = (double) h; return (1); } return (0); } int GMT_H_read (FILE *fp, double *d) { unsigned short int h; if (fread ((void *)&h, sizeof (unsigned short int), 1, fp)) { *d = (double) ((GMT_do_swab) ? GMT_swab2 (h) : h); return (1); } return (0); } int GMT_i_read (FILE *fp, double *d) { int i; if (fread ((void *)&i, sizeof (int), 1, fp)) { if (GMT_do_swab) i = GMT_swab4 (i); *d = (double) i; return (1); } return (0); } int GMT_I_read (FILE *fp, double *d) { unsigned int i; if (fread ((void *)&i, sizeof (unsigned int), 1, fp)) { *d = (double) ((GMT_do_swab) ? GMT_swab4 (i) : i); return (1); } return (0); } int GMT_l_read (FILE *fp, double *d) { long int l; if (fread ((void *)&l, sizeof (long int), 1, fp)) { if (GMT_do_swab) { unsigned int *i, k; i = (unsigned int *)&l; for (k = 0; k < sizeof (long int)/4; k++) i[k] = GMT_swab4 (i[k]); } *d = (double) l; return (1); } return (0); } int GMT_f_read (FILE *fp, double *d) { float f; if (fread ((void *)&f, sizeof (float), 1, fp)) { if (GMT_do_swab) { unsigned int *i; i = (unsigned int *)&f; *i = GMT_swab4 (*i); } *d = (double) f; return (1); } return (0); } int GMT_d_read (FILE *fp, double *d) { if (fread ((void *)d, sizeof (double), 1, fp)) { if (GMT_do_swab) { unsigned int *i, j; i = (unsigned int *)d; j = GMT_swab4 (i[0]); i[0] = GMT_swab4 (i[1]); i[1] = j; } return (1); } return (0); } int GMT_a_write (FILE *fp, double d) { int n = 0; n = (GMT_is_dnan (d)) ? fprintf (fp, "NaN") : fprintf (fp, gmtdefs.d_format, d); fprintf (fp, "\n"); return (n); } int GMT_c_write (FILE *fp, double d) { char c; c = (char) d; return (fwrite ((void *)&c, sizeof (char), (size_t)1, fp)); } int GMT_u_write (FILE *fp, double d) { unsigned char u; u = (unsigned char) d; return (fwrite ((void *)&u, sizeof (unsigned char), (size_t)1, fp)); } int GMT_h_write (FILE *fp, double d) { short int h; h = (short int) d; return (fwrite ((void *)&h, sizeof (short int), (size_t)1, fp)); } int GMT_H_write (FILE *fp, double d) { unsigned short int h; h = (unsigned short int) d; return (fwrite ((void *)&h, sizeof (unsigned short int), (size_t)1, fp)); } int GMT_i_write (FILE *fp, double d) { int i; i = (int) d; return (fwrite ((void *)&i, sizeof (int), (size_t)1, fp)); } int GMT_I_write (FILE *fp, double d) { unsigned int i; i = (unsigned int) d; return (fwrite ((void *)&i, sizeof (unsigned int), (size_t)1, fp)); } int GMT_l_write (FILE *fp, double d) { long int l; l = (long int) d; return (fwrite ((void *)&l, sizeof (long int), (size_t)1, fp)); } int GMT_f_write (FILE *fp, double d) { float f; f = (float) d; return (fwrite ((void *)&f, sizeof (float), (size_t)1, fp)); } int GMT_d_write (FILE *fp, double d) { return (fwrite ((void *)&d, sizeof (double), (size_t)1, fp)); } void GMT_col_ij (struct GMT_Z_IO *r, int ij, int *gmt_ij) { /* Translates incoming ij to gmt_ij for column-structured data */ r->gmt_j = r->start_row + r->y_step * (ij % r->y_period); r->gmt_i = r->start_col + r->x_step * (ij / r->y_period); *gmt_ij = r->gmt_j * r->nx + r->gmt_i; } void GMT_row_ij (struct GMT_Z_IO *r, int ij, int *gmt_ij) { /* Translates incoming ij to gmt_ij for row-structured data */ r->gmt_j = r->start_row + r->y_step * (ij / r->x_period); r->gmt_i = r->start_col + r->x_step * (ij % r->x_period); *gmt_ij = r->gmt_j * r->nx + r->gmt_i; }