Eclipse SUMO - Simulation of Urban MObility
OutputDevice.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2004-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 // Static storage of an output device and its base (abstract) implementation
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <map>
25 #include <fstream>
26 #include <sstream>
27 #include <string>
28 #include <iomanip>
29 #include "OutputDevice.h"
30 #include "OutputDevice_File.h"
31 #include "OutputDevice_COUT.h"
32 #include "OutputDevice_CERR.h"
33 #include "OutputDevice_Network.h"
34 #include "PlainXMLFormatter.h"
38 #include <utils/common/ToString.h>
41 
42 
43 // ===========================================================================
44 // static member definitions
45 // ===========================================================================
46 std::map<std::string, OutputDevice*> OutputDevice::myOutputDevices;
47 
48 
49 // ===========================================================================
50 // static method definitions
51 // ===========================================================================
53 OutputDevice::getDevice(const std::string& name) {
54  // check whether the device has already been aqcuired
55  if (myOutputDevices.find(name) != myOutputDevices.end()) {
56  return *myOutputDevices[name];
57  }
58  // build the device
59  OutputDevice* dev = nullptr;
60  // check whether the device shall print to stdout
61  if (name == "stdout") {
63  } else if (name == "stderr") {
65  } else if (FileHelpers::isSocket(name)) {
66  try {
67  int port = StringUtils::toInt(name.substr(name.find(":") + 1));
68  dev = new OutputDevice_Network(name.substr(0, name.find(":")), port);
69  } catch (NumberFormatException&) {
70  throw IOError("Given port number '" + name.substr(name.find(":") + 1) + "' is not numeric.");
71  } catch (EmptyData&) {
72  throw IOError("No port number given.");
73  }
74  } else {
75  const int len = (int)name.length();
76  std::string name2 = name;
77  if (OptionsCont::getOptions().isSet("output-prefix") && name != "/dev/null") {
78  std::string prefix = OptionsCont::getOptions().getString("output-prefix");
79  const std::string::size_type metaTimeIndex = prefix.find("TIME");
80  if (metaTimeIndex != std::string::npos) {
81  time_t rawtime;
82  char buffer [80];
83  time(&rawtime);
84  struct tm* timeinfo = localtime(&rawtime);
85  strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S", timeinfo);
86  prefix.replace(metaTimeIndex, 4, std::string(buffer));
87  }
88  name2 = FileHelpers::prependToLastPathComponent(prefix, name);
89  }
90  dev = new OutputDevice_File(name2, len > 3 && name.substr(len - 3) == ".gz");
91  }
92  dev->setPrecision();
93  dev->getOStream() << std::setiosflags(std::ios::fixed);
94  myOutputDevices[name] = dev;
95  return *dev;
96 }
97 
98 
99 bool
100 OutputDevice::createDeviceByOption(const std::string& optionName,
101  const std::string& rootElement,
102  const std::string& schemaFile) {
103  if (!OptionsCont::getOptions().isSet(optionName)) {
104  return false;
105  }
106  OutputDevice& dev = OutputDevice::getDevice(OptionsCont::getOptions().getString(optionName));
107  if (rootElement != "") {
108  dev.writeXMLHeader(rootElement, schemaFile);
109  }
110  return true;
111 }
112 
113 
115 OutputDevice::getDeviceByOption(const std::string& optionName) {
116  std::string devName = OptionsCont::getOptions().getString(optionName);
117  if (myOutputDevices.find(devName) == myOutputDevices.end()) {
118  throw InvalidArgument("Device '" + devName + "' has not been created.");
119  }
120  return OutputDevice::getDevice(devName);
121 }
122 
123 
124 void
125 OutputDevice::closeAll(bool keepErrorRetrievers) {
126  std::vector<OutputDevice*> errorDevices;
127  std::vector<OutputDevice*> nonErrorDevices;
128  for (std::map<std::string, OutputDevice*>::iterator i = myOutputDevices.begin(); i != myOutputDevices.end(); ++i) {
129  if (MsgHandler::getErrorInstance()->isRetriever(i->second)) {
130  errorDevices.push_back(i->second);
131  } else {
132  nonErrorDevices.push_back(i->second);
133  }
134  }
135  for (std::vector<OutputDevice*>::iterator i = nonErrorDevices.begin(); i != nonErrorDevices.end(); ++i) {
136  try {
137  //std::cout << " close '" << (*i)->getFilename() << "'\n";
138  (*i)->close();
139  } catch (const IOError& e) {
140  WRITE_ERROR("Error on closing output devices.");
141  WRITE_ERROR(e.what());
142  }
143  }
144  if (!keepErrorRetrievers) {
145  for (std::vector<OutputDevice*>::iterator i = errorDevices.begin(); i != errorDevices.end(); ++i) {
146  try {
147  (*i)->close();
148  } catch (const IOError& e) {
149  std::cerr << "Error on closing error output devices." << std::endl;
150  std::cerr << e.what() << std::endl;
151  }
152  }
153  }
154 }
155 
156 
157 std::string
158 OutputDevice::realString(const double v, const int precision) {
159  std::ostringstream oss;
160  if (v == 0) {
161  return "0";
162  }
163  if (v < pow(10., -precision)) {
164  oss.setf(std::ios::scientific, std::ios::floatfield);
165  } else {
166  oss.setf(std::ios::fixed, std::ios::floatfield); // use decimal format
167  oss.setf(std::ios::showpoint); // print decimal point
168  oss << std::setprecision(precision);
169  }
170  oss << v;
171  return oss.str();
172 }
173 
174 
175 // ===========================================================================
176 // member method definitions
177 // ===========================================================================
178 OutputDevice::OutputDevice(const int defaultIndentation, const std::string& filename) :
179  myFilename(filename) {
180  myFormatter = new PlainXMLFormatter(defaultIndentation);
181 }
182 
183 
185  delete myFormatter;
186 }
187 
188 
189 bool
191  return getOStream().good();
192 }
193 
194 
195 const std::string&
197  return myFilename;
198 }
199 
200 void
202  while (closeTag()) {}
203  for (std::map<std::string, OutputDevice*>::iterator i = myOutputDevices.begin(); i != myOutputDevices.end(); ++i) {
204  if (i->second == this) {
205  myOutputDevices.erase(i);
206  break;
207  }
208  }
210  delete this;
211 }
212 
213 
214 void
216  getOStream() << std::setprecision(precision);
217 }
218 
219 
220 bool
221 OutputDevice::writeXMLHeader(const std::string& rootElement,
222  const std::string& schemaFile,
223  std::map<SumoXMLAttr, std::string> attrs) {
224  if (schemaFile != "") {
225  attrs[SUMO_ATTR_XMLNS] = "http://www.w3.org/2001/XMLSchema-instance";
226  attrs[SUMO_ATTR_SCHEMA_LOCATION] = "http://sumo.dlr.de/xsd/" + schemaFile;
227  }
228  return myFormatter->writeXMLHeader(getOStream(), rootElement, attrs);
229 }
230 
231 
233 OutputDevice::openTag(const std::string& xmlElement) {
234  myFormatter->openTag(getOStream(), xmlElement);
235  return *this;
236 }
237 
238 
240 OutputDevice::openTag(const SumoXMLTag& xmlElement) {
241  myFormatter->openTag(getOStream(), xmlElement);
242  return *this;
243 }
244 
245 
246 bool
247 OutputDevice::closeTag(const std::string& comment) {
248  if (myFormatter->closeTag(getOStream(), comment)) {
249  postWriteHook();
250  return true;
251  }
252  return false;
253 }
254 
255 
256 void
258 
259 
260 void
261 OutputDevice::inform(const std::string& msg, const char progress) {
262  if (progress != 0) {
263  getOStream() << msg << progress;
264  } else {
265  getOStream() << msg << '\n';
266  }
267  postWriteHook();
268 }
269 
270 
271 /****************************************************************************/
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_ATTR_XMLNS
@ SUMO_ATTR_SCHEMA_LOCATION
static bool isSocket(const std::string &name)
Returns the information whether the given name represents a socket.
static std::string prependToLastPathComponent(const std::string &prefix, const std::string &path)
prepend the given prefix to the last path component of the given file path
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
static void removeRetrieverFromAllInstances(OutputDevice *out)
ensure that that given output device is no longer used as retriever by any instance
Definition: MsgHandler.cpp:198
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
static OutputDevice * getDevice()
Returns the single cerr instance.
static OutputDevice * getDevice()
Returns the single cout instance.
An output device that encapsulates an ofstream.
An output device for TCP/IP network connections.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:60
virtual ~OutputDevice()
Destructor.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
OutputDevice(const int defaultIndentation=0, const std::string &filename="")
Constructor.
static std::string realString(const double v, const int precision=gPrecision)
Helper method for string formatting.
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
virtual void postWriteHook()
Called after every write access.
std::string myFilename
Definition: OutputDevice.h:333
static bool createDeviceByOption(const std::string &optionName, const std::string &rootElement="", const std::string &schemaFile="")
Creates the device using the output definition stored in the named option.
const std::string & getFilename()
get filename or suitable description of this device
OutputFormatter * myFormatter
The formatter for XML.
Definition: OutputDevice.h:330
virtual std::ostream & getOStream()=0
Returns the associated ostream.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precison or resets it to default.
static void closeAll(bool keepErrorRetrievers=false)
void inform(const std::string &msg, const char progress=0)
Retrieves a message to this device.
static std::map< std::string, OutputDevice * > myOutputDevices
map from names to output devices
Definition: OutputDevice.h:325
static OutputDevice & getDevice(const std::string &name)
Returns the described OutputDevice.
virtual bool ok()
returns the information whether one can write into the device
virtual bool writeXMLHeader(std::ostream &into, const std::string &rootElement, const std::map< SumoXMLAttr, std::string > &attrs)=0
Writes an XML header with optional configuration.
virtual bool closeTag(std::ostream &into, const std::string &comment="")=0
Closes the most recently opened tag and optinally add a comment.
virtual void openTag(std::ostream &into, const std::string &xmlElement)=0
Opens an XML tag.
Output formatter for plain XML output.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...