~ubuntu-branches/ubuntu/wily/octave-miscellaneous/wily

« back to all changes in this revision

Viewing changes to src/csv2cell.cc

  • Committer: Package Import Robot
  • Author(s): Sébastien Villemot
  • Date: 2012-10-17 13:40:55 UTC
  • mfrom: (1.1.6)
  • mto: (5.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 13.
  • Revision ID: package-import@ubuntu.com-20121017134055-e8lrxjd3qgcd3kmt
Tags: upstream-1.2.0
Import upstream version 1.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2004 Laurent Mazet
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify
5
 
 * it under the terms of the GNU General Public License as published by
6
 
 * the Free Software Foundation; either version 2 of the License, or
7
 
 * (at your option) any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; If not, see <http://www.gnu.org/licenses/>.
16
 
 */
17
 
 
18
 
/* 2004-04-08
19
 
 *   initial release
20
 
 */
21
 
 
22
 
#include <fstream>
23
 
 
24
 
#include <octave/oct.h>
25
 
#include <octave/Cell.h>
26
 
 
27
 
#define MAXSTRINGLENGTH 4096
28
 
 
29
 
DEFUN_DLD (csv2cell, args, nargout, 
30
 
           "-*- texinfo -*-\n"
31
 
           "@deftypefn {Function File} {@var{c} = } csv2cell (@var{file})\n"
32
 
           "@deftypefnx {Function File} {@var{c} = } csv2cell (@var{file}, @var{sep})\n"
33
 
           "@deftypefnx {Function File} {@var{c} = } csv2cell (@var{file}, @var{sep}, @var{prot})\n"
34
 
           "\n"
35
 
           "Read a CSV (Comma Separated Values) file and convert it into a "
36
 
           "cell. "
37
 
           "@var{sep} changes the character used to separate two fields. By "
38
 
           "default, two fields are expected to be separated by a coma "
39
 
           "(@code{,}). @var{prot} changes the character used to protect a string. "
40
 
           "By default it's a double quote (@code{\"}).\n"
41
 
           "@end deftypefn") {
42
 
 
43
 
  /* Get arguments */
44
 
  std::string file = args(0).string_value();
45
 
 
46
 
  std::string _sep = (args.length() > 1) ? args(1).string_value() : ",";
47
 
  if (_sep.length() != 1) {
48
 
    error("only on charactere need as separator\n");
49
 
    return octave_value();
50
 
  }
51
 
  char sep = _sep[0];
52
 
 
53
 
  std::string _prot = (args.length() > 2) ? args(2).string_value() : "\"";
54
 
  if (_prot.length() != 1) {
55
 
    error("only on charactere need as protector\n");
56
 
    return octave_value();
57
 
  }
58
 
  char prot = _prot[0];
59
 
 
60
 
  /* Open file */
61
 
  std::ifstream fd(file.c_str());
62
 
  if (!fd.is_open()) {
63
 
    error("cannot read %s\n", file.c_str());
64
 
    return octave_value();
65
 
  }
66
 
  fd.seekg (0, std::ios::end);
67
 
  long fdend = fd.tellg();
68
 
  fd.seekg (0, std::ios::beg);
69
 
 
70
 
  /* Buffers */
71
 
  char line[MAXSTRINGLENGTH];
72
 
  std::string str, word;
73
 
  bool inside = false;
74
 
 
75
 
  /* Read a line */
76
 
  str = "";
77
 
  fd.getline(line, MAXSTRINGLENGTH);
78
 
  while (fd.fail()) {
79
 
    fd.clear();
80
 
    str += line;
81
 
    fd.getline(line, MAXSTRINGLENGTH);
82
 
  }
83
 
  str += line;
84
 
 
85
 
  /* Parse first to get number of columns */
86
 
  int nbcolumns = 0;
87
 
  for (int i=0, len=str.length(); i<=len; i++)
88
 
    if (((i==len) || (str[i] == sep)) && (!inside))
89
 
      nbcolumns++;
90
 
    else if ((inside) && (str[i]==prot) && ((i<len) && (str[i+1]==prot)))
91
 
      ++i;
92
 
    else if (str[i] == prot)
93
 
      inside = !inside;
94
 
  
95
 
  /* Read all the file to get number of rows */
96
 
  int nbrows = 1;
97
 
  while (fd.tellg() < fdend) {
98
 
    fd.getline(line, MAXSTRINGLENGTH);
99
 
    while (fd.fail()) {
100
 
      fd.clear();
101
 
      fd.getline(line, MAXSTRINGLENGTH);
102
 
    }
103
 
    nbrows++;
104
 
  }
105
 
 
106
 
  /* Rewind */
107
 
  fd.seekg (0, std::ios::beg);
108
 
  if (!fd.good()) {
109
 
    error("cannot reread %s\n", file.c_str());
110
 
    return octave_value();
111
 
  }
112
 
 
113
 
  /* Read all the file until the end */
114
 
  Cell c(nbrows, nbcolumns);
115
 
  for (int i=0; i<nbrows; i++) {
116
 
    
117
 
    /* Read a line */
118
 
    str = "";
119
 
    fd.getline(line, MAXSTRINGLENGTH);
120
 
    while (fd.fail()) {
121
 
      fd.clear();
122
 
      str += line;
123
 
      fd.getline(line, MAXSTRINGLENGTH);
124
 
    }
125
 
    str += line;
126
 
 
127
 
    /* Explode a line into a sub cell */
128
 
    word = "";
129
 
    inside = false;
130
 
    int j = 0;
131
 
    for (int k=0, len=str.length(); k<=len; k++) {
132
 
      if (((k==len) || (str[k] == sep)) && (!inside)) {
133
 
 
134
 
        /* Check number of columns */
135
 
        if (j == nbcolumns) {
136
 
          fd.close();
137
 
          error("incorrect CSV file, line %d too long\n", i+1);
138
 
          return octave_value();
139
 
        }
140
 
 
141
 
        /* Check if scalar */
142
 
        const char *word_str=word.c_str();
143
 
        char *err;
144
 
        double val = strtod (word_str, &err);
145
 
 
146
 
        /* Store into the cell */
147
 
        c(i, j++) = ((word == "") || (err != word_str+word.length())) ?
148
 
          octave_value(word) : octave_value(val);
149
 
        word = "";
150
 
      }
151
 
      else if ((inside) && (str[k]==prot) && ((k<len) && (str[k+1]==prot))) {
152
 
 
153
 
        /* Insisde a string */
154
 
        word += prot;
155
 
        ++k;
156
 
      }
157
 
      else if (str[k] == prot)
158
 
        /* Changing */
159
 
        inside = !inside;
160
 
      else
161
 
        word += str[k];
162
 
    }
163
 
 
164
 
    /* Check number of columns */
165
 
    if (j != nbcolumns) {
166
 
      fd.close();
167
 
      error("incorrect CSV file, line %d too short\n", i+1);
168
 
      return octave_value();
169
 
    }
170
 
  }
171
 
 
172
 
  /* Close file */
173
 
  fd.close();
174
 
 
175
 
  return octave_value(c);
176
 
}