IMP logo
IMP Reference Guide  2.15.0
The Integrative Modeling Platform
file.h
Go to the documentation of this file.
1 /**
2  * \file IMP/file.h
3  * \brief Handling of file input/output
4  *
5  * Copyright 2007-2021 IMP Inventors. All rights reserved.
6  *
7  */
8 
9 #ifndef IMPKERNEL_FILE_H
10 #define IMPKERNEL_FILE_H
11 
12 #include <IMP/kernel_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 IMPKERNEL_BEGIN_NAMESPACE
27 
28 #if !defined(IMP_DOXYGEN)
29 template <class Stream>
30 struct TextProxy {
31  Stream *str_;
32  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 IMPKERNELEXPORT 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 IMPKERNELEXPORT 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 IMPKERNELEXPORT void set_log_target(TextOutput l);
128 IMPKERNELEXPORT 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 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 IMPKERNELEXPORT 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 IMPKERNELEXPORT 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 IMPKERNELEXPORT std::string get_relative_path(std::string base,
178  std::string relative);
179 
180 //! Convert a possibly relative path to an absolute path.
181 /** If the provided path is a relative path, add the current working
182  directory to make it an absolute path.
183 
184  \note If the path is already absolute, it is returned unchanged.
185  Paths are not made canonical (symlinks or '..' elements are
186  not removed). On Windows, the path is always returned unchanged.
187  */
188 IMPKERNELEXPORT std::string get_absolute_path(std::string file);
189 
190 IMPKERNEL_END_NAMESPACE
191 
192 #endif /* IMPKERNEL_FILE_H */
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
Temporarily change something; undo the change when this object is destroyed.
Definition: RAII.h:28
#define IMP_RAII(Name, args, Initialize, Set, Reset, Show)
Declares RAII-style methods in a class.
Definition: raii_macros.h:34
#define IMP_SAFE_BOOL(Name, expr)
Exception definitions and assertions.
A more IMP-like version of the std::vector.
Definition: Vector.h:40
TextOutput create_temporary_file(std::string prefix="imp_temp", std::string suffix="")
Basic types used by IMP.
An input/output exception.
Definition: exception.h:174
#define IMP_VALUES(Name, PluralName)
Define the type for storing sets of values.
Definition: value_macros.h:23
Convenience class to accept multiple input types.
std::string get_relative_path(std::string base, std::string relative)
Return a path to a file relative to another file.
void set_log_target(TextOutput l)
Set the target for the log.
std::string get_absolute_path(std::string file)
Convert a possibly relative path to an absolute path.
#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.
Helper macros for throwing and handling exceptions.
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:168
Macros to help in implementing Value objects.
Convenience class to accept multiple input types.
Definition: InputAdaptor.h:25
Macros to aid in writing RAII-style classes.
std::string create_temporary_file_name(std::string prefix="imp_temp", std::string suffix="")
Create a temporary file.