1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef REMOTING_BASE_TYPED_BUFFER_H_
6#define REMOTING_BASE_TYPED_BUFFER_H_
7
8#include <assert.h>
9
10#include <algorithm>
11
12#include "base/basictypes.h"
13#include "base/move.h"
14
15namespace remoting {
16
17// A scoper for a variable-length structure such as SID, SECURITY_DESCRIPTOR and
18// similar. These structures typically consist of a header followed by variable-
19// length data, so the size may not match sizeof(T). The class supports
20// move-only semantics and typed buffer getters.
21template <typename T>
22class TypedBuffer {
23  MOVE_ONLY_TYPE_FOR_CPP_03(TypedBuffer, RValue)
24
25 public:
26  TypedBuffer() : buffer_(NULL), length_(0) {
27  }
28
29  // Creates an instance of the object allocating a buffer of the given size.
30  explicit TypedBuffer(uint32 length) : buffer_(NULL), length_(length) {
31    if (length_ > 0)
32      buffer_ = reinterpret_cast<T*>(new uint8[length_]);
33  }
34
35  // Move constructor for C++03 move emulation of this type.
36  TypedBuffer(RValue rvalue) : buffer_(NULL), length_(0) {
37    TypedBuffer temp;
38    temp.Swap(*rvalue.object);
39    Swap(temp);
40  }
41
42  ~TypedBuffer() {
43    if (buffer_) {
44      delete[] reinterpret_cast<uint8*>(buffer_);
45      buffer_ = NULL;
46    }
47  }
48
49  // Move operator= for C++03 move emulation of this type.
50  TypedBuffer& operator=(RValue rvalue) {
51    TypedBuffer temp;
52    temp.Swap(*rvalue.object);
53    Swap(temp);
54    return *this;
55  }
56
57  // Accessors to get the owned buffer.
58  // operator* and operator-> will assert() if there is no current buffer.
59  T& operator*() const {
60    assert(buffer_ != NULL);
61    return *buffer_;
62  }
63  T* operator->() const  {
64    assert(buffer_ != NULL);
65    return buffer_;
66  }
67  T* get() const { return buffer_; }
68
69  uint32 length() const { return length_; }
70
71  // Helper returning a pointer to the structure starting at a specified byte
72  // offset.
73  T* GetAtOffset(uint32 offset) {
74    return reinterpret_cast<T*>(reinterpret_cast<uint8*>(buffer_) + offset);
75  }
76
77  // Allow TypedBuffer<T> to be used in boolean expressions, but not
78  // implicitly convertible to a real bool (which is dangerous).
79  typedef T* TypedBuffer::*Testable;
80  operator Testable() const { return buffer_ ? &TypedBuffer::buffer_ : NULL; }
81
82  // Swap two buffers.
83  void Swap(TypedBuffer& other) {
84    std::swap(buffer_, other.buffer_);
85    std::swap(length_, other.length_);
86  }
87
88 private:
89  // Points to the owned buffer.
90  T* buffer_;
91
92  // Length of the owned buffer in bytes.
93  uint32 length_;
94};
95
96}  // namespace remoting
97
98#endif  // REMOTING_BASE_TYPED_BUFFER_H_
99