dlvhex  2.5.0
src/InputProvider.cpp
Go to the documentation of this file.
00001 /* dlvhex -- Answer-Set Programming with external interfaces.
00002  * Copyright (C) 2005-2007 Roman Schindlauer
00003  * Copyright (C) 2006-2015 Thomas Krennwallner
00004  * Copyright (C) 2009-2016 Peter Schüller
00005  * Copyright (C) 2011-2016 Christoph Redl
00006  * Copyright (C) 2015-2016 Tobias Kaminski
00007  * Copyright (C) 2015-2016 Antonius Weinzierl
00008  *
00009  * This file is part of dlvhex.
00010  *
00011  * dlvhex is free software; you can redistribute it and/or modify it
00012  * under the terms of the GNU Lesser General Public License as
00013  * published by the Free Software Foundation; either version 2.1 of
00014  * the License, or (at your option) any later version.
00015  *
00016  * dlvhex is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with dlvhex; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00035 #ifdef HAVE_CONFIG_H
00036 #include "config.h"
00037 #endif                           // HAVE_CONFIG_H
00038 
00039 #include "dlvhex2/InputProvider.h"
00040 #include "dlvhex2/URLBuf.h"
00041 #include "dlvhex2/Error.h"
00042 
00043 #include <cassert>
00044 #include <fstream>
00045 #include <sstream>
00046 
00047 DLVHEX_NAMESPACE_BEGIN
00048 
00049 WARNING("TODO use boost::iostream::chain or something similar to create real streaming/incremental input provider")
00050 
00051 class InputProvider::Impl
00052 {
00053     public:
00054         std::stringstream stream;
00055         std::vector<std::string> contentNames;
00056 
00057     public:
00058         Impl() {
00059         }
00060 };
00061 
00062 InputProvider::InputProvider():
00063 pimpl(new Impl)
00064 {
00065 }
00066 
00067 
00068 InputProvider::~InputProvider()
00069 {
00070 }
00071 
00072 
00073 void InputProvider::addStreamInput(std::istream& i, const std::string& contentname)
00074 {
00075     // read the input before adding it to pimpl->stream (otherwise empty input seems to make the overall stream corrupt)
00076     std::stringstream inp;
00077     inp << i.rdbuf();
00078     pimpl->stream << inp.str();
00079     pimpl->contentNames.push_back(contentname);
00080 }
00081 
00082 
00083 void InputProvider::addStringInput(const std::string& content, const std::string& contentname)
00084 {
00085     pimpl->stream << content;
00086     pimpl->contentNames.push_back(contentname);
00087 }
00088 
00089 
00090 void InputProvider::addFileInput(const std::string& filename)
00091 {
00092     std::ifstream ifs;
00093     ifs.open(filename.c_str());
00094 
00095     if (!ifs.is_open()) {
00096         throw GeneralError("File " + filename + " not found");
00097     }
00098 
00099     pimpl->stream << ifs.rdbuf();
00100     ifs.close();
00101     pimpl->contentNames.push_back(filename);
00102 }
00103 
00104 void InputProvider::addCSVFileInput(const std::string& predicate, const std::string& filename)
00105 {
00106     std::ifstream ifs;
00107     ifs.open(filename.c_str());
00108 
00109     std::string line;
00110     int lineNr = 0;
00111     while (std::getline(ifs, line)) {
00112         // replace unquoted semicolons by commas
00113         bool firstChar = true;
00114         bool addQuotes = false;
00115         bool escaped = false;
00116         pimpl->stream << predicate << "(" << lineNr << ",";
00117         for (int i = 0; i <= line.length(); ++i){
00118             // decide type of argument
00119             if (firstChar && !(line[i] >= '0' && line[i] <= '9')) {
00120                 addQuotes = true;
00121                 pimpl->stream << "\"";
00122             }
00123             firstChar = false;
00124 
00125             // detect end of argument
00126             if ((line[i] == ';' || line[i] == 0) && !escaped){
00127                 if (addQuotes) pimpl->stream << "\"";
00128                 if (line[i] != 0) pimpl->stream << ",";
00129                 addQuotes = false;
00130                 firstChar = true;
00131             }
00132 
00133             // escape sequence
00134             else if (line[i] == '\\' && !escaped) {
00135                 pimpl->stream << line[i];
00136                 escaped = true;
00137             }
00138 
00139             // output ordinary character
00140             else if (line[i] != 0){
00141                 pimpl->stream << line[i];
00142                 escaped = false;
00143             }
00144         }
00145         // construct fact for this line
00146         pimpl->stream << ").";
00147 
00148         ++lineNr;
00149     }
00150 
00151     ifs.close();
00152     pimpl->contentNames.push_back(filename);
00153 }
00154 
00155 #ifdef HAVE_CURL
00156 void InputProvider::addURLInput(const std::string& url)
00157 {
00158     assert(url.find("http://") == 0 && "currently only processing http:// URLs");
00159 
00160     URLBuf ubuf;
00161     ubuf.open(url);
00162     std::istream is(&ubuf);
00163 
00164     pimpl->stream << is.rdbuf();
00165 
00166     if (ubuf.responsecode() == 404) {
00167         throw GeneralError("Requested URL " + url + " was not found");
00168     }
00169 
00170     pimpl->contentNames.push_back(url);
00171 }
00172 #endif
00173 
00174 bool InputProvider::hasContent() const
00175 {
00176     return !pimpl->contentNames.empty();
00177 }
00178 
00179 
00180 const std::vector<std::string>& InputProvider::contentNames() const
00181 {
00182     return pimpl->contentNames;
00183 }
00184 
00185 
00186 std::istream& InputProvider::getAsStream()
00187 {
00188     assert(hasContent() && "should have gotten some content before using content");
00189     return pimpl->stream;
00190 }
00191 
00192 
00193 DLVHEX_NAMESPACE_END
00194 
00195 // vim:expandtab:ts=4:sw=4:
00196 // mode: C++
00197 // End: