]> git.lyx.org Git - lyx.git/blob - src/xtl/autobuf.h
more FILMagain stuff
[lyx.git] / src / xtl / autobuf.h
1 /* Automatic buffer driver for XTL
2  *
3  * Copyright (C) 2000 Allan Rae, allan.rae@mailbox.uq.edu.au
4  * Copyright (C) 1998-2000 Jose' Orlando Pereira, jop@di.uminho.pt
5  */
6 /* XTL - eXternalization Template Library - http://gsd.di.uminho.pt/~jop/xtl
7  * Copyright (C) 1998-2000 Jose' Orlando Pereira, Universidade do Minho
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  * 
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  * 
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the Free
21  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
22  * MA 02111-1307, USA
23  *
24  * Id: autobuf.h 1.4 Fri, 05 May 2000 18:57:58 +0100 jop 
25  */
26
27 #ifndef __XTL_AUTOBUF
28 #define __XTL_AUTOBUF
29
30 #include <xtl/config.h>
31 #include <xtl/objio.h>
32
33 /** Based on mem_buffer.  It automatically increases it's capacity when being
34     written too.  It still throws an exception if there is insufficient data
35     when reading.  As a result the input and output routines memory handling
36     had to be separated (mem_buffer uses the same code for both) into required
37     memory (input) and desired memory (output). ARRae 20000423
38     
39     Possible improvements:
40     auto_mem_buffer(char *, size_t)  same constructor as mem_buffer
41     reserve(size_t)                  make it bigger if need be.
42     
43     Rewrite XTL to use an iterator interface; at least at the buffer level.
44 */
45 class auto_mem_buffer {
46 public:
47         class buffer_overflow_error: public std::overflow_error {
48         public:
49                 int bytes_left;
50                 int bytes_needed;
51
52                 buffer_overflow_error(int left, int needed):
53                         std::overflow_error("XTL auto_mem_buffer overflow"),
54                              bytes_left(left),bytes_needed(needed) {}
55         };
56
57         auto_mem_buffer() : buffer(0), pos(0), lim(32) {
58                 buffer = new char[lim];
59         }
60
61         auto_mem_buffer(size_t size) : buffer(0), pos(0), lim(4) {
62                 // the smallest useful size is probably 8 bytes (4*2)
63                 do {
64                         lim *= 2;
65                 } while (lim < size);
66                 buffer = new char[lim];
67         }
68
69 // I haven't figured out why yet but this code causes a segfault upon
70 // destruction of the copy after the destruction of the original.
71 // HOWEVER, this only occurs in LyX, it doesn't occur in my test program
72 // which is almost identical to the way LyX operates.  The major differences
73 // between LyX and the test program are the presense of libsigc++ and xforms.
74 // The contents of the mem buffer are used to build up an xforms dialog.
75 // ARRae 20000423
76 //
77 //      auto_mem_buffer(auto_mem_buffer const & o)
78 //              : buffer(0), pos(o.pos), lim(o.lim) {
79 //              buffer = new char[lim];
80 //              memcpy(buffer, o.buffer, (pos > 0) ? pos : lim);
81 //      }
82
83         ~auto_mem_buffer() {
84                 delete[] buffer;
85         }
86
87         inline void read(char* ptr, int size) {
88                 memcpy(ptr, require(size), size);
89         }
90
91         inline void write(char const* ptr, int size) {
92                 memcpy(desire(size), ptr, size);
93         }
94
95         inline void* require(int size) {
96                 size_t aux = pos;
97                 if ((pos += size) > lim)
98                         throw buffer_overflow_error(lim - aux, size);
99                 return buffer + aux;
100         }
101
102         inline void* desire(int size) {
103                 size_t const aux = pos;
104                 if ((pos += size) > lim) {
105                         do {
106                                 lim *= 2;
107                         } while (lim < pos);
108                         char * tmp = new char[lim];
109                         memcpy(tmp, buffer, aux);
110                         delete[] buffer;
111                         buffer = tmp;
112                 }
113                 return buffer + aux;
114         }
115
116         inline void flush()
117                 {}
118
119         inline void unrequire(int n)
120                 { pos -= n; }
121
122         inline void undesire(int n)
123                 { pos -= n; }
124
125         inline void rewind()
126                 { pos = 0; }
127
128         inline int size()
129                 { return pos; }
130
131         inline char* data()
132                 { return buffer; }
133
134         template <class Format>
135         inline void composite(obj_input<Format>& stream) {
136                 int size, idx;
137                 stream.array(buffer, size).simple(idx);
138                 pos = idx;
139                 lim = size;
140                 count = 1;
141         }
142         
143         template <class Format>
144         inline void composite(obj_output<Format>& stream) {
145                 stream.array(buffer, lim).simple(pos);
146         }
147 private:
148         auto_mem_buffer(auto_mem_buffer const &);
149
150         char * buffer;
151         size_t pos, lim;        
152 };
153
154 #endif
155