xref: /aosp_15_r20/external/cronet/base/win/scoped_bstr.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2010 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/win/scoped_bstr.h"
6 
7 #include <stdint.h>
8 
9 #include <string_view>
10 
11 #include "base/check.h"
12 #include "base/numerics/safe_conversions.h"
13 #include "base/process/memory.h"
14 #include "base/strings/string_util.h"
15 
16 namespace base {
17 namespace win {
18 
19 namespace {
20 
AllocBstrOrDie(std::wstring_view non_bstr)21 BSTR AllocBstrOrDie(std::wstring_view non_bstr) {
22   BSTR result = ::SysAllocStringLen(non_bstr.data(),
23                                     checked_cast<UINT>(non_bstr.length()));
24   if (!result) {
25     base::TerminateBecauseOutOfMemory((non_bstr.length() + 1) *
26                                       sizeof(wchar_t));
27   }
28   return result;
29 }
30 
AllocBstrBytesOrDie(size_t bytes)31 BSTR AllocBstrBytesOrDie(size_t bytes) {
32   BSTR result = ::SysAllocStringByteLen(nullptr, checked_cast<UINT>(bytes));
33   if (!result)
34     base::TerminateBecauseOutOfMemory(bytes + sizeof(wchar_t));
35   return result;
36 }
37 
38 }  // namespace
39 
ScopedBstr(std::wstring_view non_bstr)40 ScopedBstr::ScopedBstr(std::wstring_view non_bstr)
41     : bstr_(AllocBstrOrDie(non_bstr)) {}
42 
~ScopedBstr()43 ScopedBstr::~ScopedBstr() {
44   static_assert(sizeof(ScopedBstr) == sizeof(BSTR), "ScopedBstrSize");
45   ::SysFreeString(bstr_);
46 }
47 
Reset(BSTR bstr)48 void ScopedBstr::Reset(BSTR bstr) {
49   if (bstr != bstr_) {
50     // SysFreeString handles null properly.
51     ::SysFreeString(bstr_);
52     bstr_ = bstr;
53   }
54 }
55 
Release()56 BSTR ScopedBstr::Release() {
57   BSTR bstr = bstr_;
58   bstr_ = nullptr;
59   return bstr;
60 }
61 
Swap(ScopedBstr & bstr2)62 void ScopedBstr::Swap(ScopedBstr& bstr2) {
63   BSTR tmp = bstr_;
64   bstr_ = bstr2.bstr_;
65   bstr2.bstr_ = tmp;
66 }
67 
Receive()68 BSTR* ScopedBstr::Receive() {
69   DCHECK(!bstr_) << "BSTR leak.";
70   return &bstr_;
71 }
72 
Allocate(std::wstring_view str)73 BSTR ScopedBstr::Allocate(std::wstring_view str) {
74   Reset(AllocBstrOrDie(str));
75   return bstr_;
76 }
77 
AllocateBytes(size_t bytes)78 BSTR ScopedBstr::AllocateBytes(size_t bytes) {
79   Reset(AllocBstrBytesOrDie(bytes));
80   return bstr_;
81 }
82 
SetByteLen(size_t bytes)83 void ScopedBstr::SetByteLen(size_t bytes) {
84   DCHECK(bstr_);
85   uint32_t* data = reinterpret_cast<uint32_t*>(bstr_);
86   data[-1] = checked_cast<uint32_t>(bytes);
87 }
88 
Length() const89 size_t ScopedBstr::Length() const {
90   return ::SysStringLen(bstr_);
91 }
92 
ByteLength() const93 size_t ScopedBstr::ByteLength() const {
94   return ::SysStringByteLen(bstr_);
95 }
96 
97 }  // namespace win
98 }  // namespace base
99