blob: cf85c42607a20820013b35d7007d9cda1ee5bdf2 [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Abstract interfaces and support. This is a set of "protocols", a concept
20 * borrowed from other object oriented languages, to define interfaces for
21 * low level services. By using a protocol base class which offers both
22 * virtuals and support methods only, one can easily stack and share these
23 * as common base classes without having to consider when the final derived
24 * object implements them. Core protocol methods always are tagged with a
25 * _ prefix to make it easier to track their derivation.
26 * @file ucommon/protocols.h
27 * @author David Sugar <dyfet@gnutelephony.org>
28 */
29
30#ifndef _UCOMMON_PROTOCOLS_H_
31#define _UCOMMON_PROTOCOLS_H_
32
33#ifndef _UCOMMON_CPR_H_
34#include <ucommon/cpr.h>
35#endif
36
37NAMESPACE_UCOMMON
38
39class String;
40class StringPager;
41
42class __EXPORT MemoryProtocol
43{
44protected:
45 friend class MemoryRedirect;
46
47 /**
48 * Protocol to allocate memory from the pager heap. The size of the
49 * request must be less than the size of the memory page used. The
50 * actual method is in a derived or stacked object.
51 * @param size of memory request.
52 * @return allocated memory or NULL if not possible.
53 */
54 virtual void *_alloc(size_t size) = 0;
55
56 /**
57 * Allocation failure handler.
58 */
59 virtual void fault(void) const;
60
61public:
62 virtual ~MemoryProtocol();
63
64 /**
65 * Convenience function.
66 * @param size of memory request.
67 * @return alocated memory or NULL if not possible.
68 */
69 inline void *alloc(size_t size)
70 {return _alloc(size);};
71
72 /**
73 * Allocate memory from the pager heap. The size of the request must be
74 * less than the size of the memory page used. The memory is initialized
75 * to zero. This uses alloc.
76 * @param size of memory request.
77 * @return allocated memory or NULL if not possible.
78 */
79 void *zalloc(size_t size);
80
81 /**
82 * Duplicate NULL terminated string into allocated memory. This uses
83 * alloc.
84 * @param string to copy into memory.
85 * @return allocated memory with copy of string or NULL if cannot allocate.
86 */
87 char *dup(const char *string);
88
89 /**
90 * Duplicate existing memory block into allocated memory. This uses alloc.
91 * @param memory to data copy from.
92 * @param size of memory to allocate.
93 * @return allocated memory with copy or NULL if cannot allocate.
94 */
95 void *dup(void *memory, size_t size);
96};
97
98/**
99 * A redirection base class for the memory protocol. This is used because
100 * sometimes we choose a common memory pool to manage different objects.
101 * @author David Sugar <dyfet@gnutelephony.org>
102 */
103class __EXPORT MemoryRedirect : public MemoryProtocol
104{
105private:
106 MemoryProtocol *target;
107
108public:
109 MemoryRedirect(MemoryProtocol *protocol);
110
111 virtual void *_alloc(size_t size);
112};
113
114/**
115 * Common locking protocol. This is used for objects that may internally
116 * have sync'd functions, directly or in a derived class, that lock the
117 * current object. The default handlers do nothing but offer the virtuals
118 * as a stub.
119 * @author David Sugar <dyfet@gnutelephony.org>
120 */
121class __EXPORT LockingProtocol
122{
123protected:
124 virtual void _lock(void);
125 virtual void _unlock(void);
126
127public:
128 virtual ~LockingProtocol();
129};
130
131/**
132 * Used for forming stream output. We would create a derived class who's
133 * constructor creates an internal string object, and a single method to
134 * extract that string.
135 * @author David Sugar <dyfet@gnutelephony.org>
136 */
137class __EXPORT PrintProtocol
138{
139public:
140 virtual ~PrintProtocol();
141
142 /**
143 * Extract formatted string for object.
144 */
145 virtual const char *_print(void) const = 0;
146};
147
148/**
149 * Used for processing input. We create a derived class that processes a
150 * single character of input, and returns a status value. EOF means it
151 * accepts no more input and any value other than 0 is a character to also
152 * unget. Otherwise 0 is good to accept more input. The constructor is
153 * used to reference a final destination object in the derived class.
154 * @author David Sugar <dyfet@gnutelephony.org>
155 */
156class __EXPORT InputProtocol
157{
158public:
159 virtual ~InputProtocol();
160
161 /**
162 * Extract formatted string for object.
163 * @param character code we are pushing.
164 * @return 0 to keep processing, EOF if done, or char to unget.
165 */
166 virtual int _input(int code) = 0;
167};
168
169/**
170 * Common character processing protocol. This is used to access a character
171 * from some type of streaming buffer or memory object.
172 * @author David Sugar <dyfet@gnutelephony.org>
173 */
174class __EXPORT CharacterProtocol
175{
176protected:
177 const char *eol;
178 int back;
179
180 CharacterProtocol();
181
182 /**
183 * Get the next character.
184 * @return next character or EOF.
185 */
186 virtual int _getch(void) = 0;
187
188 /**
189 * Put the next character.
190 * @param code to put.
191 * @return code or EOF if cannot put.
192 */
193 virtual int _putch(int code) = 0;
194
195 /**
196 * Write to back buffer. Mostly used for input format processing.
197 * @param code to write into backbuffer.
198 */
199 inline void putback(int code)
200 {back = code;}
201
202 /**
203 * Set end of line marker. Normally this is set to cr & lf, which
204 * actually supports both lf alone and cr/lf termination of lines.
205 * However, putline() will always add the full cr/lf if this mode is
206 * used. This option only effects getline() and putline().
207 * @param string for eol for getline and putline.
208 */
209 inline void seteol(const char *string)
210 {eol = string;};
211
212public:
213 virtual ~CharacterProtocol();
214
215 /**
216 * Get the next character.
217 * @return next character or EOF.
218 */
219 inline int getchar(void)
220 {return _getch();};
221
222 /**
223 * Put the next character.
224 * @param code to put.
225 * @return code or EOF if cannot put.
226 */
227 inline int putchar(int code)
228 {return _putch(code);};
229
230 size_t print(const PrintProtocol& format);
231
232 size_t input(InputProtocol& format);
233
234 /**
235 * Get text as a line of input from the buffer. The eol character(s)
236 * are used to mark the end of a line. Because the end of line character
237 * is stripped, the length of the string may be less than the actual
238 * count read. If at the end of the file buffer and unable to read more
239 * data an error occured then 0 is returned.
240 * @param string to save input into.
241 * @param size limit of string to save.
242 * @return count of characters actually read or 0 if at end of data.
243 */
244 size_t getline(char *string, size_t size);
245
246 /**
247 * Get a string as a line of input from the buffer. The eol character(s)
248 * are used to mark the end of a line. Because the end of line character
249 * is stripped, the length of the string may be less than the actual
250 * count read. If at the end of the file buffer and unable to read more
251 * data an error occured then 0 is returned.
252 * @param buffer to save input into.
253 * @return count of characters actually read or 0 if at end of data.
254 */
255 size_t getline(String& buffer);
256
257 /**
258 * Put a string as a line of output to the buffer. The eol character is
259 * appended to the end.
260 * @param string to write.
261 * @return total characters successfully written, including eol chars.
262 */
263 size_t putline(const char *string);
264
265 size_t putchars(const char *string, size_t count = 0);
266
267 /**
268 * Load input to a string list. The string list filter method is used to
269 * control loading.
270 * @param list to load into.
271 * @return number of items loaded.
272 */
273 size_t load(StringPager *list);
274
275 /**
276 * Save output from a string list.
277 * @param list to save from.
278 * @return number of items loaded.
279 */
280 size_t save(const StringPager *list);
281};
282
283/**
284 * Common buffer protocol class. This is used to create objects which will
285 * stream character data as needed. This class can support bidirectional
286 * streaming as may be needed for serial devices, sockets, and pipes. The
287 * buffering mechanisms are hidden from derived classes, and two virtuals
288 * are used to communicate with the physical transport.
289 * @author David Sugar <dyfet@gnutelephony.org>
290 */
291class __EXPORT BufferProtocol : public CharacterProtocol
292{
293public:
294 typedef enum {RDONLY, WRONLY, RDWR} mode_t;
295
296private:
297 char *buffer;
298 char *input, *output;
299 size_t bufsize, bufpos, insize, outsize;
300 bool end;
301
302protected:
303 const char *format;
304
305 /**
306 * Construct an empty (unallocated) buffer.
307 */
308 BufferProtocol();
309
310 /**
311 * Construct a buffer of pre-allocated size and access type.
312 * @param size of buffer to allocate.
313 * @param access mode of buffer.
314 */
315 BufferProtocol(size_t size, mode_t access = RDWR);
316
317 /**
318 * Destroy object by releasing buffer memory.
319 */
320 virtual ~BufferProtocol();
321
322 /**
323 * Allocation error handler.
324 */
325 virtual void fault(void) const;
326
327 /**
328 * Allocate I/O buffer(s) of specified size. If a buffer is currently
329 * allocated, it is released.
330 * @param size of buffer to allocate.
331 * @param access mode of buffer.
332 */
333 void allocate(size_t size, mode_t access = RDWR);
334
335 /**
336 * Release (free) buffer memory.
337 */
338 void release(void);
339
340 /**
341 * Request workspace in output buffer. This returns a pointer to
342 * memory from the output buffer and advances the output position.
343 * This is sometimes used for a form of zero copy write.
344 * @param size of request area.
345 * @return data pointer or NULL if not available.
346 */
347 char *request(size_t size);
348
349 /**
350 * Gather returns a pointer to contiguous input of specified size.
351 * This may require moving the input data in memory.
352 * @param size of gather space.
353 * @return data pointer to gathered data or NULL if not available.
354 */
355 char *gather(size_t size);
356
357 /**
358 * Method to push buffer into physical i/o (write). The address is
359 * passed to this virtual since it is hidden as private.
360 * @param address of data to push.
361 * @param size of data to push.
362 * @return number of bytes written, 0 on error.
363 */
364 virtual size_t _push(const char *address, size_t size) = 0;
365
366 /**
367 * Method to pull buffer from physical i/o (read). The address is
368 * passed to this virtual since it is hidden as private.
369 * @param address of buffer to pull data into.
370 * @param size of buffer area being pulled..
371 * @return number of read written, 0 on error or end of data.
372 */
373 virtual size_t _pull(char *address, size_t size) = 0;
374
375 /**
376 * Method to get low level i/o error.
377 * @return error from low level i/o methods.
378 */
379 virtual int _err(void) const = 0;
380
381 /**
382 * Method to clear low level i/o error.
383 */
384 virtual void _clear(void) = 0;
385
386 /**
387 * Return true if blocking.
388 */
389 virtual bool _blocking(void);
390
391 /**
392 * Check if data is pending.
393 */
394 virtual bool _pending(void);
395
396 /**
397 * Flush buffer to physical i/o.
398 */
399 virtual bool _flush(void);
400
401 virtual int _getch(void);
402
403 virtual int _putch(int ch);
404
405 /**
406 * Get current input position. Sometimes used to help compute and report
407 * a "tell" offset.
408 * @return offset of input buffer.
409 */
410 inline size_t input_pending(void)
411 {return bufpos;};
412
413 /**
414 * Get current output position. Sometimes used to help compute a
415 * "trunc" operation.
416 */
417 inline size_t output_waiting(void)
418 {return outsize;};
419
420public:
421 const char *endl(void)
422 {return eol;}
423
424 /**
425 * Put memory into the buffer. If count is 0 then put as NULL
426 * terminated string.
427 * @param address of characters to put into buffer.
428 * @param count of characters to put into buffer.
429 * @return number of characters actually written.
430 */
431 size_t put(const void *address, size_t count);
432
433 /**
434 * Get memory from the buffer.
435 * @param address of characters save from buffer.
436 * @param count of characters to get from buffer.
437 * @return number of characters actually copied.
438 */
439 size_t get(void *address, size_t count);
440
441 /**
442 * Print formatted string to the buffer. The maximum output size is
443 * the buffer size, and the operation flushes the buffer.
444 * @param format string.
445 * @return number of bytes written.
446 */
447 size_t printf(const char *format, ...) __PRINTF(2, 3);
448
449 /**
450 * Flush buffered memory to physical I/O.
451 * @return true on success, false if not active or fails.
452 */
453 inline bool flush(void)
454 {return _flush();}
455
456 /**
457 * Purge any pending input or output buffer data.
458 */
459 void purge(void);
460
461 /**
462 * Reset input buffer state. Drops any pending input.
463 */
464 void reset(void);
465
466 /**
467 * Check if at end of input.
468 * @return true if end of data, false if input still buffered.
469 */
470 bool eof(void);
471
472 /**
473 * See if buffer open.
474 * @return true if buffer active.
475 */
476 inline operator bool()
477 {return buffer != NULL;}
478
479 /**
480 * See if buffer closed.
481 * @return true if buffer inactive.
482 */
483 inline bool operator!()
484 {return buffer == NULL;}
485
486 /**
487 * See if buffer open.
488 * @return true if buffer active.
489 */
490 inline bool is_open(void)
491 {return buffer != NULL;}
492
493 /**
494 * See if input active.
495 * @return true if input active.
496 */
497 inline bool is_input(void)
498 {return input != NULL;}
499
500 /**
501 * See if output active.
502 * @return true if output active.
503 */
504 inline bool is_output(void)
505 {return output != NULL;}
506
507 /**
508 * See if pending input.
509 * @return true if input pending.
510 */
511 inline bool is_pending(void)
512 {return _pending();}
513
514 /**
515 * Set eof flag.
516 */
517 inline void seteof(void)
518 {end = true;}
519
520 inline int err(void)
521 {return _err();}
522
523 template<typename T> inline size_t write(const T& data)
524 {return put(&data, sizeof(T));}
525
526 template<typename T> inline size_t read(T& data)
527 {return get(&data, sizeof(T));}
528
529 template<typename T> inline size_t write(const T* data, unsigned count)
530 {return put(data, sizeof(T) * count) / sizeof(T);}
531
532 template<typename T> inline size_t read(T* data, unsigned count)
533 {return get(data, sizeof(T) * count) / sizeof(T);}
534
535};
536
537/**
538 * A common base class for all managed objects. This is used to manage
539 * objects that might be linked or reference counted. The base class defines
540 * only core virtuals some common public methods that should be used by
541 * all inherited object types.
542 * @author David Sugar <dyfet@gnutelephony.org>
543 */
544class __EXPORT ObjectProtocol
545{
546public:
547 /**
548 * Method to retain (or increase retention) of an object.
549 */
550 virtual void retain(void) = 0;
551
552 /**
553 * Method to release (or decrease retention) of an object.
554 */
555 virtual void release(void) = 0;
556
557 /**
558 * Required virtual destructor.
559 */
560 virtual ~ObjectProtocol();
561
562 /**
563 * Retain (increase retention of) object when copying.
564 */
565 ObjectProtocol *copy(void);
566
567 /**
568 * Increase retention operator.
569 */
570 inline void operator++(void)
571 {retain();};
572
573 /**
574 * Decrease retention operator.
575 */
576 inline void operator--(void)
577 {release();};
578};
579
580/**
581 * At least with gcc, linking of stream operators was broken. This provides
582 * an auxillory class to solve the issue.
583 */
584class __EXPORT _character_operators
585{
586private:
587 inline _character_operators() {};
588
589public:
590 static CharacterProtocol& print(CharacterProtocol& p, const char *s);
591
592 static CharacterProtocol& print(CharacterProtocol& p, const char& ch);
593
594 static CharacterProtocol& input(CharacterProtocol& p, char& ch);
595
596 static CharacterProtocol& input(CharacterProtocol& p, String& str);
597
598 static CharacterProtocol& print(CharacterProtocol& p, const long& value);
599
600 static CharacterProtocol& input(CharacterProtocol& p, long& value);
601
602 static CharacterProtocol& print(CharacterProtocol& p, const double& value);
603
604 static CharacterProtocol& input(CharacterProtocol& p, double& value);
605};
606
607inline CharacterProtocol& operator<< (CharacterProtocol& p, const char *s)
608 {return _character_operators::print(p, s);}
609
610inline CharacterProtocol& operator<< (CharacterProtocol& p, const char& ch)
611 {return _character_operators::print(p, ch);}
612
613inline CharacterProtocol& operator>> (CharacterProtocol& p, char& ch)
614 {return _character_operators::input(p, ch);}
615
616inline CharacterProtocol& operator>> (CharacterProtocol& p, String& str)
617 {return _character_operators::input(p, str);}
618
619inline CharacterProtocol& operator<< (CharacterProtocol& p, const PrintProtocol& format)
620 {p.print(format); return p;}
621
622inline CharacterProtocol& operator>> (CharacterProtocol& p, InputProtocol& format)
623 {p.input(format); return p;}
624
625inline CharacterProtocol& operator<< (CharacterProtocol& p, const StringPager& list)
626 {p.save(&list); return p;}
627
628inline CharacterProtocol& operator>> (CharacterProtocol& p, StringPager& list)
629 {p.load(&list); return p;}
630
631inline CharacterProtocol& operator<< (CharacterProtocol& p, const long& value)
632 {return _character_operators::print(p, value);}
633
634inline CharacterProtocol& operator>> (CharacterProtocol& p, long& value)
635 {return _character_operators::input(p, value);}
636
637inline CharacterProtocol& operator<< (CharacterProtocol& p, const double& value)
638 {return _character_operators::print(p, value);}
639
640inline CharacterProtocol& operator>> (CharacterProtocol& p, double& value)
641 {return _character_operators::input(p, value);}
642
643END_NAMESPACE
644
645#endif