1/*
2 * Copyright (c) 2000-2004,2006,2011,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25//
26// cssmalloc - memory allocation in the CDSA world
27//
28#ifndef _H_CSSMALLOC
29#define _H_CSSMALLOC
30
31#include <security_utilities/alloc.h>
32#include <Security/cssm.h>
33#include <cstring>
34
35
36namespace Security
37{
38
39
40//
41// A POD wrapper for the memory functions structure passed around in CSSM.
42//
43class CssmMemoryFunctions : public PodWrapper<CssmMemoryFunctions, CSSM_MEMORY_FUNCS> {
44public:
45	CssmMemoryFunctions(const CSSM_MEMORY_FUNCS &funcs)
46	{ *(CSSM_MEMORY_FUNCS *)this = funcs; }
47	CssmMemoryFunctions() { }
48
49	void *malloc(size_t size) const throw(std::bad_alloc);
50	void free(void *mem) const throw() { free_func(mem, AllocRef); }
51	void *realloc(void *mem, size_t size) const throw(std::bad_alloc);
52	void *calloc(uint32 count, size_t size) const throw(std::bad_alloc);
53
54	bool operator == (const CSSM_MEMORY_FUNCS &other) const throw()
55	{ return !memcmp(this, &other, sizeof(*this)); }
56};
57
58inline void *CssmMemoryFunctions::malloc(size_t size) const throw(std::bad_alloc)
59{
60	if (void *addr = malloc_func(size, AllocRef))
61		return addr;
62	throw std::bad_alloc();
63}
64
65inline void *CssmMemoryFunctions::calloc(uint32 count, size_t size) const throw(std::bad_alloc)
66{
67	if (void *addr = calloc_func(count, size, AllocRef))
68		return addr;
69	throw std::bad_alloc();
70}
71
72inline void *CssmMemoryFunctions::realloc(void *mem, size_t size) const throw(std::bad_alloc)
73{
74	if (void *addr = realloc_func(mem, size, AllocRef))
75		return addr;
76	throw std::bad_alloc();
77}
78
79
80//
81// A Allocator based on CssmMemoryFunctions
82//
83class CssmMemoryFunctionsAllocator : public Allocator {
84public:
85	CssmMemoryFunctionsAllocator(const CssmMemoryFunctions &memFuncs) : functions(memFuncs) { }
86
87	void *malloc(size_t size) throw(std::bad_alloc);
88	void free(void *addr) throw();
89	void *realloc(void *addr, size_t size) throw(std::bad_alloc);
90
91	operator const CssmMemoryFunctions & () const throw() { return functions; }
92
93private:
94	const CssmMemoryFunctions functions;
95};
96
97
98//
99// A MemoryFunctions object based on a Allocator.
100// Note that we don't copy the Allocator object. It needs to live (at least)
101// as long as any CssmAllocatorMemoryFunctions object based on it.
102//
103class CssmAllocatorMemoryFunctions : public CssmMemoryFunctions {
104public:
105	CssmAllocatorMemoryFunctions(Allocator &alloc);
106	CssmAllocatorMemoryFunctions() { /*IFDEBUG(*/ AllocRef = NULL /*)*/ ; }	// later assignment req'd
107
108private:
109	static void *relayMalloc(size_t size, void *ref) throw(std::bad_alloc);
110	static void relayFree(void *mem, void *ref) throw();
111	static void *relayRealloc(void *mem, size_t size, void *ref) throw(std::bad_alloc);
112	static void *relayCalloc(uint32 count, size_t size, void *ref) throw(std::bad_alloc);
113
114	static Allocator &allocator(void *ref) throw()
115	{ return *reinterpret_cast<Allocator *>(ref); }
116};
117
118
119//
120// A generic helper for the unhappily ubiquitous CSSM-style
121// (count, pointer-to-array) style of arrays.
122//
123template <class Base, class Wrapper = Base>
124class CssmVector {
125public:
126    CssmVector(uint32 &cnt, Base * &vec, Allocator &alloc = Allocator::standard())
127        : count(cnt), vector(reinterpret_cast<Wrapper * &>(vec)),
128          allocator(alloc)
129    {
130        count = 0;
131        vector = NULL;
132    }
133
134    ~CssmVector()	{ allocator.free(vector); }
135
136    uint32 &count;
137    Wrapper * &vector;
138    Allocator &allocator;
139
140public:
141    Wrapper &operator [] (uint32 ix)
142    { assert(ix < count); return vector[ix]; }
143
144    void operator += (const Wrapper &add)
145    {
146        vector = reinterpret_cast<Wrapper *>(allocator.realloc(vector, (count + 1) * sizeof(Wrapper)));
147        //@@@???compiler bug??? vector = allocator.alloc<Wrapper>(vector, count + 1);
148        vector[count++] = add;
149    }
150};
151
152
153} // end namespace Security
154
155#endif //_H_CSSMALLOC
156