-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBStr.h
107 lines (94 loc) · 2.41 KB
/
BStr.h
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
/*
* Copyright (c) 2022-2024 WangBin <wbsecg1 at gmail.com>
*/
#pragma once
#include <algorithm>
#include <cstdlib>
#include <string>
#include <string.h>
#if (_WIN32 + 0)
# include <oleauto.h>
#endif
class BStr
{
public:
#if (_WIN32 + 0)
using StrType = BSTR; // WCHAR*: length prefix + data string + 0x0000
#elif (__APPLE__ + 0)
using StrType = CFStringRef;
#else
using StrType = char*;
#endif
static std::string to_string(StrType s) {
if (!s)
return {};
#if (_WIN32 + 0)
std::string cs(std::snprintf(nullptr, 0, "%ls", s), 0);
std::snprintf(&cs[0], cs.size() + 1, "%ls", s); // TODO: code page?
return cs;
#elif (__APPLE__ + 0)
if (auto cs = CFStringGetCStringPtr(s, kCFStringEncodingUTF8))
return cs;
const auto utf16length = CFStringGetLength(s);
const auto maxUtf8len = CFStringGetMaximumSizeForEncoding(utf16length, kCFStringEncodingUTF8);
std::string u8s(maxUtf8len, 0);
CFStringGetCString(s, u8s.data(), maxUtf8len, kCFStringEncodingUTF8);
u8s.resize(strlen(u8s.data()));
return u8s;
#else
return s;
#endif
}
BStr() = default;
BStr(const char* s/*utf8*/) {
if (!s)
return;
#if (_WIN32 + 0)
const auto wlen = MultiByteToWideChar(CP_UTF8, 0, s, strlen(s), nullptr, 0); // including null terminator
std::wstring ws(wlen, 0);
MultiByteToWideChar(CP_UTF8, 0, s, strlen(s), &ws[0], ws.size());
s_ = SysAllocString(ws.data());
#elif (__APPLE__ + 0)
s_ = CFStringCreateWithCString(nullptr, s, kCFStringEncodingUTF8);
#else
s_ = strdup(s);
#endif
}
BStr(const BStr&) = delete;
BStr& operator=(const BStr&) = delete;
BStr(BStr&& other) {
std::swap(s_, other.s_);
}
BStr& operator=(BStr&& other) {
std::swap(s_, other.s_);
return *this;
}
// release and get address of. BRawStr is allocated or ref added in GetXXX(BRawStr)
StrType* operator&() {
release();
return &s_;
}
~BStr() {
release();
}
StrType get() {
return s_;
}
std::string to_string() const {
return BStr::to_string(s_);
}
private:
void release() {
if (!s_)
return;
#if (_WIN32 + 0)
SysFreeString(s_);
#elif (__APPLE__ + 0)
CFRelease(s_);
#else
free(s_);
#endif
s_ = {};
}
StrType s_{};
};