SUMO - Simulation of Urban MObility
OutputDevice.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // Static storage of an output device and its base (abstract) implementation
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright (C) 2004-2017 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <map>
34 #include <fstream>
35 #include <sstream>
36 #include <string>
37 #include <iomanip>
38 #include "OutputDevice.h"
39 #include "OutputDevice_File.h"
40 #include "OutputDevice_COUT.h"
41 #include "OutputDevice_CERR.h"
42 #include "OutputDevice_Network.h"
43 #include "PlainXMLFormatter.h"
47 #include <utils/common/ToString.h>
50 
51 #ifdef CHECK_MEMORY_LEAKS
52 #include <foreign/nvwa/debug_new.h>
53 #endif // CHECK_MEMORY_LEAKS
54 
55 
56 // ===========================================================================
57 // static member definitions
58 // ===========================================================================
59 std::map<std::string, OutputDevice*> OutputDevice::myOutputDevices;
60 
61 
62 // ===========================================================================
63 // static method definitions
64 // ===========================================================================
66 OutputDevice::getDevice(const std::string& name) {
67  // check whether the device has already been aqcuired
68  if (myOutputDevices.find(name) != myOutputDevices.end()) {
69  return *myOutputDevices[name];
70  }
71  // build the device
72  OutputDevice* dev = 0;
73  // check whether the device shall print to stdout
74  if (name == "stdout") {
76  } else if (name == "stderr") {
78  } else if (FileHelpers::isSocket(name)) {
79  try {
80  int port = TplConvert::_2int(name.substr(name.find(":") + 1).c_str());
81  dev = new OutputDevice_Network(name.substr(0, name.find(":")), port);
82  } catch (NumberFormatException&) {
83  throw IOError("Given port number '" + name.substr(name.find(":") + 1) + "' is not numeric.");
84  } catch (EmptyData&) {
85  throw IOError("No port number given.");
86  }
87  } else {
88  const int len = (int)name.length();
89  std::string name2 = name;
90  if (OptionsCont::getOptions().isSet("output-prefix") && name != "/dev/null") {
91  std::string prefix = OptionsCont::getOptions().getString("output-prefix");
92  const std::string::size_type metaTimeIndex = prefix.find("TIME");
93  if (metaTimeIndex != std::string::npos) {
94  time_t rawtime;
95  char buffer [80];
96  time(&rawtime);
97  struct tm* timeinfo = localtime(&rawtime);
98  strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S", timeinfo);
99  prefix.replace(metaTimeIndex, 4, std::string(buffer));
100  }
101  name2 = FileHelpers::prependToLastPathComponent(prefix, name);
102  }
103  dev = new OutputDevice_File(name2, len > 4 && name.substr(len - 4) == ".sbx");
104  }
105  dev->setPrecision();
106  dev->getOStream() << std::setiosflags(std::ios::fixed);
107  myOutputDevices[name] = dev;
108  return *dev;
109 }
110 
111 
112 bool
113 OutputDevice::createDeviceByOption(const std::string& optionName,
114  const std::string& rootElement,
115  const std::string& schemaFile) {
116  if (!OptionsCont::getOptions().isSet(optionName)) {
117  return false;
118  }
119  OutputDevice& dev = OutputDevice::getDevice(OptionsCont::getOptions().getString(optionName));
120  if (rootElement != "") {
121  dev.writeXMLHeader(rootElement, schemaFile);
122  }
123  return true;
124 }
125 
126 
128 OutputDevice::getDeviceByOption(const std::string& optionName) {
129  std::string devName = OptionsCont::getOptions().getString(optionName);
130  if (myOutputDevices.find(devName) == myOutputDevices.end()) {
131  throw InvalidArgument("Device '" + devName + "' has not been created.");
132  }
133  return OutputDevice::getDevice(devName);
134 }
135 
136 
137 void
139  std::vector<OutputDevice*> errorDevices;
140  std::vector<OutputDevice*> nonErrorDevices;
141  for (std::map<std::string, OutputDevice*>::iterator i = myOutputDevices.begin(); i != myOutputDevices.end(); ++i) {
142  if (MsgHandler::getErrorInstance()->isRetriever(i->second)) {
143  errorDevices.push_back(i->second);
144  } else {
145  nonErrorDevices.push_back(i->second);
146  }
147  }
148  for (std::vector<OutputDevice*>::iterator i = nonErrorDevices.begin(); i != nonErrorDevices.end(); ++i) {
149  try {
150  (*i)->close();
151  } catch (const IOError& e) {
152  WRITE_ERROR("Error on closing output devices.");
153  WRITE_ERROR(e.what());
154  }
155  }
156  for (std::vector<OutputDevice*>::iterator i = errorDevices.begin(); i != errorDevices.end(); ++i) {
157  try {
158  (*i)->close();
159  } catch (const IOError& e) {
160  std::cerr << "Error on closing error output devices." << std::endl;
161  std::cerr << e.what() << std::endl;
162  }
163  }
164 }
165 
166 
167 std::string
168 OutputDevice::realString(const SUMOReal v, const int precision) {
169  std::ostringstream oss;
170  if (v == 0) {
171  return "0";
172  }
173  if (v < pow(10., -precision)) {
174  oss.setf(std::ios::scientific, std::ios::floatfield);
175  } else {
176  oss.setf(std::ios::fixed , std::ios::floatfield); // use decimal format
177  oss.setf(std::ios::showpoint); // print decimal point
178  oss << std::setprecision(precision);
179  }
180  oss << v;
181  return oss.str();
182 }
183 
184 
185 // ===========================================================================
186 // member method definitions
187 // ===========================================================================
188 OutputDevice::OutputDevice(const bool binary, const int defaultIndentation)
189  : myAmBinary(binary) {
190  if (binary) {
192  } else {
193  myFormatter = new PlainXMLFormatter(defaultIndentation);
194  }
195 }
196 
197 
199  delete myFormatter;
200 }
201 
202 
203 bool
205  return getOStream().good();
206 }
207 
208 
209 void
211  while (closeTag()) {}
212  for (std::map<std::string, OutputDevice*>::iterator i = myOutputDevices.begin(); i != myOutputDevices.end(); ++i) {
213  if (i->second == this) {
214  myOutputDevices.erase(i);
215  break;
216  }
217  }
218  delete this;
219 }
220 
221 
222 void
224  getOStream() << std::setprecision(precision);
225 }
226 
227 
228 bool
229 OutputDevice::writeXMLHeader(const std::string& rootElement,
230  const std::string& schemaFile,
231  std::map<SumoXMLAttr, std::string> attrs) {
232  if (schemaFile != "") {
233  attrs[SUMO_ATTR_XMLNS] = "http://www.w3.org/2001/XMLSchema-instance";
234  attrs[SUMO_ATTR_SCHEMA_LOCATION] = "http://sumo.dlr.de/xsd/" + schemaFile;
235  }
236  return myFormatter->writeXMLHeader(getOStream(), rootElement, attrs);
237 }
238 
239 
241 OutputDevice::openTag(const std::string& xmlElement) {
242  myFormatter->openTag(getOStream(), xmlElement);
243  return *this;
244 }
245 
246 
248 OutputDevice::openTag(const SumoXMLTag& xmlElement) {
249  myFormatter->openTag(getOStream(), xmlElement);
250  return *this;
251 }
252 
253 
254 bool
256  if (myFormatter->closeTag(getOStream())) {
257  postWriteHook();
258  return true;
259  }
260  return false;
261 }
262 
263 
264 void
266 
267 
268 void
269 OutputDevice::inform(const std::string& msg, const char progress) {
270  if (progress != 0) {
271  getOStream() << msg << progress;
272  } else {
273  getOStream() << msg << '\n';
274  }
275  postWriteHook();
276 }
277 
278 
279 /****************************************************************************/
280 
bool isRetriever(OutputDevice *retriever) const
Returns whether the given output device retrieves messages from the handler.
Definition: MsgHandler.cpp:191
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:80
virtual bool closeTag(std::ostream &into)=0
Closes the most recently opened tag.
static std::map< std::string, OutputDevice * > myOutputDevices
map from names to output devices
Definition: OutputDevice.h:341
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:94
void setPrecision(int precision=gPrecision)
Sets the precison or resets it to default.
An output device for TCP/IP network connections.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
void inform(const std::string &msg, const char progress=0)
Retrieves a message to this device.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
Output formatter for plain XML output.
static void closeAll()
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.
OutputDevice(const bool binary=false, const int defaultIndentation=0)
Constructor.
virtual bool ok()
returns the information whether one can write into the device
static std::string realString(const SUMOReal v, const int precision=gPrecision)
Helper method for string formatting.
Output formatter for plain XML output.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
static int _2int(const E *const data)
converts a char-type array into the integer value described by it
Definition: TplConvert.h:149
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:348
OutputFormatter * myFormatter
The formatter for XML.
Definition: OutputDevice.h:346
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:71
bool closeTag()
Closes the most recently opened tag.
#define SUMOReal
Definition: config.h:208
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.