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