Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
csv.cpp
Go to the documentation of this file.
1 #include "csv.h"
2 #include "vsfilesystem.h"
3 
4 using std::string;
5 
6 vector< string > readCSV( string s, string delim )
7 {
8  vector< string >l;
9  string as;
10  unsigned int epos = 0;
11  unsigned int sl = s.length();
12  bool insert;
13  bool quote = false;
14  char ddelim = 0;
15  while ( (epos < sl) && !( (s[epos] == '\r') || (s[epos] == '\n') ) ) {
16  insert = true;
17  if (quote) {
18  if (s[epos] == '\"') {
19  if ( (epos+1 < sl) && (s[epos+1] == '\"') )
20  epos++;
21 
22  else
23  quote = insert = false;
24  }
25  } else {
26  bool ep;
27  if (!ddelim) {
28  size_t dp = delim.find( s[epos] );
29  if (dp != string::npos) ddelim = delim[dp];
30  ep = (dp != string::npos);
31  } else {
32  ep = s[epos] == ddelim;
33  }
34 
35  if (ep) {
36  insert = false;
37  l.push_back( as );
38  as.erase();
39  } else if (s[epos] == '\"') {
40  if ( (epos+1 < sl) && (s[epos+1] == '\"') )
41  epos++;
42  else
43  insert = !(quote = true);
44  }
45  }
46  if ( insert && (epos < sl) ) as += s[epos];
47  epos++;
48  }
49  if ( !as.empty() ) l.push_back( as );
50  return l;
51 }
52 
53 static string addQuote( string s, string delim = ",;" )
54 {
55  if (s.find_first_of( delim+"\"" ) != string::npos) {
56  if (s.find( '\"' ) != string::npos) {
57  //Replace " by ""
58  string as;
59  int sl = s.length();
60  as.reserve( 2*sl );
61  for (int i = 0; i < sl; i++)
62  if (s[i] != '\"') as += s[i];
63 
64  else as += "\"\"";
65  s.swap( as );
66  }
67  //Add single quotes to the sides
68  s.insert( s.begin(), 1, '\"' );
69  s.insert( s.end(), 1, '\"' );
70  }
71  return s;
72 }
73 
74 string writeCSV( const vector< string > &key, const vector< string > &table, string delim )
75 {
76  unsigned int i;
77  unsigned int wid = key.size();
78  string ret;
79  for (i = 0; i < wid; ++i) {
80  ret += addQuote( key[i], delim );
81  if (i+1 < wid)
82  ret += delim[0];
83  }
84  ret += '\n';
85  for (i = 0; i < table.size(); ++i) {
86  ret += addQuote( table[i], delim );
87  if (i+1%wid == 0)
88  ret += '\n';
89  else
90  ret += delim[0];
91  }
92  return ret;
93 }
94 
95 void CSVTable::Init( string data )
96 {
97  //Clear optimizer
98  optimizer_setup = false;
99  optimizer_keys.clear();
100  optimizer_indexes.clear();
101  optimizer_type = ~0;
102  const string delim( ",;" );
103  const char *cdata = data.c_str();
104  const char *csep = strchr( cdata, '\n' );
105  if (csep == NULL) return;
106  string buffer( cdata, csep-cdata );
107  cdata = csep+1;
108  key = readCSV( buffer, delim );
109  for (unsigned int i = 0; i < key.size(); i++)
110  columns[key[i]] = i;
111  while (cdata && *cdata) {
112  csep = strchr( cdata, '\n' );
113  if (csep == NULL)
114  buffer.assign( cdata );
115 
116  else
117  buffer.assign( cdata, csep-cdata );
118  if (csep == NULL)
119  cdata = NULL;
120 
121  else
122  cdata = csep+1;
123  vector< string >strs = readCSV( buffer );
124  unsigned int row = table.size()/key.size();
125  while ( strs.size() > key.size() ) {
126  fprintf( stderr, "error in csv, line %d: %s has no key", row+1, strs.back().c_str() );
127  strs.pop_back();
128  }
129  while ( strs.size() < key.size() )
130  strs.push_back( "" );
131  assert( strs.size() == key.size() );
132  table.insert( table.end(), strs.begin(), strs.end() );
133  if ( strs.size() )
134  rows[strs[0]] = row;
135 
136  else
137  table.pop_back();
138  }
139 }
140 
141 CSVTable::CSVTable( string data, string root )
142 {
143  this->rootdir = root;
144  Init( data );
145 }
146 
147 CSVTable::CSVTable( VSFileSystem::VSFile &f, string root )
148 {
149  this->rootdir = root;
150  Init( f.ReadFull() );
151 }
152 
153 CSVRow::CSVRow( CSVTable *parent, string key )
154 {
155  this->parent = parent;
156  iter = parent->rows[key]*parent->key.size();
157 }
158 
159 CSVRow::CSVRow( CSVTable *parent, unsigned int i )
160 {
161  this->parent = parent;
162  iter = i*parent->key.size();
163 }
164 
165 const string& CSVRow::operator[]( const string &col ) const
166 {
167  static string empty_string;
168  vsUMap< string, int >::iterator i = parent->columns.find( col );
169  if ( i == parent->columns.end() )
170  return empty_string;
171 
172  else
173  return parent->table[iter+(*i).second];
174 }
175 
176 const string& CSVRow::operator[]( unsigned int col ) const
177 {
178  return parent->table[iter+col];
179 }
180 
181 const string& CSVRow::getKey( unsigned int which ) const
182 {
183  return parent->key[which];
184 }
185 
186 bool CSVTable::RowExists( string name, unsigned int &where )
187 {
188  vsUMap< string, int >::iterator i = rows.find( name );
189  if ( i == rows.end() )
190  return false;
191  where = (*i).second;
192  return true;
193 }
194 
195 bool CSVTable::ColumnExists( string name, unsigned int &where )
196 {
197  vsUMap< string, int >::iterator i = columns.find( name );
198  if ( i == columns.end() )
199  return false;
200  where = (*i).second;
201  return true;
202 }
203 
204 vector< CSVTable* > unitTables;
205 
207 {
208  if (parent)
209  return parent->rootdir;
210  fprintf( stderr, "Error getting root for unit\n" );
211  return "";
212 }
213 
214 void CSVTable::SetupOptimizer( vector< string > keys, unsigned int type )
215 {
216  optimizer_setup = true;
217  optimizer_type = type;
218  optimizer_keys = keys;
219  optimizer_indexes.resize( keys.size(), CSVTable::optimizer_undefined );
220  for (unsigned int i = 0; i < keys.size(); ++i)
221  ColumnExists( keys[i], optimizer_indexes[i] );
222 }
223