Skip to content

Commit 8bfd7e7

Browse files
authored
Merge pull request #9 from sandsmark/master
make it possible to specify window bits, and possible to specify parameters from zstr::istream/ostream. several bug fixes and platform compatibility things.
2 parents a55d56e + ca26b9b commit 8bfd7e7

File tree

3 files changed

+272
-121
lines changed

3 files changed

+272
-121
lines changed

src/strict_fstream.hpp

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
#ifndef __STRICT_FSTREAM_HPP
2-
#define __STRICT_FSTREAM_HPP
1+
#pragma once
32

43
#include <cassert>
54
#include <fstream>
65
#include <cstring>
76
#include <string>
7+
#include <vector>
88

99
/**
1010
* This namespace defines wrappers for std::ifstream, std::ofstream, and
@@ -16,42 +16,67 @@
1616
*/
1717
namespace strict_fstream
1818
{
19-
/// Overload of error-reporting function, to enable use with VS (1)
20-
/// and POSIX signature found in MUSL on Alpine (2)
21-
/// Ref 1: http://stackoverflow.com/a/901316/717706
22-
/// Ref 2: http://stackoverflow.com/a/41956165
23-
static inline char* strerror_r_compat(int result, char* buffer, int err)
24-
{
25-
if (result)
26-
{
27-
sprintf(buffer, "Unknown error: %d", err);
28-
}
29-
return buffer;
30-
}
3119

32-
static inline char* strerror_r_compat(char* result, char*, int)
20+
// Help people out a bit, it seems like this is a common recommenation since
21+
// musl breaks all over the place.
22+
#if defined(__NEED_size_t) && !defined(__MUSL__)
23+
#warning "It seems to be recommended to patch in a define for __MUSL__ if you use musl globally: https://www.openwall.com/lists/musl/2013/02/10/5"
24+
#define __MUSL__
25+
#endif
26+
27+
// Workaround for broken musl implementation
28+
// Since musl insists that they are perfectly compatible, ironically enough,
29+
// they don't officially have a __musl__ or similar. But __NEED_size_t is defined in their
30+
// relevant header (and not in working implementations), so we can use that.
31+
#ifdef __MUSL__
32+
#warning "Working around broken strerror_r() implementation in musl, remove when musl is fixed"
33+
#endif
34+
35+
// Non-gnu variants of strerror_* don't necessarily null-terminate if
36+
// truncating, so we have to do things manually.
37+
inline std::string trim_to_null(const std::vector<char> &buff)
3338
{
34-
return result;
39+
std::string ret(buff.begin(), buff.end());
40+
41+
const std::string::size_type pos = ret.find('\0');
42+
if (pos == std::string::npos) {
43+
ret += " [...]"; // it has been truncated
44+
} else {
45+
ret.resize(pos);
46+
}
47+
return ret;
3548
}
3649

50+
/// Overload of error-reporting function, to enable use with VS and non-GNU
51+
/// POSIX libc's
52+
/// Ref:
53+
/// - http://stackoverflow.com/a/901316/717706
3754
static std::string strerror()
3855
{
39-
std::string buff(80, '\0');
56+
// Can't use std::string since we're pre-C++17
57+
std::vector<char> buff(256, '\0');
58+
4059
#ifdef _WIN32
41-
if (strerror_s(&buff[0], buff.size(), errno) != 0)
42-
{
43-
buff = "Unknown error";
60+
// Since strerror_s might set errno itself, we need to store it.
61+
const int err_num = errno;
62+
if (strerror_s(buff.data(), buff.size(), err_num) != 0) {
63+
return trim_to_null(buff);
64+
} else {
65+
return "Unknown error (" + std::to_string(err_num) + ")";
66+
}
67+
#elif ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600 || defined(__APPLE__)) && ! _GNU_SOURCE) || defined(__MUSL__)
68+
// XSI-compliant strerror_r()
69+
const int err_num = errno; // See above
70+
if (strerror_r(err_num, buff.data(), buff.size()) == 0) {
71+
return trim_to_null(buff);
72+
} else {
73+
return "Unknown error (" + std::to_string(err_num) + ")";
4474
}
4575
#else
46-
auto p = strerror_r_compat(strerror_r(errno, &buff[0], buff.size()), &buff[0], errno);
47-
std::string tmp(p, std::strlen(p));
48-
std::swap(buff, tmp);
76+
// GNU-specific strerror_r()
77+
char * p = strerror_r(errno, &buff[0], buff.size());
78+
return std::string(p, std::strlen(p));
4979
#endif
50-
if(buff.find('\0') != std::string::npos)
51-
{
52-
buff.resize(buff.find('\0'));
53-
}
54-
return buff;
5580
}
5681

5782
/// Exception class thrown by failed operations.
@@ -136,7 +161,7 @@ struct static_method_holder
136161
is_p->peek();
137162
peek_failed = is_p->fail();
138163
}
139-
catch (const std::ios_base::failure &e) {}
164+
catch (const std::ios_base::failure &) {}
140165
if (peek_failed)
141166
{
142167
throw Exception(std::string("strict_fstream: open('")
@@ -210,4 +235,3 @@ class fstream
210235

211236
} // namespace strict_fstream
212237

213-
#endif

0 commit comments

Comments
 (0)