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