ScopedBstr

 

// Manages a BSTR string pointer.

// The class interface is based on scoped_ptr.

class ScopedBstr {

 public:

  ScopedBstr() : bstr_(NULL) {

  }

 

  // Constructor to create a new BSTR.

  // NOTE: Do not pass a BSTR to this constructor expecting ownership to

  // be transferred - even though it compiles! ;-)

  explicit ScopedBstr(const wchar_t* non_bstr);

  ~ScopedBstr();

 

  // Give ScopedBstr ownership over an already allocated BSTR or NULL.

  // If you need to allocate a new BSTR instance, use |allocate| instead.

  void Reset(BSTR bstr = NULL);

 

  // Releases ownership of the BSTR to the caller.

  BSTR Release();

 

  // Creates a new BSTR from a wide string.

  // If you already have a BSTR and want to transfer ownership to the

  // ScopedBstr instance, call |reset| instead.

  // Returns a pointer to the new BSTR, or NULL if allocation failed.

  BSTR Allocate(const wchar_t* wide_str);

 

  // Allocates a new BSTR with the specified number of bytes.

  // Returns a pointer to the new BSTR, or NULL if allocation failed.

  BSTR AllocateBytes(int bytes);

 

  // Sets the allocated length field of the already-allocated BSTR to be

  // |bytes|.  This is useful when the BSTR was preallocated with e.g.

  // SysAllocStringLen or SysAllocStringByteLen (call |AllocateBytes|) and

  // then not all the bytes are being used.

  // Note that if you want to set the length to a specific number of characters,

  // you need to multiply by sizeof(wchar_t).  Oddly, there's no public API to

  // set the length, so we do this ourselves by hand.

  //

  // NOTE: The actual allocated size of the BSTR MUST be >= bytes.

  //  That responsibility is with the caller.

  void SetByteLen(uint32 bytes);

 

  // Swap values of two ScopedBstr's.

  void Swap(ScopedBstr& bstr2);

 

  // Retrieves the pointer address.

  // Used to receive BSTRs as out arguments (and take ownership).

  // The function DCHECKs on the current value being NULL.

  // Usage: GetBstr(bstr.Receive());

  BSTR* Receive();

 

  // Returns number of chars in the BSTR.

  uint32 Length() const;

 

  // Returns the number of bytes allocated for the BSTR.

  uint32 ByteLength() const;

 

  operator BSTR() const {

    return bstr_;

  }

 

 protected:

  BSTR bstr_;

 

 private:

  // Forbid comparison of ScopedBstr types.  You should never have the same

  // BSTR owned by two different scoped_ptrs.

  bool operator==(const ScopedBstr& bstr2) const;

  bool operator!=(const ScopedBstr& bstr2) const;

  DISALLOW_COPY_AND_ASSIGN(ScopedBstr);

};

 

 

ScopedBstr::ScopedBstr(const wchar_t* non_bstr)

    : bstr_(SysAllocString(non_bstr)) {

}

 

ScopedBstr::~ScopedBstr() {

  COMPILE_ASSERT(sizeof(ScopedBstr) == sizeof(BSTR), ScopedBstrSize);

  SysFreeString(bstr_);

}

 

void ScopedBstr::Reset(BSTR bstr) {

  if (bstr != bstr_) {

    // if |bstr_| is NULL, SysFreeString does nothing.

    SysFreeString(bstr_);

    bstr_ = bstr;

  }

}

 

BSTR ScopedBstr::Release() {

  BSTR bstr = bstr_;

  bstr_ = NULL;

  return bstr;

}

 

void ScopedBstr::Swap(ScopedBstr& bstr2) {

  BSTR tmp = bstr_;

  bstr_ = bstr2.bstr_;

  bstr2.bstr_ = tmp;

}

 

BSTR* ScopedBstr::Receive() {

  DCHECK(bstr_ == NULL) << "BSTR leak.";

  return &bstr_;

}

 

BSTR ScopedBstr::Allocate(const wchar_t* wide_str) {

  Reset(SysAllocString(wide_str));

  return bstr_;

}

 

BSTR ScopedBstr::AllocateBytes(int bytes) {

  Reset(SysAllocStringByteLen(NULL, bytes));

  return bstr_;

}

 

void ScopedBstr::SetByteLen(uint32 bytes) {

  DCHECK(bstr_ != NULL) << "attempting to modify a NULL bstr";

  uint32* data = reinterpret_cast<uint32*>(bstr_);

  data[-1] = bytes;

}

 

uint32 ScopedBstr::Length() const {

  return SysStringLen(bstr_);

}

 

uint32 ScopedBstr::ByteLength() const {

  return SysStringByteLen(bstr_);

}

 

發佈了60 篇原創文章 · 獲贊 0 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章