234 строки
5.2 KiB
Plaintext
234 строки
5.2 KiB
Plaintext
% Simple ascii file reader
|
|
% Copyright (C) 2007-2017,2018 John E. Davis
|
|
%
|
|
% This file is part of the S-Lang Library and may be distributed under the
|
|
% terms of the GNU General Public License. See the file COPYING for
|
|
% more information.
|
|
|
|
private define allocate_array_of_arrays (list, num)
|
|
{
|
|
variable n = length (list);
|
|
variable array_list = Array_Type[n];
|
|
_for (0, n-1, 1)
|
|
{
|
|
variable j = ();
|
|
array_list[j] = typeof(list[j])[num];
|
|
}
|
|
return array_list;
|
|
}
|
|
|
|
define readascii ()
|
|
{
|
|
if (_NARGS < 2)
|
|
{
|
|
usage ("nrows = %s (file, &a1,...; qualifiers);\nQualifiers:\n"
|
|
+ "nrows=int, ncols=int, format=string, skip=int, maxlines=int, delim=string\n"
|
|
+ "size=int, dsize=int, stop_on_mismatch, lastline=&var lastlinenum=&var\n"
|
|
+ "type=string, cols=array, comment=string, as_list\n",
|
|
_function_name);
|
|
}
|
|
|
|
variable nrows = qualifier ("nrows", NULL);
|
|
variable ncols = qualifier ("ncols", NULL);
|
|
variable fmt = qualifier ("format", NULL);
|
|
variable skip = qualifier ("skip", 0);
|
|
variable maxlines = qualifier ("maxlines", NULL);
|
|
variable delim = qualifier ("delim", " ");
|
|
variable init_size = qualifier("size", NULL);
|
|
variable dsize = qualifier ("dsize", NULL);
|
|
variable stop_on_mismatch = qualifier_exists ("stop_on_mismatch");
|
|
variable linep = qualifier ("lastline", NULL);
|
|
variable linenump = qualifier ("lastlinenum", NULL);
|
|
variable comment = qualifier ("comment", NULL);
|
|
variable want_columns = qualifier("cols", NULL);
|
|
variable type=qualifier("type", "lf"); % Double_Type
|
|
variable is_list = qualifier_exists ("as_list");
|
|
|
|
if (comment != NULL)
|
|
variable comment_len = strbytelen (comment);
|
|
|
|
if (skip < 0)
|
|
skip = 0;
|
|
|
|
variable has_ncols_qualifier = 0;
|
|
variable arg_refs;
|
|
|
|
if (ncols != NULL)
|
|
{
|
|
has_ncols_qualifier = 1;
|
|
if (_NARGS != 2)
|
|
throw UsageError, "The ncols qualifier is incompatible with more than one reference arg";
|
|
arg_refs = ();
|
|
}
|
|
else
|
|
{
|
|
arg_refs = __pop_list (_NARGS-1);
|
|
ncols = length (arg_refs);
|
|
}
|
|
variable fp = ();
|
|
|
|
if (want_columns != NULL)
|
|
ncols = length (want_columns);
|
|
|
|
if (fmt == NULL)
|
|
{
|
|
type = strtrim_beg (type, "%");
|
|
if (want_columns != NULL)
|
|
{
|
|
fmt = String_Type[max(want_columns)];
|
|
fmt[*] = strcat ("%*", type);
|
|
fmt[want_columns-1] = strcat ("%", type);
|
|
}
|
|
else
|
|
{
|
|
fmt = String_Type[ncols];
|
|
fmt[*] = strcat ("%", type);
|
|
}
|
|
|
|
fmt = strjoin (fmt, delim);
|
|
}
|
|
|
|
variable fp_is_array = 0;
|
|
switch (typeof (fp))
|
|
{
|
|
case Array_Type or case List_Type:
|
|
if ((maxlines == NULL) || (maxlines > length (fp)))
|
|
maxlines = length (fp);
|
|
fp_is_array = 1;
|
|
}
|
|
{
|
|
case File_Type:
|
|
}
|
|
{
|
|
% default:
|
|
variable file = fp;
|
|
fp = fopen (file, "r");
|
|
if (fp == NULL)
|
|
throw IOError, "Unable to open $file"$;
|
|
}
|
|
|
|
if (nrows == NULL)
|
|
nrows = -1;
|
|
else if (nrows < 0)
|
|
nrows = 0;
|
|
|
|
if (init_size == NULL)
|
|
{
|
|
if ((nrows != NULL) && (nrows > 0))
|
|
init_size = nrows;
|
|
else if (fp_is_array)
|
|
init_size = maxlines;
|
|
else
|
|
init_size = 0x8000;
|
|
}
|
|
|
|
if (dsize == NULL)
|
|
dsize = init_size;
|
|
|
|
variable array_list = NULL;
|
|
variable max_allocated = 0;
|
|
variable i, k, nitems = 0;
|
|
|
|
% Create a list of references that can be passed to sscanf
|
|
variable ref_list = {}, ref_buf = {};
|
|
_for i (0, ncols-1, 1)
|
|
{
|
|
list_append (ref_buf, 1);
|
|
list_append (ref_list, &ref_buf[i]);
|
|
}
|
|
|
|
% If arrays are to be returned, the array_list is an array of arrays
|
|
% Otherwise, is_list is non-zero, and array_list is a list of lists.
|
|
if (is_list)
|
|
{
|
|
array_list = {};
|
|
_for i (0, ncols-1, 1)
|
|
list_append (array_list, {});
|
|
}
|
|
|
|
variable nlines = 0;
|
|
variable line = NULL;
|
|
variable comment_char = (comment != NULL) ? comment[0] : 0;
|
|
|
|
while ((nitems != nrows) && (nlines != maxlines))
|
|
{
|
|
if (fp_is_array)
|
|
line = fp[nlines];
|
|
else if (-1 == fgets (&line, fp))
|
|
break;
|
|
|
|
nlines++;
|
|
|
|
if (skip)
|
|
{
|
|
skip--;
|
|
continue;
|
|
}
|
|
|
|
if ((comment_char == line[0])
|
|
&& (0 == strnbytecmp (comment, line, comment_len)))
|
|
continue;
|
|
|
|
if (ncols != sscanf (line, fmt, __push_list(ref_list)))
|
|
{
|
|
if (stop_on_mismatch)
|
|
break;
|
|
|
|
continue;
|
|
}
|
|
|
|
if (is_list)
|
|
{
|
|
_for i (0, ncols-1, 1)
|
|
{
|
|
list_append (array_list[i], ref_buf[i]);
|
|
}
|
|
nitems++;
|
|
continue;
|
|
}
|
|
|
|
ifnot (max_allocated)
|
|
{
|
|
max_allocated = init_size;
|
|
array_list = allocate_array_of_arrays (ref_buf, max_allocated);
|
|
}
|
|
|
|
if (nitems == max_allocated)
|
|
{
|
|
max_allocated += dsize;
|
|
variable new_array_list = allocate_array_of_arrays (ref_buf, max_allocated);
|
|
k = [0:nitems-1];
|
|
_for i (0, ncols-1, 1)
|
|
new_array_list[i][k] = array_list[i];
|
|
array_list = new_array_list;
|
|
}
|
|
|
|
_for i (0, ncols-1, 1)
|
|
array_list[i][nitems] = ref_buf[i];
|
|
|
|
nitems++;
|
|
}
|
|
|
|
if (nitems)
|
|
{
|
|
if ((is_list == 0) && (max_allocated != nitems))
|
|
{
|
|
k = [0:nitems-1];
|
|
_for i (0, ncols-1, 1)
|
|
array_list[i] = array_list[i][k];
|
|
}
|
|
|
|
if (has_ncols_qualifier)
|
|
@arg_refs = array_list;
|
|
else _for i (0, ncols-1, 1)
|
|
@arg_refs[i] = array_list[i];
|
|
}
|
|
|
|
if (linep != NULL)
|
|
@linep = line;
|
|
if (linenump != NULL)
|
|
@linenump = nlines;
|
|
|
|
return nitems;
|
|
}
|