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