dlvhex
2.5.0
|
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: