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