LCOV - code coverage report
Current view: top level - slsh/lib - readascii.sl (source / functions) Hit Total Coverage
Test: all.lcov Lines: 121 131 92.4 %
Date: 2022-08-02 14:41:00 Functions: 2 2 100.0 %

          Line data    Source code
       1             : % Simple ascii file reader
       2             : % Copyright (C) 2007-2021,2022 John E. Davis
       3             : %
       4             : % This file is part of the S-Lang Library and may be distributed under the
       5             : % terms of the GNU General Public License.  See the file COPYING for
       6             : % more information.
       7             : 
       8             : private define allocate_array_of_arrays (list, num)
       9             : {
      10          19 :    variable n = length (list);
      11          19 :    variable array_list = Array_Type[n];
      12          19 :    _for (0, n-1, 1)
      13             :      {
      14          54 :         variable j = ();
      15          54 :         array_list[j] = typeof(list[j])[num];
      16             :      }
      17          19 :    return array_list;
      18             : }
      19             : 
      20             : define readascii ()
      21             : {
      22          20 :    if (_NARGS < 2)
      23             :      {
      24           0 :         usage ("nrows = %s (file, &a1,...; qualifiers);\nQualifiers:\n"
      25             :                + "nrows=int, ncols=int, format=string, skip=int, maxlines=int, delim=string\n"
      26             :                + "size=int, dsize=int, stop_on_mismatch, lastline=&var lastlinenum=&var\n"
      27             :                + "type=string, cols=array, comment=string, as_list\n",
      28             :                _function_name);
      29             :      }
      30             : 
      31          20 :    variable nrows = qualifier ("nrows", NULL);
      32          20 :    variable ncols = qualifier ("ncols", NULL);
      33          20 :    variable fmt = qualifier ("format", NULL);
      34          20 :    variable skip = qualifier ("skip", 0);
      35          20 :    variable maxlines = qualifier ("maxlines", NULL);
      36          20 :    variable delim = qualifier ("delim", " ");
      37          20 :    variable init_size = qualifier("size", NULL);
      38          20 :    variable dsize = qualifier ("dsize", NULL);
      39          20 :    variable stop_on_mismatch = qualifier_exists ("stop_on_mismatch");
      40          20 :    variable linep = qualifier ("lastline", NULL);
      41          20 :    variable linenump = qualifier ("lastlinenum", NULL);
      42          20 :    variable comment = qualifier ("comment", NULL);
      43          20 :    variable want_columns = qualifier("cols", NULL);
      44          20 :    variable type=qualifier("type", "lf");   % Double_Type
      45          20 :    variable is_list = qualifier_exists ("as_list");
      46             : 
      47          20 :    if (comment != NULL)
      48           9 :      variable comment_len = strbytelen (comment);
      49             : 
      50          20 :    if (skip < 0)
      51           0 :      skip = 0;
      52             : 
      53          20 :    variable has_ncols_qualifier = 0;
      54             :    variable arg_refs;
      55             : 
      56          20 :    if (ncols != NULL)
      57             :      {
      58           2 :         has_ncols_qualifier = 1;
      59           2 :         if (_NARGS != 2)
      60           0 :           throw UsageError, "The ncols qualifier is incompatible with more than one reference arg";
      61           2 :         arg_refs = ();
      62             :      }
      63             :    else
      64             :      {
      65          18 :         arg_refs = __pop_list (_NARGS-1);
      66          18 :         ncols = length (arg_refs);
      67             :      }
      68          20 :    variable fp = ();
      69             : 
      70          20 :    if (want_columns != NULL)
      71           6 :      ncols = length (want_columns);
      72             : 
      73          20 :    if (fmt == NULL)
      74             :      {
      75          20 :         type = strtrim_beg (type, "%");
      76          20 :         if (want_columns != NULL)
      77             :           {
      78           6 :              fmt = String_Type[max(want_columns)];
      79           6 :              fmt[*] = strcat ("%*", type);
      80           6 :              fmt[want_columns-1] = strcat ("%", type);
      81             :           }
      82             :         else
      83             :           {
      84          14 :              fmt = String_Type[ncols];
      85          14 :              fmt[*] = strcat ("%", type);
      86             :           }
      87             : 
      88          20 :         fmt = strjoin (fmt, delim);
      89             :      }
      90             : 
      91          20 :    variable fp_is_array = 0;
      92          20 :    switch (typeof (fp))
      93             :      {
      94          20 :       case Array_Type or case List_Type:
      95          18 :         if ((maxlines == NULL) || (maxlines > length (fp)))
      96          18 :           maxlines = length (fp);
      97          18 :         fp_is_array = 1;
      98             :      }
      99             :      {
     100           2 :       case File_Type:
     101             :      }
     102             :      {
     103             :         % default:
     104           2 :         variable file = fp;
     105           2 :         fp = fopen (file, "r");
     106           2 :         if (fp == NULL)
     107           0 :           throw IOError, "Unable to open $file"$;
     108             :      }
     109             : 
     110          20 :    if (nrows == NULL)
     111          20 :      nrows = -1;
     112           0 :    else if (nrows < 0)
     113           0 :      nrows = 0;
     114             : 
     115          20 :    if (init_size == NULL)
     116             :      {
     117          18 :         if ((nrows != NULL) && (nrows > 0))
     118           0 :           init_size = nrows;
     119          18 :         else if (fp_is_array)
     120          18 :           init_size = maxlines;
     121             :         else
     122           0 :           init_size = 0x8000;
     123             :      }
     124             : 
     125          20 :    if (dsize == NULL)
     126          18 :      dsize = init_size;
     127             : 
     128          20 :    variable array_list = NULL;
     129          20 :    variable max_allocated = 0;
     130          20 :    variable i, k, nitems = 0;
     131             : 
     132             :    % Create a list of references that can be passed to sscanf
     133          40 :    variable ref_list = {}, ref_buf = {};
     134          20 :    _for i (0, ncols-1, 1)
     135             :      {
     136          54 :         list_append (ref_buf, 1);
     137          54 :         list_append (ref_list, &ref_buf[i]);
     138             :      }
     139             : 
     140             :    % If arrays are to be returned, the array_list is an array of arrays
     141             :    % Otherwise, is_list is non-zero, and array_list is a list of lists.
     142          20 :    if (is_list)
     143             :      {
     144           3 :         array_list = {};
     145           3 :         _for i (0, ncols-1, 1)
     146           6 :           list_append (array_list, {});
     147             :      }
     148             : 
     149          20 :    variable nlines = 0;
     150          20 :    variable line = NULL;
     151          20 :    variable comment_char = (comment != NULL) ? comment[0] : 0;
     152             : 
     153         438 :    while ((nitems != nrows) && (nlines != maxlines))
     154             :      {
     155         432 :         if (fp_is_array)
     156         408 :           line = fp[nlines];
     157          24 :         else if (-1 == fgets (&line, fp))
     158           2 :           break;
     159             : 
     160         430 :         nlines++;
     161             : 
     162         430 :         if (skip)
     163             :           {
     164           0 :              skip--;
     165           0 :              continue;
     166             :           }
     167             : 
     168         430 :         if ((comment_char == line[0])
     169             :             && (0 == strnbytecmp (comment, line, comment_len)))
     170           9 :           continue;
     171             : 
     172         421 :         if (ncols != sscanf (line, fmt, __push_list(ref_list)))
     173             :           {
     174          15 :              if (stop_on_mismatch)
     175          12 :                break;
     176             : 
     177           3 :              continue;
     178             :           }
     179             : 
     180         406 :         if (is_list)
     181             :           {
     182          66 :              _for i (0, ncols-1, 1)
     183             :                {
     184         132 :                   list_append (array_list[i], ref_buf[i]);
     185             :                }
     186          66 :              nitems++;
     187          66 :              continue;
     188             :           }
     189             : 
     190         340 :         ifnot (max_allocated)
     191             :           {
     192          17 :              max_allocated = init_size;
     193          17 :              array_list = allocate_array_of_arrays (ref_buf, max_allocated);
     194             :           }
     195             : 
     196         340 :         if (nitems == max_allocated)
     197             :           {
     198           2 :              max_allocated += dsize;
     199           2 :              variable new_array_list = allocate_array_of_arrays (ref_buf, max_allocated);
     200           2 :              k = [0:nitems-1];
     201           2 :              _for i (0, ncols-1, 1)
     202           6 :                new_array_list[i][k] = array_list[i];
     203           2 :              array_list = new_array_list;
     204             :           }
     205             : 
     206         340 :         _for i (0, ncols-1, 1)
     207         954 :           array_list[i][nitems] = ref_buf[i];
     208             : 
     209         340 :         nitems++;
     210             :      }
     211             : 
     212          20 :    if (nitems)
     213             :      {
     214          20 :         if ((is_list == 0) && (max_allocated != nitems))
     215             :           {
     216          14 :              k = [0:nitems-1];
     217          14 :              _for i (0, ncols-1, 1)
     218          39 :                array_list[i] = array_list[i][k];
     219             :           }
     220             : 
     221          20 :         if (has_ncols_qualifier)
     222           2 :           @arg_refs = array_list;
     223          18 :         else _for i (0, ncols-1, 1)
     224          48 :           @arg_refs[i] = array_list[i];
     225             :      }
     226             : 
     227          20 :    if (linep != NULL)
     228          12 :      @linep = line;
     229          20 :    if (linenump != NULL)
     230          18 :      @linenump = nlines;
     231             : 
     232          20 :    return nitems;
     233             : }

Generated by: LCOV version 1.13