|
|
| version 1.1.1.1, 2001/01/26 14:47:52 | version 1.68, 2001/10/29 13:04:46 |
|---|---|
| Line 1 | Line 1 |
| /* | /** @file |
| Parser: pool class decl. | |
| String Chunk0 | Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) |
| ====== ======== | |
| head_chunk--------->[ptr, size] | |
| append_here-------->[ptr, size] | |
| chunk_link_row ........ | |
| . . | |
| . [ptr, size] | |
| ...........>[link to the next chunk] | |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | |
| $Id$ | |
| */ | */ |
| #ifndef PA_POOL_H | #ifndef PA_POOL_H |
| #define PA_POOL_H | #define PA_POOL_H |
| #include <stddef.h> | #include "pa_config_includes.h" |
| class Pool; | #ifdef XML |
| #include <memory> | |
| #include <XalanDOM/XalanDOMString.hpp> | |
| #include <util/TransService.hpp> | |
| #endif | |
| class String { | // forwards |
| friend Pool; | |
| // the pool I'm allocated on | class Exception; |
| Pool *pool; | class String; |
| // the number of records per chunk | |
| int chunk_items; | |
| enum { | |
| CI_CONST_STRING_GROW=5, | |
| CI_DYNAMIC_STRING_GROW_DEFAULT=10 | |
| }; | |
| struct Chunk { | |
| union Row { | |
| // chunk item | |
| struct { | |
| char *ptr; // pointer to the start of string fragment | |
| size_t size; // length of the fragment | |
| } item; | |
| Chunk *link; // link to the next chunk in chain | |
| } first; | |
| // next rows are here | |
| } | |
| *head_chunk; // the head chunk of the chunk chain | |
| // next append would write to this record | /** |
| Chunk::Row *append_here; | Pool mechanizm allows users not to free up allocated memory, |
| leaving that problem to 'pools'. | |
| // the address of place where lies address | |
| // of the link to the next chunk to allocate | @see Pooled |
| Chunk::Row *chunk_link_row; | */ |
| // new&constructors made private to enforce factory manufacturing at pool | class Pool { |
| void *operator new(size_t size, Pool *apool); | public: |
| void construct(Pool *apool, int achunk_items); | Pool(void *astorage); |
| String(Pool *apool, int achunk_items=CI_DYNAMIC_STRING_GROW_DEFAULT) { | ~Pool(); |
| construct(apool, achunk_items); | |
| void set_context(void *acontext) { fcontext=acontext; } | |
| void *get_context() { return fcontext; } | |
| void set_tag(void *atag) { ftag=atag; } | |
| void *tag() { return ftag; } | |
| /// allocates some bytes on pool | |
| void *malloc(size_t size, int place=0) { | |
| return check(real_malloc(size, place), size); | |
| } | } |
| String(Pool *apool, char *src) { | /// allocates some bytes clearing them with zeros |
| construct(apool, CI_CONST_STRING_GROW); | void *calloc(size_t size) { |
| *this+=src; | return check(real_calloc(size), size); |
| } | |
| /// registers a routine to clean up non-pooled allocations | |
| void register_cleanup(void (*cleanup) (void *), void *data) { | |
| if(!real_register_cleanup(cleanup, data)) | |
| fail_register_cleanup(); | |
| } | } |
| bool chunk_is_full() { | /// resets transcoder if they change charset |
| return append_here == chunk_link_row; | void set_charset(const String &charset); |
| /// returns current charset | |
| const String& get_charset() { return *charset; } | |
| private: | |
| void *fstorage; | |
| void *fcontext; | |
| void *ftag; | |
| const String *charset; | |
| private: | |
| //{ | |
| /// @name implementation defined | |
| void *real_malloc(size_t size, int place); | |
| void *real_calloc(size_t size); | |
| bool real_register_cleanup(void (*cleanup) (void *), void *data); | |
| //} | |
| private: | |
| /// checks whether mem allocated OK. throws exception otherwise | |
| void *check(void *ptr, size_t size) { | |
| if(ptr) | |
| return ptr; | |
| fail_alloc(size); | |
| // never reached | |
| return 0; | |
| } | } |
| void expand(); | /// throws allocation exception |
| void fail_alloc(size_t size) const; | |
| /// throws register cleanup exception | |
| void fail_register_cleanup() const; | |
| #ifdef XML | |
| public: | public: |
| /// converts Xalan string to char * | |
| const char *transcode_cstr(const XalanDOMString& s); | |
| /// converts Xalan string to parser String | |
| String& transcode(const XalanDOMString& s); | |
| /// converts char * to Xalan string | |
| std::auto_ptr<XalanDOMString> transcode_buf(const char *buf, size_t buf_size); | |
| /// converts parser String to Xalan string | |
| std::auto_ptr<XalanDOMString> transcode(const String& s); | |
| private: | |
| void set_charset(const char *new_scharset); | |
| void update_transcoder(); | |
| private: | |
| XMLTranscoder *transcoder; | |
| #endif | |
| size_t size(); | private: //disabled |
| char *c_str(); | |
| String& operator += (char *src); | Pool(const Pool&); |
| Pool& operator= (const Pool&); | |
| }; | }; |
| class Pool { | /** |
| Base for all classes that are allocated in 'pools'. | |
| Holds Pool object. Contains useful wrappers to it's methods. | |
| @see NEW | |
| */ | |
| class Pooled { | |
| // the pool i'm allocated on | |
| Pool *fpool; | |
| public: | public: |
| Pool(); | |
| ~Pool(); | |
| void *alloc(size_t size); | |
| void *calloc(size_t size); | |
| String *makeString() { | /// the Pooled-sole: Pooled instances can be allocated in Pool rather then on heap |
| return new(this) String(this); | static void *operator new(size_t size, Pool& apool) { |
| } | return apool.malloc(size, 1); |
| String *makeString(int chunk_items) { | } |
| return new(this) String(this, chunk_items); | |
| } | Pooled(Pool& apool) : fpool(&apool) {} |
| String *makeString(char *src) { | |
| return new(this) String(this, src); | /// my pool |
| } | Pool& pool() const { return *fpool; } |
| /** used for moving objects from one pool to another. | |
| in between object can have no pool and can not be used | |
| @see SQL_Driver_manager | |
| */ | |
| void set_pool(Pool *apool) { fpool=apool; } | |
| //{ | |
| /// @name useful wrapper around pool | |
| void *malloc(size_t size, int place=0) const { return fpool->malloc(size, place); } | |
| void *calloc(size_t size) const { return fpool->calloc(size); } | |
| void register_cleanup(void (*cleanup) (void *), void *data) { fpool->register_cleanup(cleanup, data); } | |
| #ifdef XML | |
| const char *transcode_cstr(const XalanDOMString& s) { return fpool->transcode_cstr(s); } | |
| String& transcode(const XalanDOMString& s) { return fpool->transcode(s); } | |
| #endif | |
| //} | |
| }; | }; |
| /// useful macro for creating objects on current Pooled object Pooled::pool() | |
| #define NEW new(pool()) | |
| #endif | #endif |