-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
std.custom_unique_ptr.cpp
132 lines (108 loc) · 2.83 KB
/
std.custom_unique_ptr.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright ⓒ 2018-2023 ThePhD.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// See https://github.com/ThePhD/out_ptr/blob/master/docs/out_ptr.adoc for documentation.
#include <ztd/out_ptr/out_ptr.hpp>
#include <assert.hpp>
#include <iostream>
#include <array>
#include <cstdio>
#include <cstddef>
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#else
// Some functions to achieve cross-platform parity
#include <unistd.h>
int fopen_s(FILE** f, const char* name, const char* mode) {
int ret = 0;
OUT_PTR_C_ASSERT(f);
*f = fopen(name, mode);
/* Can't be sure about 1-to-1 mapping of errno and MS' errno_t */
if (!*f)
ret = errno;
return ret;
}
#endif // Windows
struct fd {
int handle;
fd()
: fd(nullptr) {
}
fd(std::nullptr_t)
: handle(static_cast<intptr_t>(-1)) {
}
fd(FILE* f)
#ifdef _WIN32
: handle(f ? _fileno(f) : static_cast<intptr_t>(-1)) {
#else
: handle(f ? fileno(f) : static_cast<intptr_t>(-1)) {
#endif // Windows
}
operator FILE*() const {
if (!*this)
return nullptr;
#ifdef _WIN32
return _fdopen(handle, "rb");
#else
return fdopen(handle, "rb");
#endif // Windows
}
explicit operator bool() const {
return *this != nullptr;
}
bool operator==(std::nullptr_t) const {
return handle == -1;
}
bool operator!=(std::nullptr_t) const {
return handle != -1;
}
bool operator==(const fd& fd) const {
return handle == fd.handle;
}
bool operator!=(const fd& fd) const {
return handle != fd.handle;
}
bool operator==(int fdhandle) const {
return handle == fdhandle;
}
bool operator!=(int fdhandle) const {
return handle != fdhandle;
}
};
struct fd_deleter {
using pointer = fd;
void operator()(fd des) const {
if (des.handle != -1) {
#ifdef _WIN32
_close(des.handle);
#else
close(des.handle);
#endif // Windows
}
}
};
int main() {
std::unique_ptr<int, fd_deleter> my_unique_fd;
auto err = fopen_s(ztd::out_ptr::out_ptr<FILE*>(my_unique_fd), "prod.csv", "r+b");
// check err, then work with fd
if (err != 0) {
// something horrible happened, handle etc. etc.
std::cout << "Error is non-zero, could not open prod.csv with a raw handle." << std::endl;
}
else {
std::cout << "Opened prod.csv with a raw handle!" << std::endl;
}
return 0;
}