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 uncompression.
5
6#ifndef GEMMI_INPUT_HPP_
7#define GEMMI_INPUT_HPP_
8
9#include <cassert>
10#include <cstddef> // for ptrdiff_t
11#include <cstdio> // for FILE, fseek, fread
12#include <cstdlib> // for malloc, realloc
13#include <cstring> // for memchr
14#include <memory> // for unique_ptr
15#include <string>
16#include "fail.hpp" // for unreachable
17
18namespace gemmi {
19
20// provides the same methods as GzStream
21struct FileStream {
22 std::FILE* f;
23 // used in pdb.hpp
24 char* gets(char* line, int size) { return std::fgets(line, size, f); }
25 int getc() { return std::fgetc(f); }
26 // used in ccp4.hpp
27 bool read(void* buf, size_t len) { return std::fread(buf, len, 1, f) == 1; }
28
29 // used in mtz.hpp
30 std::string read_rest() {
31 std::string ret;
32 int c = std::fgetc(f);
33 if (c != EOF) {
34 ret += (char)c;
35 char buf[512];
36 for (;;) {
37 size_t n = std::fread(buf, 1, sizeof(buf), f);
38 ret.append(buf, n);
39 if (n != sizeof(buf))
40 break;
41 }
42 }
43 return ret;
44 }
45
46 bool seek(std::ptrdiff_t offset) {
47#if defined(_MSC_VER)
48 return _fseeki64(f, offset, SEEK_SET) == 0;
49#elif defined(__MINGW32__)
50 return fseeko(f, (_off_t)offset, SEEK_SET) == 0;
51#else
52 return std::fseek(f, (long)offset, SEEK_SET) == 0;
53#endif
54 }
55};
56
58 MemoryStream(const char* start_, size_t size)
59 : start(start_), end(start_ + size), cur(start_) {}
60
61 char* gets(char* line, int size) {
62 --size; // fgets reads in at most one less than size characters
63 if (cur >= end)
64 return nullptr;
65 if (size > end - cur)
66 size = int(end - cur);
67 const char* nl = (const char*) std::memchr(cur, '\n', size);
68 size_t len = nl ? nl - cur + 1 : size;
69 std::memcpy(line, cur, len);
70 line[len] = '\0';
71 cur += len;
72 return line;
73 }
74 int getc() { return cur < end ? *cur++ : EOF; }
75
76 bool read(void* buf, size_t len) {
77 if (cur + len > end)
78 return false;
79 std::memcpy(buf, cur, len);
80 cur += len;
81 return true;
82 }
83
84 std::string read_rest() {
85 const char* last = cur;
86 cur = end;
87 return std::string(last, end);
88 }
89
90 int seek(std::ptrdiff_t offset) {
91 cur = start + offset;
92 return cur < end;
93 }
94
95private:
96 const char* const start;
97 const char* const end;
98 const char* cur;
99};
100
102 std::unique_ptr<char, decltype(&std::free)> ptr_;
103 size_t size_;
104public:
105 CharArray() : ptr_(nullptr, &std::free), size_(0) {}
106 explicit CharArray(size_t n) : ptr_((char*)std::malloc(n), &std::free), size_(n) {};
107 explicit operator bool() const { return (bool)ptr_; }
108 char* data() { return ptr_.get(); }
109 const char* data() const { return ptr_.get(); }
110 size_t size() const { return size_; }
111 void set_size(size_t n) { size_ = n; }
112
113 MemoryStream stream() const { return MemoryStream(data(), size()); }
114
115 void resize(size_t n) {
116 char* new_ptr = (char*) std::realloc(ptr_.get(), n);
117 if (!new_ptr && n != 0)
118 fail("Out of memory.");
119 (void) ptr_.release();
120 ptr_.reset(new_ptr);
121 size_ = n;
122 }
123
124 // Remove first n bytes making space for more text at the returned position.
125 char* roll(size_t n) {
126 assert(n <= size());
127 std::memmove(data(), data() + n, n);
128 return data() + n;
129 }
130};
131
133public:
134 explicit BasicInput(const std::string& path) : path_(path) {}
135
136 const std::string& path() const { return path_; };
137 const std::string& basepath() const { return path_; };
138
139 // Does the path stands for stdin?
140 // Each reading function needs to call it (some functions use stdin
141 // and some std::cin, so we don't try to unify it here).
142 bool is_stdin() const { return path() == "-"; };
143
144 // providing the same interface as MaybeGzipped
145 bool is_compressed() const { return false; }
147 // for reading (uncompressing into memory) the whole file at once
148 CharArray uncompress_into_buffer(size_t=0) { return {}; }
149
150private:
151 std::string path_;
152};
153
154template<typename Input>
155inline size_t copy_line_from_stream(char* line, int size, Input&& in) {
156 if (!in.gets(line, size))
157 return 0;
158 size_t len = std::strlen(line);
159 // If a line is longer than size we discard the rest of it.
160 if (len > 0 && line[len-1] != '\n')
161 for (int c = in.getc(); c > 0 /* not 0 nor EOF */ && c != '\n'; c = in.getc())
162 continue;
163 return len;
164}
165
166} // namespace gemmi
167#endif
FileStream get_uncompressing_stream() const
Definition input.hpp:146
bool is_stdin() const
Definition input.hpp:142
CharArray uncompress_into_buffer(size_t=0)
Definition input.hpp:148
const std::string & basepath() const
Definition input.hpp:137
BasicInput(const std::string &path)
Definition input.hpp:134
const std::string & path() const
Definition input.hpp:136
bool is_compressed() const
Definition input.hpp:145
char * data()
Definition input.hpp:108
void resize(size_t n)
Definition input.hpp:115
size_t size() const
Definition input.hpp:110
void set_size(size_t n)
Definition input.hpp:111
const char * data() const
Definition input.hpp:109
CharArray(size_t n)
Definition input.hpp:106
char * roll(size_t n)
Definition input.hpp:125
MemoryStream stream() const
Definition input.hpp:113
size_t copy_line_from_stream(char *line, int size, Input &&in)
Definition input.hpp:155
void fail(const std::string &msg)
Definition fail.hpp:59
void unreachable()
Definition fail.hpp:80
Definition seqid.hpp:149
bool read(void *buf, size_t len)
Definition input.hpp:27
char * gets(char *line, int size)
Definition input.hpp:24
std::FILE * f
Definition input.hpp:22
std::string read_rest()
Definition input.hpp:30
bool seek(std::ptrdiff_t offset)
Definition input.hpp:46
bool read(void *buf, size_t len)
Definition input.hpp:76
std::string read_rest()
Definition input.hpp:84
char * gets(char *line, int size)
Definition input.hpp:61
int seek(std::ptrdiff_t offset)
Definition input.hpp:90
MemoryStream(const char *start_, size_t size)
Definition input.hpp:58