Pointer class
Suppose you are writing a C++ program and are linking to a C library. Many of the library calls return a pointer to a heap-allocated structure. You are expected to free that structure using a specialized free function. For example, the openssl library has a BIGNUM type that is typically created using BN_new() and deleted using BN_free(); The following Pointer< BIGNUM, BN_clear_free >
class will take ownership of the BIGNUM pointer in a smart-pointer way and call the BN_free() function when ever the BIGNUM_ptr goes out of scope.
This allows me to exit a function in any of several places (using return or throw) without explicitly freeing memeory.
// Pointer Template
// Copyright 2013 Hal Canary
//
// 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.
#ifndef POINTER_H
#define POINTER_H
#include <cstdlib> // std::free(void *)
namespace Pointers {
/**
A wrapper for the C free function that makes it type-correct. */
template< typename T >
inline void free(T * t_ptr) {
std::free(static_cast< void * >(t_ptr) );
}
/**
A wrapper for the C malloc function that makes it type-correct,
AND multiplies by sizeof(T). */
template< typename T >
inline T * malloc(unsigned int number=1) {
return static_cast< T * >(std::malloc(number * sizeof(T)));
}
}
/**
A wrapper for C pointers that makes them smart pointers.
Example use:
void f() {
static const unsigned int N = 100;
Pointer< char, Pointers::free< char > > str(
Pointers::malloc< char >(N));
sprintf( str, "%d = 0x%04x\n", 0x1234, 0x1234);
std::cout << str;
} */
template< typename T, void (*F)( T *) >
class Pointer {
private:
T * m_ptr;
Pointer(const Pointer &) { /* disallowed */}
public:
Pointer ( T * ptr=NULL )
: m_ptr(ptr) { }
~Pointer () {
if (m_ptr)
F(m_ptr);
}
Pointer & operator=(T * ptr) {
if (m_ptr)
F(m_ptr);
m_ptr = ptr;
return *this;
}
operator T * () { return m_ptr; }
operator T * () const { return m_ptr; }
bool operator!() const { return (! m_ptr); }
T ** operator&() { return &m_ptr; }
T ** operator&() const { return &m_ptr; }
T * operator->() { return m_ptr; }
T * operator->() const { return m_ptr; }
};
#endif /* POINTER_H */
And the main funtion, as promised:
// compile with "-lcrypto"
#include <iostream> // cout
#include <exception> // exception
#include <openssl/bn.h> // BIGNUM
#include "Pointer.h" // Pointer
/**
Convert a long hexidecimal number to decimal. */
int main(int, char **) {
const char hexnumber[]
= "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9";
Pointer< BIGNUM, BN_clear_free > bn(NULL);
if (! BN_hex2bn(&(bn), hexnumber))
throw std::exception();
Pointer< char, Pointers::free< char > > dec(BN_bn2dec(bn));
std::cout << dec << '\n';
return 0;
}