IMP logo
IMP Reference Guide  develop.cb469e0f11,2024/05/29
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 
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 //! Temporarily set log target
132 /** Set the log target to a given value and reset it
133  when the object is destroyed. Use this in Python
134  to set the target of logs.
135  \ingroup logging
136 */
137 class SetLogTarget : public RAII {
138  /* Python deletes all Python objects before static
139  destructors are called. As a result, having static
140  C++ objects point to Python objects is problematic.
141  This class makes sure that the pointer to the
142  Python class gets cleaned up when Python exits.
143  */
144  TextOutput old_;
145 
146  public:
147  IMP_RAII(SetLogTarget, (TextOutput to), old_ = get_log_target();
148  , set_log_target(to);, set_log_target(old_);, );
149 };
150 
153 
154 //! Create a temporary file. The path can be extracted from the TextOutput.
155 
156 /** If suffix is non-empty, there is some small chance of a collision on
157  non-BSD systems as a unique temporary file is first created, and then
158  a file with that suffix appended is created. */
159 IMPKERNELEXPORT TextOutput create_temporary_file(std::string prefix = "imp_temp",
160  std::string suffix = "");
161 
162 //! Create a temporary file.
163 /** If suffix is non-empty, there is some small chance of a collision on
164  non-BSD systems as a unique temporary file is first created, and then
165  a file with that suffix appended is created. */
166 IMPKERNELEXPORT std::string create_temporary_file_name(std::string prefix =
167  "imp_temp",
168  std::string suffix = "");
169 
170 //! Return a path to a file relative to another file.
171 /** For example
172  if base is path/to/config.file and relative is data/image0.jpg
173  then the return value would be path/to/data/image0.jpg. This
174  function should be used when processing configuration files so
175  that the meaning of the configuration file does not change if
176  current working directory changes.
177 */
178 IMPKERNELEXPORT std::string get_relative_path(std::string base,
179  std::string relative);
180 
181 //! Convert a possibly relative path to an absolute path.
182 /** If the provided path is a relative path, add the current working
183  directory to make it an absolute path.
184 
185  \note If the path is already absolute, it is returned unchanged.
186  Paths are not made canonical (symlinks or '..' elements are
187  not removed). On Windows, the path is always returned unchanged.
188  */
189 IMPKERNELEXPORT std::string get_absolute_path(std::string file);
190 
191 IMPKERNEL_END_NAMESPACE
192 
193 #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:137
#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
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.