Gemmi C++ API
Loading...
Searching...
No Matches
fileutil.hpp
Go to the documentation of this file.
1// Copyright 2018 Global Phasing Ltd.
2//
3// File-related utilities.
4
5#ifndef GEMMI_FILEUTIL_HPP_
6#define GEMMI_FILEUTIL_HPP_
7
8#include <cstdio> // for FILE, fopen, fclose
9#include <cstdint>
10#include <cstring> // strlen
11#include <initializer_list>
12#include <memory> // for unique_ptr
13#include "fail.hpp" // for sys_fail
14#include "input.hpp" // for CharArray
15
16#if defined(_WIN32) && !defined(GEMMI_USE_FOPEN)
17#include "utf.hpp"
18#endif
19
20namespace gemmi {
21
22// strip directory and suffixes from filename
23inline std::string path_basename(const std::string& path,
24 std::initializer_list<const char*> exts) {
25 size_t pos = path.find_last_of("\\/");
26 std::string basename = pos == std::string::npos ? path : path.substr(pos + 1);
27 for (const char* ext : exts) {
28 size_t len = std::strlen(ext);
29 if (basename.size() > len &&
30 basename.compare(basename.length() - len, len, ext, len) == 0)
31 basename.resize(basename.length() - len);
32 }
33 return basename;
34}
35
36// file operations
37typedef std::unique_ptr<std::FILE, decltype(&std::fclose)> fileptr_t;
38
39inline fileptr_t file_open(const char* path, const char* mode) {
40 std::FILE* file;
41#if defined(_WIN32) && !defined(GEMMI_USE_FOPEN)
42 std::wstring wpath = UTF8_to_wchar(path);
43 std::wstring wmode = UTF8_to_wchar(mode);
44 if ((file = ::_wfopen(wpath.c_str(), wmode.c_str())) == nullptr)
45#else
46 if ((file = std::fopen(path, mode)) == nullptr)
47#endif
48 sys_fail(std::string("Failed to open ") + path +
49 (*mode == 'w' ? " for writing" : ""));
50 return fileptr_t(file, &std::fclose);
51}
52
53// helper function for treating "-" as stdin or stdout
54inline fileptr_t file_open_or(const char* path, const char* mode,
55 std::FILE* dash_stream) {
56 if (path[0] == '-' && path[1] == '\0')
57 return fileptr_t(dash_stream, [](std::FILE*) { return 0; });
58 return file_open(path, mode);
59}
60
61inline std::size_t file_size(std::FILE* f, const std::string& path) {
62 if (std::fseek(f, 0, SEEK_END) != 0)
63 sys_fail(path + ": fseek failed");
64 long length = std::ftell(f);
65 if (length < 0)
66 sys_fail(path + ": ftell failed");
67 if (std::fseek(f, 0, SEEK_SET) != 0)
68 sys_fail(path + ": fseek failed");
69 return length;
70}
71
72// helper function for working with binary files
73inline bool is_little_endian() {
74 std::uint32_t x = 1;
75 return *reinterpret_cast<char *>(&x) == 1;
76}
77
78inline void swap_two_bytes(void* start) {
79 char* bytes = static_cast<char*>(start);
80 std::swap(bytes[0], bytes[1]);
81}
82
83inline void swap_four_bytes(void* start) {
84 char* bytes = static_cast<char*>(start);
85 std::swap(bytes[0], bytes[3]);
86 std::swap(bytes[1], bytes[2]);
87}
88
89inline void swap_eight_bytes(void* start) {
90 char* bytes = static_cast<char*>(start);
91 std::swap(bytes[0], bytes[7]);
92 std::swap(bytes[1], bytes[6]);
93 std::swap(bytes[2], bytes[5]);
94 std::swap(bytes[3], bytes[4]);
95}
96
97// reading file into a memory buffer
98inline CharArray read_file_into_buffer(const std::string& path) {
99 fileptr_t f = file_open(path.c_str(), "rb");
100 size_t size = file_size(f.get(), path);
101 CharArray buffer(size);
102 if (std::fread(buffer.data(), size, 1, f.get()) != 1)
103 sys_fail(path + ": fread failed");
104 return buffer;
105}
106
108 size_t n = 0;
109 CharArray buffer(16 * 1024);
110 for (;;) {
111 n += std::fread(buffer.data() + n, 1, buffer.size() - n, stdin);
112 if (n != buffer.size()) {
113 buffer.set_size(n);
114 break;
115 }
116 buffer.resize(2*n);
117 }
118 return buffer;
119}
120
121template<typename T>
123 if (input.is_stdin())
124 return read_stdin_into_buffer();
125 if (input.is_compressed())
126 return input.uncompress_into_buffer();
127 return read_file_into_buffer(input.path());
128}
129
130} // namespace gemmi
131#endif
void swap_eight_bytes(void *start)
Definition fileutil.hpp:89
void swap_four_bytes(void *start)
Definition fileutil.hpp:83
CharArray read_into_buffer(T &&input)
Definition fileutil.hpp:122
std::unique_ptr< std::FILE, decltype(&std::fclose)> fileptr_t
Definition fileutil.hpp:37
CharArray read_stdin_into_buffer()
Definition fileutil.hpp:107
std::size_t file_size(std::FILE *f, const std::string &path)
Definition fileutil.hpp:61
std::wstring UTF8_to_wchar(const char *in)
Definition utf.hpp:12
bool is_little_endian()
Definition fileutil.hpp:73
std::string path_basename(const std::string &path, std::initializer_list< const char * > exts)
Definition fileutil.hpp:23
fileptr_t file_open(const char *path, const char *mode)
Definition fileutil.hpp:39
void swap_two_bytes(void *start)
Definition fileutil.hpp:78
GEMMI_COLD void sys_fail(const std::string &msg)
Definition fail.hpp:71
CharArray read_file_into_buffer(const std::string &path)
Definition fileutil.hpp:98
fileptr_t file_open_or(const char *path, const char *mode, std::FILE *dash_stream)
Definition fileutil.hpp:54