]> git.lyx.org Git - lyx.git/blob - src/xtl/objio.h
fix ru.po typo
[lyx.git] / src / xtl / objio.h
1 /*
2  * Core externaliztion utilities
3  *
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: objio.h 1.20 Fri, 05 May 2000 18:57:58 +0100 jop 
25  */
26
27 #ifndef __XTL_OBJIO
28 #define __XTL_OBJIO
29
30 #include <xtl/config.h>
31
32 #include <typeinfo>
33 #include <stdexcept>
34 #include <string>
35
36 template <class Buffer>
37 class generic_format {
38 private:
39         Buffer& buffer;
40 protected:
41         void* require(int n)    {return buffer.require(n);}
42         void unrequire(int n)   {buffer.unrequire(n);}
43         void* desire(int n)     {return buffer.desire(n);}
44         void undesire(int n)    {buffer.undesire(n);}
45
46         void read(char* data, int size)         {buffer.read(data, size);}
47         void write(char const* data, int size)  {buffer.write(data, size);}
48 public:
49         generic_format(Buffer& buf):buffer(buf) {}
50
51         void input_start() {}
52
53         void input_start_composite() {}
54         void input_end_composite() {}
55
56         void input_start_vector() {}
57         void input_end_vector() {}
58
59         virtual void output_start() {}
60
61         void output_start_composite() {}
62         void output_end_composite() {}
63
64         void output_start_vector() {}
65         void output_end_vector() {}
66
67         void reset_buffer() {
68                 buffer.rewind();
69                 output_start();
70         }
71 };
72
73 /*
74                 void input_start_array(int& n) {simple(n);}
75                 bool input_end_array(int& n) {return n--<=0;}
76
77                 void output_start_array(int n) {simple(n);}
78                 void output_end_array() {}
79  */
80
81 template <class Buffer>
82 class raw_format: public generic_format<Buffer> {
83  public:
84         typedef Buffer buffer;
85
86         raw_format(Buffer& buf):generic_format<Buffer>(buf) {}
87         
88         template <class T>
89         inline void input_simple(T& data)
90                 {data=*((T*)require(sizeof(T)));}
91
92         void input_start_array(int& n) {input_simple(n);}
93         bool input_end_array(int& n) {return !(n-->0);}
94
95         void input_chars(char* data, int size) {input_raw(data, size);}
96
97         void input_raw(char* data, int size) {
98                 int i;
99                 for(i=0;i<(size>>8)-1;i++,data+=256)
100                         memcpy(data, require(256), 256);
101                 int res=size-(i<<8);
102                 memcpy(data, require(res), res);
103         }
104
105         template <class T>
106         inline void output_simple(T const& data)
107                 {*((T*)desire(sizeof(T)))=data;}
108
109         void output_start_array(int n) {output_simple(n);}
110         void output_end_array() {}
111
112         void output_chars(char const* data, int size) {output_raw(data, size);}
113
114         void output_raw(char const* data, int size) {
115                 int i;
116                 for(i=0;i<(size>>8)-1;i++,data+=256)
117                         memcpy(desire(256), data, 256);
118                 int res=size-(i<<8);
119                 memcpy(desire(res), data, res);
120         }
121 };
122
123 #ifdef XTL_CONFIG_CHOICE_MACROS
124 #include <xtl/macros.h>
125 #endif
126
127 #ifdef XTL_CONFIG_COMPOSITE_BUG
128 #define content(d) composite(d)
129 #else
130 #define content(d) simple(d)
131 #define array_s array
132 #define vector_s vector
133 #endif
134
135 class no_refs;
136
137 #define def_simple_input(type) \
138         inline obj_input& simple(type& data) { \
139                 format.input_simple(data); \
140                 return *this; \
141         }
142
143 template <class Format, class References=no_refs>
144 class obj_input {
145  private:
146         Format& format;
147         References refs;
148
149  public:
150         obj_input(Format& buf):format(buf)
151                 {format.input_start();}
152
153         def_simple_input(bool);
154         def_simple_input(char);
155         def_simple_input(unsigned char);
156         def_simple_input(short);
157         def_simple_input(unsigned short);
158         def_simple_input(int);
159         def_simple_input(unsigned int);
160         def_simple_input(long);
161         def_simple_input(unsigned long);
162         def_simple_input(longlong);
163         def_simple_input(unsignedlonglong);
164         def_simple_input(float);
165         def_simple_input(double);
166
167         inline obj_input& cstring(char*& data) {
168                 int size;
169                 format.input_start_array(size);
170                 data=new char[size+1];
171                 format.input_chars(data, size);
172                 data[size]=0;
173                 format.input_end_array(size);
174                 return *this;
175         }
176
177         inline obj_input& cstring(char* data, int max) {
178                 int size;
179                 format.input_start_array(size);
180                 format.input_chars(data, size>max?max:size);
181                 data[size>max?max:size]=0;
182                 format.input_end_array(size);
183                 return *this;
184         }
185
186         inline obj_input& simple(std::string& data) {
187                 int size;
188                 format.input_start_array(size);
189                 char* tmp=new char[size];
190                 format.input_chars(tmp, size);
191                 data=std::string(tmp, size);
192                 // FIXME: This causes a crash. Investigate...
193                 //delete[] tmp;
194                 format.input_end_array(size);
195                 return *this;
196         }
197
198         template <class T>
199         inline obj_input& vector(T data[], int size) {
200                 format.input_start_vector();
201                 for(int i=0;i<size;i++)
202                         content(data[i]);
203                 format.input_end_vector();
204                 return *this;
205         }
206
207         template <class T>
208         inline obj_input& array(T*& data, int& size) {
209                 format.input_start_array(size);
210                 data=new T[size];
211                 for(int j=size,i=0;!format.input_end_array(j);i++)
212                         content(data[i]);
213                 return *this;
214         }
215
216 #ifdef XTL_CONFIG_COMPOSITE_BUG
217         template <class T>
218         inline obj_input& vector_s(T data[], int size) {
219                 format.input_start_vector();
220                 for(int i=0;i<size;i++)
221                         simple(data[i]);
222                 format.input_end_vector();
223                 return *this;
224         }
225
226         template <class T>
227         inline obj_input& array_s(T*& data, int& size) {
228                 format.input_start_array(size);
229                 data=new T[size];
230                 for(int j=size,i=0;!format.input_end_array(j);i++)
231                         simple(data[i]);
232                 return *this;
233         }
234 #endif
235
236         inline obj_input& opaque(char data[], int size) {
237                 format.input_start_vector();
238                 format.input_raw(data, size);
239                 format.input_end_vector();
240                 return *this;
241         }
242
243         inline obj_input& bytes(char*& data, int& size) {
244                 int s=size;
245                 format.input_start_array(size);
246                 data=new char[size];
247                 format.input_raw(data, size);
248                 format.input_end_array(s);
249                 return *this;
250         }
251
252         // This is for compilers which do not support specialization
253         // If possible, use simple(T&) below.
254         template <class T>
255         inline obj_input& composite(T& data) {
256                 format.input_start_composite();
257                 ::composite(*this, data);
258                 format.input_end_composite();
259                 return *this;
260         }
261
262 #ifndef XTL_CONFIG_COMPOSITE_BUG
263         template <class T>
264         inline obj_input& simple(T& data) {
265                 format.input_start_composite();
266                 ::composite(*this, data);
267                 format.input_end_composite();
268                 return *this;
269         }
270 #endif  
271
272         template <class T>
273         inline obj_input& reference(T*& data) {
274                 refs.reference(*this, data);
275                 return *this;
276         }
277
278         template <class T>
279         inline obj_input& pointer(T*& data) {
280                 bool exists;
281                 simple(exists);
282                 if (exists) 
283                         reference(data);
284                 return *this;
285         }
286
287         template <class T>
288         inline obj_input& container(T& data) {
289                 int j=0;
290                 format.input_start_array(j);
291                 while(!format.input_end_array(j)) {
292                         typename T::value_type v;
293                         content(v);
294                         data.insert(data.end(), v);
295                 }
296                 return *this;
297         }
298
299 #ifdef XTL_CONFIG_CHOICE_MACROS
300         decl_ich_method(2)
301         decl_ich_method(3)
302         decl_ich_method(4)
303         decl_ich_method(5)
304
305         decl_iobj_method(2)
306         decl_iobj_method(3)
307         decl_iobj_method(4)
308         decl_iobj_method(5)
309 #endif
310 };
311
312 #define def_simple_output(type) \
313         inline obj_output& simple(type const& data) { \
314                 format.output_simple(data); \
315                 return *this; \
316         }
317
318 template <class Format, class References=no_refs>
319 class obj_output {
320  private:
321         Format& format;
322         References refs;
323
324  public:
325         obj_output(Format& buf):format(buf)
326                 {format.output_start();}
327
328         def_simple_output(bool);
329         def_simple_output(char);
330         def_simple_output(unsigned char);
331         def_simple_output(short);
332         def_simple_output(unsigned short);
333         def_simple_output(int);
334         def_simple_output(unsigned int);
335         def_simple_output(long);
336         def_simple_output(unsigned long);
337         def_simple_output(longlong);
338         def_simple_output(unsignedlonglong);
339         def_simple_output(float);
340         def_simple_output(double);
341
342         inline obj_output& cstring(char const* data) {
343                 int size=strlen(data);
344                 format.output_start_array(size);
345                 format.output_chars(data, size);
346                 format.output_end_array();
347                 return *this;
348         }
349
350         inline obj_output& cstring(char const* data, int max) {
351                 int size=strlen(data);
352                 format.output_start_array(size);
353                 format.output_chars(data, size);
354                 format.output_end_array();
355                 return *this;
356         }
357
358         inline obj_output& simple(const std::string& data) {
359                 int size=data.size();
360                 format.output_start_array(size);
361                 format.output_chars(data.data(), size);
362                 format.output_end_array();
363                 return *this;
364         }
365
366         template <class T>
367         inline obj_output& vector(const T data[], int size) {
368                 format.output_start_vector();
369                 for(int i=0;i<size;i++)
370                         content(data[i]);
371                 format.output_end_vector();
372                 return *this;
373         }
374
375         template <class T>
376         inline obj_output& array(T const* data, int size) {
377                 format.output_start_array(size);
378                 for(int i=0;i<size;i++)
379                         content(data[i]);
380                 format.output_end_array();
381                 return *this;
382         }
383 #ifdef XTL_CONFIG_COMPOSITE_BUG
384         template <class T>
385         inline obj_output& vector_s(const T data[], int size) {
386                 format.output_start_vector();
387                 for(int i=0;i<size;i++)
388                         simple(data[i]);
389                 format.output_end_vector();
390                 return *this;
391         }
392
393         template <class T>
394         inline obj_output& array_s(T const* data, int size) {
395                 format.output_start_array(size);
396                 for(int i=0;i<size;i++)
397                         simple(data[i]);
398                 format.output_end_array();
399                 return *this;
400         }
401 #endif
402
403         inline obj_output& opaque(const char data[], int size) {
404                 format.output_start_vector();
405                 format.output_raw(data, size);
406                 format.output_end_vector();
407                 return *this;
408         }
409
410         inline obj_output& bytes(char const* data, int size) {
411                 format.output_start_array(size);
412                 format.output_raw(data, size);
413                 format.output_end_array();
414                 return *this;
415         }
416
417         // This is for compilers which do not support specialization
418         // If possible, use simple(T&) below.
419         template <class T>
420         inline obj_output& composite(T const& data) {
421                 format.output_start_composite();
422                 ::composite(*this, const_cast<T&>(data));
423                 format.output_end_composite();
424                 return *this;
425         }
426
427 #ifndef XTL_CONFIG_COMPOSITE_BUG
428         template <class T>
429         inline obj_output& simple(T const& data) {
430                 format.output_start_composite();
431                 ::composite(*this, const_cast<T&>(data));
432                 format.output_end_composite();
433                 return *this;
434         }
435 #endif
436
437         template <class T>
438         inline obj_output& reference(T const* data) {
439                 refs.reference(*this, data);
440                 return *this;
441         }
442
443         template <class T>
444         inline obj_output& pointer(T const* data) {
445                 bool exists=data!=NULL;
446                 simple(exists);
447                 if (exists)
448                         reference(data);
449                 return *this;
450         }
451
452         template <class T>
453         inline obj_output& container(T const& data) {
454                 int j=data.size();
455                 format.output_start_array(j);
456                 for(typename T::const_iterator i=data.begin();
457                         i!=data.end();
458                         i++)
459                         content(*i);
460                 format.output_end_array();
461                 return *this;
462         }
463
464 #ifdef XTL_CONFIG_CHOICE_MACROS
465         decl_och_method(2)
466         decl_och_method(3)
467         decl_och_method(4)
468         decl_och_method(5)
469
470         decl_oobj_method(2)
471         decl_oobj_method(3)
472         decl_oobj_method(4)
473         decl_oobj_method(5)
474
475 #define option(t) (t*)NULL
476
477 #endif
478 };
479
480 #undef def_simple_input
481 #undef def_simple_output
482
483 template <class Stream, class T>
484 inline void composite(Stream& stream, T& data) {
485         data.composite(stream);
486 }
487
488 class no_refs {
489  public:
490         template <class Format, class T>
491         void reference(obj_input<Format>& stream, T*& data) {
492                 delete data;
493                 data=new T;
494                 stream.content(*data);
495         }
496
497         template <class Format, class T>
498         void reference(obj_output<Format>& stream, T const* data) {
499                 stream.content(*data);
500         }
501 };
502
503 // mem_buffer
504
505 class mem_buffer {
506  private:
507         char *buffer, *ptr, *lim;
508
509  public:
510         class buffer_overflow_error: public std::overflow_error {
511          public:
512                 int bytes_left;
513                 int bytes_needed;
514
515                 buffer_overflow_error(int left, int needed):
516                 std::overflow_error("XTL mem_buffer overflow"),
517                         bytes_left(left),bytes_needed(needed) {}
518         };
519
520         mem_buffer(void *buf, int size):
521                 buffer((char*)buf),ptr((char*)buf),lim(((char*)buf)+size) {}
522
523         inline void read(char* ptr, int size)
524                 {memcpy(ptr, require(size), size);}
525         inline void write(char const* ptr, int size)
526                 {memcpy(desire(size), ptr, size);}
527
528         inline void* require(int size) {
529                 char* aux=ptr;
530                 if ((ptr+=size)>lim)
531                         throw buffer_overflow_error(lim-aux,size);
532                 return aux;
533         }
534         inline void* desire(int size)
535                 {return require(size);}
536         inline void flush()
537                 {}
538
539         inline void unrequire(int n)
540                 {ptr-=n;}
541         inline void undesire(int n)
542                 {unrequire(n);}
543         inline void rewind()
544                 {ptr=buffer;}
545         inline int size()
546                 {return ptr-buffer;}
547         inline char* data()
548                 {return buffer;}
549
550         template <class Format>
551         inline void composite(obj_input<Format>& stream) {
552                 int size, idx;
553                 stream.array(buffer, size).simple(idx);
554                 ptr=buffer+idx;
555                 lim=buffer+size;
556         }
557
558         template <class Format>
559         inline void composite(obj_output<Format>& stream) {
560                 stream.array(buffer, lim-buffer).simple((int)ptr-buffer);
561         }
562
563 };
564
565 #ifdef XTL_CONFIG_SIMPLE_CONTAINERS
566
567 #include <utility>
568 #include <vector>
569 #include <list>
570 #include <map>
571
572 template <class Stream, class T1, class T2>
573 inline void composite(Stream& stream, std::pair<const T1,T2>& data) {
574         stream.simple(const_cast<T1&>(data.first));
575         stream.simple(data.second);
576 }
577
578 template <class Stream, class T1, class T2>
579 inline void composite(Stream& stream, std::pair<T1,T2>& data) {
580         stream.simple(data.first);
581         stream.simple(data.second);
582 }
583
584 template <class Stream, class T>
585 inline void composite(Stream& stream, std::list<T>& data) {
586         stream.container(data);
587 }
588
589 template <class Stream, class T>
590 inline void composite(Stream& stream, std::vector<T>& data) {
591         stream.container(data);
592 }
593
594 template <class Stream, class T1, class T2>
595 inline void composite(Stream& stream, std::map<T1, T2>& data) {
596         stream.container(data);
597 }
598
599 #endif
600
601 #endif