/usr/include/qpdf/PointerHolder.hh is in libqpdf-dev 8.0.2-3~16.04.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | // Copyright (c) 2005-2018 Jay Berkenbilt
//
// This file is part of qpdf.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Versions of qpdf prior to version 7 were released under the terms
// of version 2.0 of the Artistic License. At your option, you may
// continue to consider qpdf to be licensed under those terms. Please
// see the manual for additional information.
#ifndef __POINTERHOLDER_HH__
#define __POINTERHOLDER_HH__
// This class is basically boost::shared_pointer but predates that by
// several years.
// This class expects to be initialized with a dynamically allocated
// object pointer. It keeps a reference count and deletes this once
// the reference count goes to zero. PointerHolder objects are
// explicitly safe for use in STL containers.
// It is very important that a client who pulls the pointer out of
// this holder does not let the holder go out of scope until it is
// finished with the pointer. It is also important that exactly one
// instance of this object ever gets initialized with a given pointer.
// Otherwise, the pointer will be deleted twice, and before that, some
// objects will be left with a pointer to a deleted object. In other
// words, the only legitimate way for two PointerHolder objects to
// contain the same pointer is for one to be a copy of the other.
// Copy and assignment semantics are well-defined and essentially
// allow you to use PointerHolder as a means to get pass-by-reference
// semantics in a pass-by-value environment without having to worry
// about memory management details.
// Comparison (== and <) are defined and operate on the internally
// stored pointers, not on the data. This makes it possible to store
// PointerHolder objects in sorted lists or to find them in STL
// containers just as one would be able to store pointers. Comparing
// the underlying pointers provides a well-defined, if not
// particularly meaningful, ordering.
template <class T>
class PointerHolder
{
private:
class Data
{
public:
Data(T* pointer, bool array) :
pointer(pointer),
array(array),
refcount(0)
{
}
~Data()
{
if (array)
{
delete [] this->pointer;
}
else
{
delete this->pointer;
}
}
T* pointer;
bool array;
int refcount;
private:
Data(Data const&);
Data& operator=(Data const&);
};
public:
PointerHolder(T* pointer = 0)
{
this->init(new Data(pointer, false));
}
// Special constructor indicating to free memory with delete []
// instead of delete
PointerHolder(bool, T* pointer)
{
this->init(new Data(pointer, true));
}
PointerHolder(PointerHolder const& rhs)
{
this->copy(rhs);
}
PointerHolder& operator=(PointerHolder const& rhs)
{
if (this != &rhs)
{
this->destroy();
this->copy(rhs);
}
return *this;
}
~PointerHolder()
{
this->destroy();
}
bool operator==(PointerHolder const& rhs) const
{
return this->data->pointer == rhs.data->pointer;
}
bool operator<(PointerHolder const& rhs) const
{
return this->data->pointer < rhs.data->pointer;
}
// NOTE: The pointer returned by getPointer turns into a pumpkin
// when the last PointerHolder that contains it disappears.
T* getPointer()
{
return this->data->pointer;
}
T const* getPointer() const
{
return this->data->pointer;
}
int getRefcount() const
{
return this->data->refcount;
}
T const& operator*() const
{
return *this->data->pointer;
}
T& operator*()
{
return *this->data->pointer;
}
T const* operator->() const
{
return this->data->pointer;
}
T* operator->()
{
return this->data->pointer;
}
private:
void init(Data* data)
{
this->data = data;
{
++this->data->refcount;
}
}
void copy(PointerHolder const& rhs)
{
this->init(rhs.data);
}
void destroy()
{
bool gone = false;
{
if (--this->data->refcount == 0)
{
gone = true;
}
}
if (gone)
{
delete this->data;
}
}
Data* data;
};
#endif // __POINTERHOLDER_HH__
|