IMP logo
IMP Reference Guide  develop.562c2f4da8,2025/03/09
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-2022 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 <memory>
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  std::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  std::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  //! Control whether to open the file in text or binary mode.
121  /** This only has an effect on files constructed from filename, and is an
122  error if the file has already been opened. For streams or filelike
123  objects, open the stream in binary mode first before passing it to
124  TextInput.
125  */
126  void set_binary_open_mode(bool binary) { in_->set_binary_open_mode(binary); }
127 };
128 
129 //! Set the target for the log.
130 /** See TextOutput for options. Python users should use
131  SetLogTarget instead.
132  \ingroup logging
133  */
134 #ifndef SWIG
135 IMPKERNELEXPORT void set_log_target(TextOutput l);
136 IMPKERNELEXPORT TextOutput get_log_target();
137 #endif
138 
139 //! Temporarily set log target
140 /** Set the log target to a given value and reset it
141  when the object is destroyed. Use this in Python
142  to set the target of logs.
143  \ingroup logging
144 */
145 class SetLogTarget : public RAII {
146  /* Python deletes all Python objects before static
147  destructors are called. As a result, having static
148  C++ objects point to Python objects is problematic.
149  This class makes sure that the pointer to the
150  Python class gets cleaned up when Python exits.
151  */
152  TextOutput old_;
153 
154  public:
155  IMP_RAII(SetLogTarget, (TextOutput to), old_ = get_log_target();
156  , set_log_target(to);, set_log_target(old_);, );
157 };
158 
161 
162 //! Create a temporary file. The path can be extracted from the TextOutput.
163 
164 /** If suffix is non-empty, there is some small chance of a collision on
165  non-BSD systems as a unique temporary file is first created, and then
166  a file with that suffix appended is created. */
167 IMPKERNELEXPORT TextOutput create_temporary_file(std::string prefix = "imp_temp",
168  std::string suffix = "");
169 
170 //! Create a temporary file.
171 /** If suffix is non-empty, there is some small chance of a collision on
172  non-BSD systems as a unique temporary file is first created, and then
173  a file with that suffix appended is created. */
174 IMPKERNELEXPORT std::string create_temporary_file_name(std::string prefix =
175  "imp_temp",
176  std::string suffix = "");
177 
178 //! Return a path to a file relative to another file.
179 /** For example
180  if base is path/to/config.file and relative is data/image0.jpg
181  then the return value would be path/to/data/image0.jpg. This
182  function should be used when processing configuration files so
183  that the meaning of the configuration file does not change if
184  current working directory changes.
185 */
186 IMPKERNELEXPORT std::string get_relative_path(std::string base,
187  std::string relative);
188 
189 //! Convert a possibly relative path to an absolute path.
190 /** If the provided path is a relative path, add the current working
191  directory to make it an absolute path.
192 
193  \note If the path is already absolute, it is returned unchanged.
194  Paths are not made canonical (symlinks or '..' elements are
195  not removed). On Windows, the path is always returned unchanged.
196  */
197 IMPKERNELEXPORT std::string get_absolute_path(std::string file);
198 
199 IMPKERNEL_END_NAMESPACE
200 
201 #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
Temporarily set log target.
Definition: file.h:145
#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:50
TextOutput create_temporary_file(std::string prefix="imp_temp", std::string suffix="")
Create a temporary file. The path can be extracted from the TextOutput.
Basic types used by IMP.
An input/output exception.
Definition: exception.h:173
#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
void set_binary_open_mode(bool binary)
Control whether to open the file in text or binary mode.
Definition: file.h:126
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.