1/* 2 * Copyright (c) 2000-2004,2011-2012,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// memstreams - primitive memory block streaming support 27// 28#ifndef _H_MEMSTREAMS 29#define _H_MEMSTREAMS 30 31#include <stdint.h> 32#include <security_utilities/memutils.h> 33#include <security_utilities/endian.h> 34#include <security_utilities/errors.h> 35 36 37namespace Security 38{ 39 40// 41// Encapsulate these very sharp tools in a separate namespace 42// 43namespace LowLevelMemoryUtilities 44{ 45 46 47// 48// A simple utility for incremental creation of a contiguous memory block. 49// 50// Note that Writer and Writer::Counter go together. They use the same alignment 51// and padding rules, so Writer::Counter will correctly calculate total buffer 52// size for Writer, *presuming* that they are called in the same order. 53// 54// This layer allocates no memory; that's up to the caller (you). 55// 56// WARNING: There is no check for overflow. If you write too much, you will die. 57// Writer::Counter can tell you how much you need. 58// 59class Writer { 60private: 61 void *advance(size_t size) 62 { 63 void *here = alignUp(writePos); 64 writePos = increment(here, size); 65 return here; 66 } 67 68public: 69 Writer() { } 70 Writer(void *base) : writePos(base) { } 71 void operator = (void *base) { writePos = base; } 72 73 template <class T> 74 T *operator () (const T &obj) 75 { T *here = (T *)advance(sizeof(T)); *here = obj; return here; } 76 77 void *operator () (const void *addr, size_t size) 78 { void *here = advance(size); return memcpy(here, addr, size); } 79 80 char *operator () (const char *s) 81 { return (char *)(*this)(s, strlen(s) + 1); } 82 83 void countedData(const void *data, size_t length) 84 { 85 if (length > uint32_t(~0)) 86 UnixError::throwMe(ERANGE); 87 Endian<uint32_t> temp = (uint32_t)length; (*this)(temp); (*this)(data, length); 88 } 89 90 template <class Data> 91 void countedData(const Data &data) 92 { countedData(data.data(), data.length()); } 93 94 class Counter; 95 96private: 97 void *writePos; // next byte address 98}; 99 100class Writer::Counter { 101private: 102 void align() { totalSoFar = alignUp(totalSoFar); } 103 104public: 105 Counter() : totalSoFar(0) { } 106 operator size_t () { return totalSoFar; } 107 108 template <class T> size_t operator () (const T &) { align(); return totalSoFar += sizeof(T); } 109 size_t insert(size_t size) { align(); return totalSoFar += size; } 110 size_t operator () (const char *s) { align(); return totalSoFar += strlen(s) + 1; } 111 112 void countedData(const void *, size_t length) 113 { insert(sizeof(length)); insert(length); } 114 115 template <class Data> 116 void countedData(const Data &data) 117 { countedData(data.data(), data.length()); } 118 119private: 120 size_t totalSoFar; // total size counted so far 121}; 122 123 124// 125// The Reader counter-part for a Writer. 126// Again, Reader and Writer share alignment and representation rules, so what was 127// Written shall be Read again, just fine. 128// 129class Reader { 130private: 131 const void *advance(size_t size = 0) 132 { 133 const void *here = alignUp(readPos); 134 readPos = increment(here, size); 135 return here; 136 } 137 138public: 139 Reader() { } 140 Reader(const void *base) : readPos(base) { } 141 void operator = (const void *base) { readPos = base; } 142 143 template <class T> 144 void operator () (T &obj) { obj = *reinterpret_cast<const T *>(advance(sizeof(T))); } 145 void operator () (void *addr, size_t size) { memcpy(addr, advance(size), size); } 146 void operator () (const char * &s) 147 { s = reinterpret_cast<const char *>(advance()); advance(strlen(s) + 1); } 148 template <class T> 149 const T *get(size_t size) 150 { return reinterpret_cast<const T *>(advance(size)); } 151 152 void countedData(const void * &data, size_t &length) 153 { Endian<uint32_t> temp; (*this)(temp); length = temp; data = advance(length); } 154 155private: 156 // Explicitly forbid some invocations that are likely to be wrong. 157 void operator () (char * &s); // can't get writable string in-place 158 159private: 160 const void *readPos; // next byte address 161}; 162 163 164} // end namespace LowLevelMemoryUtilities 165 166} // end namespace Security 167 168#endif //_H_MEMUTILS 169