Gemmi C++ API
Loading...
Searching...
No Matches
input.hpp
Go to the documentation of this file.
1// Copyright 2018 Global Phasing Ltd.
2//
3// Input abstraction.
4// Used to decouple file reading and decompression.
5
6#ifndef GEMMI_INPUT_HPP_
7#define GEMMI_INPUT_HPP_
8
9#include <cstddef> // for ptrdiff_t
10#include <cstdio> // for FILE, fseek, fread
11#include <cstring> // for memchr
12#include <string>
13#include "fileutil.hpp" // for fileptr_t
14
15namespace gemmi {
16
17// base class for FileStream, MemoryStream and GzStream
18struct AnyStream {
19 virtual ~AnyStream() = default;
20
21 virtual char* gets(char* line, int size) = 0; // for pdb, copy_line()
22 virtual int getc() = 0; // for copy_line()
23 virtual bool read(void* buf, size_t len) = 0; // for ccp4, mtz
24
25 // these are not used in GzStream because MemoryStream is used for mtz
26 virtual long tell() = 0; // temporary, for testing
27 virtual bool skip(size_t n) = 0; // for reading mtz without data
28 virtual std::string read_rest() { return {}; } // for mtz (appendix)
29
30 size_t copy_line(char* line, int size) { // for pdb, xds_ascii
31 if (!gets(line, size))
32 return 0;
33 size_t len = std::strlen(line);
34 // If a line is longer than size we discard the rest of it.
35 if (len > 0 && line[len-1] != '\n')
36 for (int c = getc(); c > 0 /* not 0 nor EOF */ && c != '\n'; c = getc())
37 continue;
38 return len;
39 };
40};
41
42struct FileStream final : public AnyStream {
43 FileStream(std::FILE* f_) : f(f_, needs_fclose{false}) {}
44 FileStream(const char* path, const char* mode) : f(file_open_or(path, mode, stdin)) {}
45
46 char* gets(char* line, int size) override { return std::fgets(line, size, f.get()); }
47 int getc() override { return std::fgetc(f.get()); }
48 bool read(void* buf, size_t len) override { return std::fread(buf, len, 1, f.get()) == 1; }
49
50 std::string read_rest() override {
51 std::string ret;
52 int c = std::fgetc(f.get());
53 if (c != EOF) {
54 ret += (char)c;
55 char buf[512];
56 for (;;) {
57 size_t n = std::fread(buf, 1, sizeof(buf), f.get());
58 ret.append(buf, n);
59 if (n != sizeof(buf))
60 break;
61 }
62 }
63 return ret;
64 }
65
66 long tell() override {
67 return std::ftell(f.get());
68 }
69
70 bool skip(size_t n) override {
71#if defined(_MSC_VER)
72 int result = _fseeki64(f.get(), (std::ptrdiff_t)n, SEEK_CUR);
73#elif defined(__MINGW32__)
74 int result = fseeko(f.get(), (_off_t)n, SEEK_CUR);
75#else
76 int result = std::fseek(f.get(), (long)n, SEEK_CUR);
77#endif
78 if (result != 0) {
79 char buf[512];
80 while (n >= sizeof(buf)) {
81 if (std::fread(buf, sizeof(buf), 1, f.get()) != 1)
82 return false;
83 n -= sizeof(buf);
84 }
85 if (n > 0 && std::fread(buf, n, 1, f.get()) != 1)
86 return false;
87 }
88 return true;
89 }
90
91private:
92 fileptr_t f;
93};
94
95struct MemoryStream final : public AnyStream {
96 MemoryStream(const char* start_, size_t size)
97 : start(start_), end(start_ + size), cur(start_) {}
98
99 char* gets(char* line, int size) override {
100 --size; // fgets reads in at most one less than size characters
101 if (cur >= end)
102 return nullptr;
103 if (size > end - cur)
104 size = int(end - cur);
105 const char* nl = (const char*) std::memchr(cur, '\n', size);
106 size_t len = nl ? nl - cur + 1 : size;
107 std::memcpy(line, cur, len);
108 line[len] = '\0';
109 cur += len;
110 return line;
111 }
112 int getc() override { return cur < end ? *cur++ : EOF; }
113
114 bool read(void* buf, size_t len) override {
115 if (cur + len > end)
116 return false;
117 std::memcpy(buf, cur, len);
118 cur += len;
119 return true;
120 }
121
122 std::string read_rest() override {
123 const char* last = cur;
124 cur = end;
125 return std::string(last, end);
126 }
127
128 long tell() override {
129 return cur - start;
130 }
131 bool skip(size_t n) override {
132 cur += n;
133 return cur < end;
134 }
135
136private:
137 const char* const start;
138 const char* const end;
139 const char* cur;
140};
141
143public:
144 explicit BasicInput(const std::string& path) : path_(path) {}
145
146 const std::string& path() const { return path_; }
147 const std::string& basepath() const { return path_; }
148
149 // Does the path stands for stdin?
150 // Each reading function needs to call it (some functions use stdin
151 // and some std::cin, so we don't try to unify it here).
152 bool is_stdin() const { return path() == "-"; }
153
154 // providing the same interface as MaybeGzipped
155 bool is_compressed() const { return false; }
156 // for reading (uncompressing into memory) the whole file at once
157 CharArray uncompress_into_buffer(size_t=0) { return {}; }
158
159 std::unique_ptr<AnyStream> create_stream() {
160 return std::unique_ptr<AnyStream>(new FileStream(path().c_str(), "rb"));
161 }
162
163private:
164 std::string path_;
165};
166
167} // namespace gemmi
168#endif
bool is_stdin() const
Definition input.hpp:152
CharArray uncompress_into_buffer(size_t=0)
Definition input.hpp:157
const std::string & basepath() const
Definition input.hpp:147
BasicInput(const std::string &path)
Definition input.hpp:144
const std::string & path() const
Definition input.hpp:146
bool is_compressed() const
Definition input.hpp:155
std::unique_ptr< AnyStream > create_stream()
Definition input.hpp:159
File-related utilities.
fileptr_t file_open_or(const char *path, const char *mode, std::FILE *dash_stream)
Definition fileutil.hpp:65
std::unique_ptr< std::FILE, needs_fclose > fileptr_t
Definition fileutil.hpp:48
virtual std::string read_rest()
Definition input.hpp:28
virtual char * gets(char *line, int size)=0
virtual long tell()=0
virtual bool skip(size_t n)=0
virtual bool read(void *buf, size_t len)=0
size_t copy_line(char *line, int size)
Definition input.hpp:30
virtual int getc()=0
virtual ~AnyStream()=default
FileStream(std::FILE *f_)
Definition input.hpp:43
char * gets(char *line, int size) override
Definition input.hpp:46
int getc() override
Definition input.hpp:47
bool skip(size_t n) override
Definition input.hpp:70
long tell() override
Definition input.hpp:66
std::string read_rest() override
Definition input.hpp:50
FileStream(const char *path, const char *mode)
Definition input.hpp:44
bool read(void *buf, size_t len) override
Definition input.hpp:48
bool read(void *buf, size_t len) override
Definition input.hpp:114
bool skip(size_t n) override
Definition input.hpp:131
std::string read_rest() override
Definition input.hpp:122
int getc() override
Definition input.hpp:112
long tell() override
Definition input.hpp:128
char * gets(char *line, int size) override
Definition input.hpp:99
MemoryStream(const char *start_, size_t size)
Definition input.hpp:96
deleter for fileptr_t
Definition fileutil.hpp:40