bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
CSV_Obj.cc
1// CSV_Obj.cc
2
3// This file is part of bes, A C++ back-end server implementation framework
4// for the OPeNDAP Data Access Protocol.
5
6// Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7// Author: Stephan Zednik <zednik@ucar.edu> and Patrick West <pwest@ucar.edu>
8// and Jose Garcia <jgarcia@ucar.edu>
9//
10// This library is free software; you can redistribute it and/or
11// modify it under the terms of the GNU Lesser General Public
12// License as published by the Free Software Foundation; either
13// version 2.1 of the License, or (at your option) any later version.
14//
15// This library is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18// Lesser General Public License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23//
24// You can contact University Corporation for Atmospheric Research at
25// 3080 Center Green Drive, Boulder, CO 80301
26
27// (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
28// Please read the full copyright statement in the file COPYRIGHT_UCAR.
29//
30// Authors:
31// zednik Stephan Zednik <zednik@ucar.edu>
32// pwest Patrick West <pwest@ucar.edu>
33// jgarcia Jose Garcia <jgarcia@ucar.edu>
34
35#include <iostream>
36#include <sstream>
37#include <iomanip>
38
39#include "CSV_Obj.h"
40#include "CSV_Utils.h"
41
42#include <BESInternalError.h>
43#include <BESNotFoundError.h>
44#include <BESSyntaxUserError.h>
45
46#include <BESLog.h>
47
48using std::string;
49using std::ostream;
50using std::endl;
51using std::vector;
52using std::ostringstream;
53
54CSV_Obj::CSV_Obj()
55{
56 _reader = new CSV_Reader();
57 _header = new CSV_Header();
58 _data = new vector<CSV_Data*>();
59}
60
61CSV_Obj::~CSV_Obj()
62{
63 if (_reader) {
64 _reader->close();
65 delete _reader;
66 _reader = 0;
67 }
68 if (_header) {
69 delete _header;
70 _header = 0;
71 }
72 if (_data) {
73 CSV_Data *d = 0;
74 vector<CSV_Data*>::iterator i = _data->begin();
75 vector<CSV_Data*>::iterator e = _data->end();
76 while (i != e) {
77 d = (*i);
78 delete d;
79 _data->erase(i);
80 i = _data->begin();
81 e = _data->end();
82 }
83 delete _data;
84 _data = 0;
85 }
86}
87
88bool CSV_Obj::open(const string& filepath)
89{
90 return _reader->open(filepath);
91}
92
93void CSV_Obj::load()
94{
95 vector<string> txtLine;
96 bool OnHeader = true;
97 _reader->reset();
98 while (!_reader->eof()) {
99 _reader->get(txtLine);
100
101 if (OnHeader) {
102 if (_header->populate(&txtLine)) {
103 for (unsigned int i = 0; i < txtLine.size(); i++) {
104 _data->push_back(new CSV_Data());
105 }
106 }
107 OnHeader = false;
108 }
109 else if (!txtLine.empty()) {
110 int index = 0;
111 vector<CSV_Data *>::iterator it = _data->begin();
112 vector<CSV_Data *>::iterator et = _data->end();
113 for (; it != et; it++) {
114 CSV_Data *d = (*it);
115 try {
116 string token = txtLine.at(index);
117 CSV_Utils::slim(token);
118 CSV_Field *f = _header->getField(index);
119 if (!f) {
120 ostringstream err;
121 err << " Attempting to add value " << token << " to field " << index << ", field does not exist";
122 ERROR_LOG(err.str());
123 throw BESInternalError(err.str(), __FILE__, __LINE__);
124 }
125 d->insert(f, &token);
126 }
127 catch (const std::out_of_range &/*e*/) {
128 ostringstream err;
129 err << "Error in CSV dataset, too few data elements on line " << _reader->get_row_number();
130 // FIXME: Different on OSX and Linux << " (C++ Error: " << e.what() << ")";
131 ERROR_LOG(err.str());
132 throw BESSyntaxUserError(err.str(), __FILE__, __LINE__);
133 }
134 index++;
135 }
136 }
137 txtLine.clear();
138 }
139}
140
141void CSV_Obj::getFieldList(vector<string> &list)
142{
143 _header->getFieldList(list);
144}
145
146string CSV_Obj::getFieldType(const string& fieldName)
147{
148 return _header->getFieldType(fieldName);
149}
150
151int CSV_Obj::getRecordCount()
152{
153 CSV_Data* alphaField = _data->at(0);
154 string type = alphaField->getType();
155
156 if (type.compare(string(STRING)) == 0) {
157 return ((vector<string>*) alphaField->getData())->size();
158 }
159 else if (type.compare(string(FLOAT32)) == 0) {
160 return ((vector<float>*) alphaField->getData())->size();
161 }
162 else if (type.compare(string(FLOAT64)) == 0) {
163 return ((vector<double>*) alphaField->getData())->size();
164 }
165 else if (type.compare(string(INT16)) == 0) {
166 return ((vector<short>*) alphaField->getData())->size();
167 }
168 else if (type.compare(string(INT32)) == 0) {
169 return ((vector<int>*) alphaField->getData())->size();
170 }
171 else {
172 return -1;
173 }
174}
175
176void *
177CSV_Obj::getFieldData(const string& field)
178{
179 void *ret = 0;
180 CSV_Field *f = _header->getField(field);
181 if (f) {
182 int index = f->getIndex();
183 CSV_Data *d = _data->at(index);
184 if (d) {
185 ret = d->getData();
186 }
187 else {
188 string err = (string) "Unable to get data for field " + field;
189 throw BESInternalError(err, __FILE__, __LINE__);
190 }
191 }
192 else {
193 string err = (string) "Unable to get data for field " + field + ", no such field exists";
194 throw BESInternalError(err, __FILE__, __LINE__);
195 }
196 return ret;
197}
198
199vector<string> CSV_Obj::getRecord(const int rowNum)
200{
201 vector<string> record;
202 void* fieldData;
203 string type;
204
205 int maxRows = getRecordCount();
206 if (rowNum > maxRows) {
207 ostringstream err;
208 err << "Attempting to retrieve row " << rowNum << " of " << maxRows;
209 throw BESInternalError(err.str(), __FILE__, __LINE__);
210 }
211
212 vector<string> fieldList;
213 getFieldList(fieldList);
214 vector<string>::iterator it = fieldList.begin();
215 vector<string>::iterator et = fieldList.end();
216 for (; it != et; it++) {
217 string fieldName = (*it);
218 ostringstream oss;
219 fieldData = getFieldData(fieldName);
220 CSV_Field *f = _header->getField(fieldName);
221 if (!f) {
222 ostringstream err;
223 err << "Unable to retrieve data for field " << fieldName << " on row " << rowNum;
224 throw BESInternalError(err.str(), __FILE__, __LINE__);
225 }
226 type = f->getType();
227
228 if (type.compare(string(STRING)) == 0) {
229 record.push_back(((vector<string>*) fieldData)->at(rowNum));
230 }
231 else if (type.compare(string(FLOAT32)) == 0) {
232 oss << ((vector<float>*) fieldData)->at(rowNum);
233 record.push_back(oss.str());
234 }
235 else if (type.compare(string(FLOAT64)) == 0) {
236 oss << ((vector<double>*) fieldData)->at(rowNum);
237 record.push_back(oss.str());
238 }
239 else if (type.compare(string(INT16)) == 0) {
240 oss << ((vector<short>*) fieldData)->at(rowNum);
241 record.push_back(oss.str());
242 }
243 else if (type.compare(string(INT32)) == 0) {
244 oss << ((vector<int>*) fieldData)->at(rowNum);
245 record.push_back(oss.str());
246 }
247 }
248
249 return record;
250}
251
252void CSV_Obj::dump(ostream &strm) const
253{
254 strm << BESIndent::LMarg << "CSV_Obj::dump - (" << (void *) this << ")" << endl;
255 BESIndent::Indent();
256 if (_reader) {
257 strm << BESIndent::LMarg << "reader:" << endl;
258 BESIndent::Indent();
259 _reader->dump(strm);
260 BESIndent::UnIndent();
261 }
262 if (_header) {
263 strm << BESIndent::LMarg << "header:" << endl;
264 BESIndent::Indent();
265 _header->dump(strm);
266 BESIndent::UnIndent();
267 }
268 if (_data) {
269 strm << BESIndent::LMarg << "data:" << endl;
270 }
271 BESIndent::UnIndent();
272}
273
virtual void dump(std::ostream &strm) const
dump the contents of this object to the specified ostream
Definition CSV_Obj.cc:252
static void slim(std::string &str)
Strips leading and trailing double quotes from string.
Definition CSV_Utils.cc:72
STL class.