Merge branch 'master' of git.dyninst.org:/pub/dyninst
[dyninst.git] / patchAPI / h / Buffer.h
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30 #if !defined(PATCHAPI_H_BUFFER_H_)
31 #define PATCHAPI_H_BUFFER_H_
32
33 #include <assert.h>
34 #include <string.h>
35 #include "dyntypes.h"
36
37 namespace Dyninst {
38 namespace PatchAPI {
39
40 // A class to support multiple forms of code generation. The design of this class is as 
41 // a tiered model:
42
43 // Tier 1: A buffer of bytes that represent position-dependent executable code
44 // Tier 2: A buffer that supports linker-style relocations of raw instructions
45 // Tier 3: A buffer that supports relocatable and optimizer-friendly instruction objects
46
47 // The current implementation supports tier 1. In that, it is a cut-down version of the
48 // Dyninst internal codeGen structure that aims to be more user-friendly. Tiers 2 and 3 
49 // are TODO. 
50
51 class PATCHAPI_EXPORT Buffer {
52   public:
53    Buffer(Address addr, unsigned initial_size);
54    ~Buffer();
55
56    static const int ALLOCATION_UNIT;
57
58    template <class InputIterator>
59       void copy(InputIterator begin, InputIterator end);
60
61    unsigned size() const;
62    unsigned max_size() const;
63    bool empty() const;
64
65    template <class Input>
66       void push_back(const Input &);
67
68    template <class storage>
69       class iterator {
70       friend class Buffer;
71
72      public:
73      iterator() : pos((storage *)-1) {};
74       ~iterator() {};
75       storage operator*() const {
76          assert(valid);
77          return *pos;
78       }
79
80       bool operator==(const iterator<storage> &rhs) const {
81          return rhs.pos == pos; 
82       }
83       bool operator!=(const iterator<storage> &rhs) const {
84          return rhs.pos != pos;
85       }
86       iterator<storage> operator++() {
87          assert(valid);
88          iterator<storage> i = *this;
89          ++pos;
90          return i;
91       }
92          
93       iterator<storage> operator++(int) {
94          assert(valid);
95          ++pos;
96          return *this;
97       }
98
99      private:
100       bool valid() const { return pos != (storage *)-1; };
101      iterator(storage *start) : pos(start) {};
102       storage *pos;
103    };
104
105    typedef iterator<unsigned char> byte_iterator;
106    typedef iterator<unsigned int> word_iterator;
107    typedef iterator<unsigned long> long_iterator;
108
109    byte_iterator begin() const;
110    byte_iterator end() const;
111
112    word_iterator w_begin() const;
113    word_iterator w_end() const;
114    
115    long_iterator l_begin() const;
116    long_iterator l_end() const;
117
118    unsigned char *start_ptr() const { return buffer_; }
119
120    Address curAddr() const { return start_ + size_; }
121
122   private:
123    // May call realloc();
124    void increase_allocation(int added);
125    unsigned char * cur_ptr() const;
126
127    unsigned char * buffer_;
128    unsigned size_;
129    unsigned max_;
130
131    Address start_;
132 };
133
134 template <class InputIterator> 
135    void Buffer::copy(InputIterator begin, InputIterator end) {
136    while (begin != end) {
137       push_back(*begin);
138       ++begin;
139    }
140 };
141
142
143
144 template <class Input> 
145    void Buffer::push_back(const Input &i) {
146    if (size_ + sizeof(i) >= max_) {
147       increase_allocation(sizeof(i));
148    }
149    Input *ptr = (Input *)cur_ptr();
150    *ptr = i;
151    size_ += sizeof(i);
152 };
153
154 }
155 }
156
157 #endif