📄 mexcdf53.c
字号:
/*
* mexcdf53.c -- For Matlab Version 5 and NetCDF Version 3.
*
* ******************** NOTICE ********************
*
* MEXCDF53 -- USGS Preliminary Computer Software For
* Interaction Between Matlab-5 and NetCDF-3.
*
* Begun: Tuesday, July 14, 1992 6:59:54 PM.
* Version: Tuesday, March 4, 1997 3:54:00 PM.
* Version: Wednesday, December 16, 1998 4:43:00 PM.
* byte ==> (signed char) Jim Mansbridge.
* Version: Monday, January 24, 2000 19:11:50 PM.
* varget1, vargetg, attget: plhs[0]
* Version: Tuesday, September 17, 2002.
* MacOSX version built with this.
*
* Written, Maintained, and Supported By:
* Dr. Charles R. Denham
* U.S. Geological Survey
* Woods Hole, Massachusetts 02543
* e-mail: cdenham@usgs.gov
*
* Computer Programming Language:
* The C-Language.
*
* Computer System:
* This software has been successfully linked with
* the NetCDF-3 library and executed from Matlab-5
* on Power Macintosh and DEC Alpha hardware. The
* software is intended to be compatible with all
* installations of Matlab-4, Matlab-5, NetCDF-2,
* and NetCDF-3.
*
* Source Code Available From:
* Author.
*
* Disclaimer:
* Although this software has been used by the USGS, no
* warranty, expressed or implied, is made by the USGS
* or the United States Government as to the accuracy
* and functioning of the software and related software
* material, nor shall the fact of distribution constitute
* any such warranty or publication, and no responsibility
* is assumed by the USGS in connection therewith.
*
* Fair Use:
* This software, named "mexcdf53", may be used freely on
* condition that this NOTICE be displayed prominantly and
* in its entirety on all copies of the software, as well
* as on all copies of software that has been derived from
* this software. Furthermore, this software requires the
* UCAR/Unidata NetCDF library, whose conditions on proper
* credit, distribution, and use must be acknowledged and
* honored fully.
*
* ******************** END OF NOTICE ********************
*
* Use mexcdf53.c and mexcdf.h, plus a valid NetCDF library,
* to build mexcdf53.mex, a mex-file function that is intended
* to be executed from Matlab.
*
* This source-code uses MATLAB Version 5 mex-file syntax,
* but it still requires that the -V4 compiler-flag be
* specified when building with the "mex" script supplied
* by MathWorks. (V4 not relevant with Matlab 6.)
*
* The strictly two-dimensional assumption of Matlab-4 can
* be recreated by specifying the MEXCDF_4 compiler-flag,
* in addition to the -V4 flag mentioned above.
* (V4 not relevant with Matlab 6.)
*
* To build mexcdf53 for use with MATLAB Version 4, specify
* the MEXCDF_4 flag, as well as other flags required by
* the "cmex" script supplied previously by MathWorks.
*
* This Mex-file invokes the high-level C-Language NetCDF-2
* interface of the NetCDF Users Guide. All of the specified
* NetCDF input arguments are required. All output arguments
* are optional.
*
* Matlab Syntax:
*
* [out1, out2, ...] = mexcdf53('operation', in1, in2, ...)
*
* Extensions:
*
* 1. Dimensions and variables accessible by id or name.
* 2. Attributes accessible by name or number.
* 3. Parameters accessible by number or name.
* 4. Prepended "nc" not necessary for operation names.
* 5. Prepended "NC_" not necessary for specifying parameters.
* 6. Parameter names not case-sensitive.
* 7. Required lengths default to actual lengths via -1.
* 8. Scaling via "scale_factor" and "add_offset" attributes.
* 9. SETOPTS to set NetCDF options. NC_FATAL is disabled.
* 10. ERR to get and auto-reset the most recent error-code.
* 11. PARAMETER to access parameters by name.
* 12. USAGE to list mexcdf53 syntax.
*
*/
# include <ctype.h>
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "netcdf.h"
# include "mex.h"
# include "mexcdf.h"
static VOID Usage (VOID);
static Matrix * SetNum (Matrix *);
static Matrix * SetStr (Matrix *);
static char * Mat2Str (Matrix *);
static Matrix * Str2Mat (char *);
static int * Mat2Int (Matrix *);
static Matrix * Int2Mat (int *, int, int);
static long * Mat2Long (Matrix *);
static Matrix * Long2Mat (long *, int, int);
static int Scalar2Int (Matrix *);
static Matrix * Int2Scalar (int);
static long Scalar2Long (Matrix *);
static Matrix * Long2Scalar (long);
static int Count (Matrix *);
static int Parameter (Matrix *);
static VOID Free (VOIDPP);
static DOUBLE Scale_Factor (int, int);
static DOUBLE Add_Offset (int, int);
static int Convert (OPCODE, nc_type, int, VOIDP,
DOUBLE, DOUBLE, DOUBLE *);
static nc_type RepairBadDataType (nc_type);
/* MexFunction(): Mex-file entry point. */
void
mexFunction (
INT nlhs,
Matrix * plhs[],
INT nrhs,
const Matrix * prhs[]
)
{
char * opname;
OPCODE opcode;
Matrix * mat;
int status;
char * path;
int cmode;
int mode;
int cdfid;
int ndims;
int nvars;
int natts;
int recdim;
char * name;
long length;
int dimid;
nc_type datatype;
int * dim;
int varid;
long * coords;
VOIDP value;
long * start;
long * count;
int * intcount;
long * stride;
long * imap;
long recnum;
int nrecvars;
int * recvarids;
long * recsizes;
VOIDPP datap; /* pointers for record access. */
int len;
int incdf;
int invar;
int outcdf;
int outvar;
int attnum;
char * attname;
char * newname;
int fillmode;
int i;
int m;
int n;
char * p;
char buffer[MAX_BUFFER];
DOUBLE * pr;
DOUBLE addoffset;
DOUBLE scalefactor;
int autoscale; /* do auto-scaling if this flag is non-zero. */
/* Disable the NC_FATAL option from ncopts. */
if (ncopts & NC_FATAL) {
ncopts -= NC_FATAL;
}
/* Display usage if less than one input argument. */
if (nrhs < 1) {
Usage();
return;
}
/* Convert the operation name to its opcode. */
opname = Mat2Str(prhs[0]);
for (i = 0; i < strlen(opname); i++) {
opname[i] = (char) tolower((int) opname[i]);
}
p = opname;
if (strncmp(p, "nc", 2) == 0) { /* Trim away "nc". */
p += 2;
}
i = 0;
opcode = NONE;
while (ops[i].opcode != NONE) {
if (!strcmp(p, ops[i].opname)) {
opcode = ops[i].opcode;
if (ops[i].nrhs > nrhs) {
mexPrintf("MEXCDF: opname = %s\n", opname);
mexErrMsgTxt("MEXCDF: Too few input arguments.\n");
}
else if (0 && ops[i].nlhs > nlhs) { /* Disabled. */
mexPrintf("MEXCDF: opname = %s\n", opname);
mexErrMsgTxt("MEXCDF: Too few output arguments.\n");
}
break;
}
else {
i++;
}
}
if (opcode == NONE) {
mexPrintf("MEXCDF: opname = %s\n", opname);
mexErrMsgTxt("MEXCDF: No such operation.\n");
}
Free((VOIDPP) & opname);
/* Extract the cdfid by number. */
switch (opcode) {
case USAGE:
case CREATE:
case OPEN:
case TYPELEN:
case SETOPTS:
case ERR:
case PARAMETER:
break;
default:
cdfid = Scalar2Int(prhs[1]);
break;
}
/* Extract the dimid by number or name. */
switch (opcode) {
case DIMINQ:
case DIMRENAME:
if (mxIsNumeric(prhs[2])) {
dimid = Scalar2Int(prhs[2]);
}
else {
name = Mat2Str(prhs[2]);
dimid = ncdimid(cdfid, name);
Free((VOIDPP) & name);
}
break;
default:
break;
}
/* Extract the varid by number or name. */
switch (opcode) {
case VARINQ:
case VARPUT1:
case VARGET1:
case VARPUT:
case VARGET:
case VARPUTG:
case VARGETG:
case VARRENAME:
case VARCOPY:
case ATTPUT:
case ATTINQ:
case ATTGET:
case ATTCOPY:
case ATTNAME:
case ATTRENAME:
case ATTDEL:
if (mxIsNumeric(prhs[2])) {
varid = Scalar2Int(prhs[2]);
}
else {
name = Mat2Str(prhs[2]);
varid = ncvarid(cdfid, name);
Free((VOIDPP) & name);
if (varid == -1) {
varid = Parameter(prhs[2]);
}
}
break;
default:
break;
}
/* Extract the attname by name or number. */
switch (opcode) {
case ATTPUT:
case ATTINQ:
case ATTGET:
case ATTCOPY:
case ATTRENAME:
case ATTDEL:
if (mxIsNumeric(prhs[3])) {
attnum = Scalar2Int(prhs[3]);
attname = (char *) mxCalloc(MAX_NC_NAME, sizeof(char));
status = ncattname(cdfid, varid, attnum, attname);
}
else {
attname = Mat2Str(prhs[3]);
}
break;
default:
break;
}
/* Extract the "add_offset" and "scale_factor" attributes. */
switch (opcode) {
case VARPUT1:
case VARGET1:
case VARPUT:
case VARGET:
case VARPUTG:
case VARGETG:
addoffset = Add_Offset(cdfid, varid);
scalefactor = Scale_Factor(cdfid, varid);
if (scalefactor == 0.0) {
scalefactor = 1.0;
}
break;
default:
break;
}
/* Perform the NetCDF operation. */
switch (opcode) {
case USAGE:
Usage();
break;
case CREATE:
path = Mat2Str(prhs[1]);
if (nrhs > 2) {
cmode = Parameter(prhs[2]);
}
else {
cmode = NC_NOCLOBBER; /* Default. */
}
cdfid = nccreate(path, cmode);
plhs[0] = Int2Scalar(cdfid);
plhs[1] = Int2Scalar((cdfid >= 0) ? 0 : -1);
Free((VOIDPP) & path);
break;
case OPEN:
path = Mat2Str(prhs[1]);
if (nrhs > 2) {
mode = Parameter(prhs[2]);
}
else {
mode = NC_NOWRITE; /* Default. */
}
cdfid = ncopen(path, mode);
plhs[0] = Int2Scalar(cdfid);
plhs[1] = Int2Scalar((cdfid >= 0) ? 0 : -1);
Free((VOIDPP) & path);
break;
case REDEF:
status = ncredef(cdfid);
plhs[0] = Int2Scalar(status);
break;
case ENDEF:
status = ncendef(cdfid);
plhs[0] = Int2Scalar(status);
break;
case CLOSE:
status = ncclose(cdfid);
plhs[0] = Int2Scalar(status);
break;
case INQUIRE:
status = ncinquire(cdfid, & ndims, & nvars, & natts, & recdim);
if (nlhs > 1) {
plhs[0] = Int2Scalar(ndims);
plhs[1] = Int2Scalar(nvars);
plhs[2] = Int2Scalar(natts);
plhs[3] = Int2Scalar(recdim);
plhs[4] = Int2Scalar(status);
}
else { /* Default to 1 x 5 row vector. */
plhs[0] = mxCreateFull(1, 5, REAL);
pr = mxGetPr(plhs[0]);
if (status == 0) {
pr[0] = (DOUBLE) ndims;
pr[1] = (DOUBLE) nvars;
pr[2] = (DOUBLE) natts;
pr[3] = (DOUBLE) recdim;
}
pr[4] = (DOUBLE) status;
}
break;
case SYNC:
status = ncsync(cdfid);
plhs[0] = Int2Scalar(status);
break;
case ABORT:
status = ncabort(cdfid);
plhs[0] = Int2Scalar(status);
break;
case DIMDEF:
name = Mat2Str(prhs[2]);
length = Parameter(prhs[3]);
dimid = ncdimdef(cdfid, name, length);
plhs[0] = Int2Scalar(dimid);
plhs[1] = Int2Scalar((dimid >= 0) ? 0 : dimid);
Free((VOIDPP) & name);
break;
case DIMID:
name = Mat2Str(prhs[2]);
dimid = ncdimid(cdfid, name);
plhs[0] = Int2Scalar(dimid);
plhs[1] = Int2Scalar((dimid >= 0) ? 0 : dimid);
Free((VOIDPP) & name);
break;
case DIMINQ:
name = (char *) mxCalloc(MAX_NC_NAME, sizeof(char));
status = ncdiminq(cdfid, dimid, name, & length);
plhs[0] = Str2Mat(name);
plhs[1] = Long2Scalar(length);
plhs[2] = Int2Scalar(status);
Free((VOIDPP) & name);
break;
case DIMRENAME:
name = Mat2Str(prhs[3]);
status = ncdimrename(cdfid, dimid, name);
plhs[0] = Int2Scalar(status);
Free((VOIDPP) & name);
break;
case VARDEF:
name = Mat2Str(prhs[2]);
datatype = (nc_type) Parameter(prhs[3]);
ndims = Scalar2Int(prhs[4]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -