stdex Additional custom or not Standard C++ covered algorithms

Loading...
Searching...
No Matches
system.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023-2024 Amebis
4*/
5
6#pragma once
7
8#include "compat.hpp"
9#if defined(_WIN32)
10#include "windows.h"
11#include <oaidl.h>
12#include <tchar.h>
13#else
14#ifndef _LARGEFILE64_SOURCE
15#define _LARGEFILE64_SOURCE // TODO: Make this -D compile-time project setting
16#endif
17#include <grp.h>
18#include <pwd.h>
19#include <string.h>
20#include <sys/types.h>
21#include <unistd.h>
22#endif
23#include <regex>
24#include <stdexcept>
25#include <string_view>
26#include <string>
27
28#if defined(_WIN32)
29#define PATH_SEPARATOR '\\'
30#define PATH_SEPARATOR_STR "\\"
31#else
32#define PATH_SEPARATOR '/'
33#define PATH_SEPARATOR_STR "/"
34#endif
35
36 namespace stdex
37{
41#if defined(_WIN32)
42 using sys_handle = HANDLE;
43 const sys_handle invalid_handle = INVALID_HANDLE_VALUE;
44#else
45 using sys_handle = int;
46 const sys_handle invalid_handle = (sys_handle)-1;
47#endif
48
52#if defined(_WIN32)
53 inline DWORD sys_error() { return GetLastError(); }
54#else
55 inline int sys_error() { return errno; }
56#endif
57
61#if defined(_WIN32)
62 using schar_t = TCHAR;
63#else
64 using schar_t = char;
65#endif
66
71 using sys_char = schar_t;
72
76 using sstring = std::basic_string<stdex::schar_t>;
77
82 using sys_string = sstring;
83
87 using sstring_view = std::basic_string_view<stdex::schar_t, std::char_traits<stdex::schar_t>>;
88
92 using sregex = std::basic_regex<stdex::schar_t>;
93
97 struct sys_object_traits
98 {
99 static inline const sys_handle invalid_handle = stdex::invalid_handle;
100
104 static void close(_In_ sys_handle h)
105 {
106#if defined(_WIN32)
107 if (CloseHandle(h) || GetLastError() == ERROR_INVALID_HANDLE)
108 return;
109 throw std::system_error(GetLastError(), std::system_category(), "CloseHandle failed");
110#else
111 if (::close(h) >= 0 || errno == EBADF)
112 return;
113 throw std::system_error(errno, std::system_category(), "close failed");
114#endif
115 }
116
120 static sys_handle duplicate(_In_ sys_handle h, _In_ bool inherit = false)
121 {
122 sys_handle h_new;
123#if defined(_WIN32)
124 HANDLE process = GetCurrentProcess();
125 if (DuplicateHandle(process, h, process, &h_new, 0, inherit, DUPLICATE_SAME_ACCESS))
126 return h_new;
127 throw std::system_error(GetLastError(), std::system_category(), "DuplicateHandle failed");
128#else
129 _Unreferenced_(inherit);
130 if ((h_new = dup(h)) >= 0)
131 return h_new;
132 throw std::system_error(errno, std::system_category(), "dup failed");
133#endif
134 }
135 };
136
140 template <class T = sys_handle, class TR = sys_object_traits>
141 class basic_sys_object
142 {
143 public:
144 basic_sys_object(_In_opt_ T h = TR::invalid_handle) : m_h(h) {}
145
146 basic_sys_object(_In_ const basic_sys_object<T, TR>& other) : m_h(other.m_h != TR::invalid_handle ? TR::duplicate(other.m_h) : TR::invalid_handle) {}
147
148 basic_sys_object& operator =(_In_ const basic_sys_object<T, TR>& other)
149 {
150 if (this != std::addressof(other)) {
151 if (m_h != TR::invalid_handle)
152 TR::close(m_h);
153 m_h = other.m_h != TR::invalid_handle ? TR::duplicate(other.m_h) : TR::invalid_handle;
154 }
155 return *this;
156 }
157
158 basic_sys_object(_Inout_ basic_sys_object<T, TR>&& other) noexcept : m_h(other.m_h)
159 {
160 other.m_h = TR::invalid_handle;
161 }
162
163 basic_sys_object& operator =(_Inout_ basic_sys_object<T, TR>&& other) noexcept
164 {
165 if (this != std::addressof(other)) {
166 if (m_h != TR::invalid_handle)
167 TR::close(m_h);
168 m_h = other.m_h;
169 other.m_h = TR::invalid_handle;
170 }
171 return *this;
172 }
173
174 virtual ~basic_sys_object() noexcept(false)
175 {
176 if (m_h != TR::invalid_handle)
177 TR::close(m_h);
178 }
179
183 virtual void close()
184 {
185 if (m_h != TR::invalid_handle) {
186 TR::close(m_h);
187 m_h = TR::invalid_handle;
188 }
189 }
190
194 operator bool() const noexcept { return m_h != TR::invalid_handle; }
195
199 T get() const noexcept { return m_h; }
200
201 protected:
202 T m_h;
203 };
204
208 using sys_object = basic_sys_object<sys_handle, sys_object_traits>;
209
210#ifdef _WIN32
211 template <class T>
212 class safearray_accessor
213 {
214 public:
215 safearray_accessor(_In_ LPSAFEARRAY sa) : m_sa(sa)
216 {
217 HRESULT hr = SafeArrayAccessData(sa, reinterpret_cast<void HUGEP**>(&m_data));
218 if (FAILED(hr))
219 throw std::system_error(hr, std::system_category(), "SafeArrayAccessData failed");
220 }
221
222 ~safearray_accessor()
223 {
224 SafeArrayUnaccessData(m_sa);
225 }
226
227 T* data() const { return m_data; }
228
229 protected:
230 LPSAFEARRAY m_sa;
231 T* m_data;
232 };
233
234 template <class T>
235 class safearray_accessor_with_size : public safearray_accessor<T>
236 {
237 public:
238 safearray_accessor_with_size(_In_ LPSAFEARRAY sa) : safearray_accessor<T>(sa)
239 {
240 m_size = SafeArrayGetElemsize(sa);
241 for (UINT d = 1, dim = SafeArrayGetDim(sa); d <= dim; ++d) {
242 long ubound, lbound;
243 if (FAILED(SafeArrayGetUBound(sa, d, &ubound)) ||
244 FAILED(SafeArrayGetLBound(sa, d, &lbound)))
245 throw std::invalid_argument("SafeArrayGet[UL]Bound failed");
246 m_size *= static_cast<size_t>(ubound) - lbound + 1;
247 }
248 m_size /= sizeof(T);
249 }
250
254 size_t size() const { return m_size; }
255
256 protected:
257 size_t m_size;
258 };
259
263 struct SafeArrayDestroy_delete
264 {
268 void operator()(_In_ LPSAFEARRAY sa) const
269 {
270 SafeArrayDestroy(sa);
271 }
272 };
273
277 struct SysFreeString_delete
278 {
282 void operator()(_In_ BSTR sa) const
283 {
284 SysFreeString(sa);
285 }
286 };
287#endif
288}
stdex::basic_sys_object
Operating system object base class.
Definition system.hpp:142
stdex::basic_sys_object::close
virtual void close()
Closes object.
Definition system.hpp:183
stdex::basic_sys_object::get
T get() const noexcept
Returns object handle.
Definition system.hpp:199
stdex::sys_object_traits
System object operations.
Definition system.hpp:98
stdex::sys_object_traits::duplicate
static sys_handle duplicate(sys_handle h, bool inherit=false)
Duplicates given object.
Definition system.hpp:120
stdex::sys_object_traits::close
static void close(sys_handle h)
Closes object.
Definition system.hpp:104