IMP  2.1.0
The Integrative Modeling Platform
base/file.h
Go to the documentation of this file.
1 /**
2  * \file IMP/base/file.h
3  * \brief Handling of file input/output
4  *
5  * Copyright 2007-2013 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPBASE_FILE_H
10 #define IMPBASE_FILE_H
11 
12 #include <IMP/base/base_config.h>
13 #include "exception.h"
14 #include "internal/ifile.h"
15 #include "Pointer.h"
16 #include "InputAdaptor.h"
17 #include "value_macros.h"
18 #include "check_macros.h"
19 #include <boost/shared_ptr.hpp>
20 #include <fstream>
21 #include <iostream>
22 
23 IMPBASE_BEGIN_NAMESPACE
24 
25 #if !defined(IMP_DOXYGEN)
26 template <class Stream>
27 struct TextProxy {
28  Stream *str_;
29  base::PointerMember<Object> ptr_;
30  TextProxy(Stream *str, Object *ptr) : str_(str), ptr_(ptr) {}
31 };
32 #endif
33 
34 /** A TextOutput can be implicitly constructed from a C++ stream, a
35  Python filelike object or a path to a file. As a result, those can be
36  passed directly to functions which take a TextOutput as an
37  argument.
38 
39  Files are created lazily, so TextOutput can be passed as
40  arguments to functions that might not produce output.
41  \code
42  IMP::atom::write_pdb(particles, "path/to/file.pdb");
43  IMP::atom::write_pdb(particles, my_fstream);
44  \endcode
45  \see TextInput
46 */
47 class IMPBASEEXPORT TextOutput : public InputAdaptor {
48  boost::shared_ptr<internal::IOStorage<std::ostream> > out_;
49 
50  public:
51 #ifndef IMP_DOXYGEN
52  // SWIG needs these here for some bizarre reason
53  TextOutput(int);
54  TextOutput(double);
55  TextOutput(const char *c, bool append = false);
56  TextOutput(TextProxy<std::ostream> p);
57 #endif
58  TextOutput() {}
59  TextOutput(std::string file_name, bool append = false);
60 #ifndef SWIG
61  TextOutput(std::ostream &out, std::string name = "C++ stream");
62 #endif
63 
64 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
65  operator std::ostream &() { return get_stream(); }
66  IMP_SAFE_BOOL(TextOutput, out_ &&out_->get_stream());
67  std::ostream &get_stream() {
68  IMP_USAGE_CHECK(out_, "Attempting to write to uninitialized text input");
69  return out_->get_stream();
70  }
71 #endif
72  IMP_SHOWABLE_INLINE(TextOutput, out << get_name());
73  std::string get_name() const { return out_->get_name(); }
74 };
75 
76 /** A TextInput can be implicitly constructed from a C++ stream, a
77  Python filelike object or a path to a file. As a result, those can be
78  passed directly to functions which take a TextInput as an
79  argument.
80  \code
81  IMP::atom::read_pdb("path/to/file.pdb", m);
82  IMP::atom::read_pdb(my_fstream, m);
83  \endcode
84  \see TextOutput
85 */
86 class IMPBASEEXPORT TextInput : public InputAdaptor {
87  boost::shared_ptr<internal::IOStorage<std::istream> > in_;
88 
89  public:
90 #ifndef IMP_DOXYGEN
91  // SWIG needs these here for some bizarre reason
92  TextInput(int);
93  TextInput(double);
94  TextInput(const char *c);
95  TextInput(TextProxy<std::istream> p);
96 #endif
97  TextInput() {}
98  TextInput(std::string file_name);
99 #ifndef SWIG
100  TextInput(std::istream &out, std::string name = "C++ stream");
101 #endif
102 
103 #if !defined(SWIG) && !defined(IMP_DOXYGEN)
104  operator std::istream &() { return get_stream(); }
105  std::istream &get_stream() {
106  if (!in_) {
107  IMP_THROW("Attempting to read from uninitialized text input",
108  IOException);
109  }
110  return in_->get_stream();
111  }
112 #endif
113  IMP_SHOWABLE_INLINE(TextInput, out << get_name());
114  IMP_SAFE_BOOL(TextInput, in_ &&in_->get_stream());
115  std::string get_name() const { return in_->get_name(); }
116 };
117 
118 //! Set the target for the log.
119 /** See TextOutput for options. Python users should use
120  SetLogTarget instead.
121  \ingroup logging
122  */
123 #ifndef SWIG
124 IMPBASEEXPORT void set_log_target(TextOutput l);
125 IMPBASEEXPORT TextOutput get_log_target();
126 #endif
127 
128 /** Set the log target to a given value and reset it
129  when the object is destroyed. Use this in Python
130  to set the target of logs.
131  \ingroup logging
132 */
133 class SetLogTarget : public base::RAII {
134  /* Python deletes all Python objects before static
135  destructors are called. As a result, having static
136  C++ objects point to Python objects is problematic.
137  This class makes sure that the pointer to the
138  Python class gets cleaned up when Python exits.
139  */
140  TextOutput old_;
141 
142  public:
143  IMP_RAII(SetLogTarget, (TextOutput to), old_ = get_log_target();
144  , set_log_target(to);, set_log_target(old_);, );
145 };
146 
149 
150 /** Create a temporary file. The path can be extracted from the TextOutput.
151 
152  If suffix is non-empty, there is some small chance of a collision on
153  non-BSD systems as a unique temporary file is first created, and then
154  a file with that suffix appended is created.*/
155 IMPBASEEXPORT TextOutput create_temporary_file(std::string prefix = "imp_temp",
156  std::string suffix = "");
157 
158 /** Create a temporary file.
159 
160  If suffix is non-empty, there is some small chance of a collision on
161  non-BSD systems as a unique temporary file is first created, and then
162  a file with that suffix appended is created.*/
163 IMPBASEEXPORT std::string create_temporary_file_name(std::string prefix =
164  "imp_temp",
165  std::string suffix = "");
166 
167 /** Return a path to a file relative to another file. For example
168  if base is path/to/config.file and relative is data/image0.jpg
169  then the return value would be path/to/data/image0.jpg. This
170  function should be used when processing configuration files so
171  that the meaning of the configuration file does not change if
172  current working directory changes.
173 */
174 IMPBASEEXPORT std::string get_relative_path(std::string base,
175  std::string relative);
176 
177 IMPBASE_END_NAMESPACE
178 
179 #endif /* IMPBASE_FILE_H */
TextOutput create_temporary_file(std::string prefix="imp_temp", std::string suffix="")
An input/output exception.
A nullptr-initialized pointer to an IMP Object.
std::string create_temporary_file_name(std::string prefix="imp_temp", std::string suffix="")
#define IMP_VALUES(Name, PluralName)
Define the type for storing sets of values.
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
void set_log_target(TextOutput l)
Set the target for the log.
std::string get_relative_path(std::string base, std::string relative)
Basic types used by IMP.
#define IMP_SAFE_BOOL(Name, expr)
Exception definitions and assertions.
#define IMP_RAII(Name, args, Initialize, Set, Reset, Show)
Declares RAII-style methods in a class.
#define IMP_THROW(message, exception_name)
Throw an exception with a message.
Various general useful macros for IMP.
Exception definitions and assertions.