File:  [parser3project] / parser3 / src / include / pa_pool.h
Revision 1.55: download - view: text, annotated - select for diffs - revision graph
Thu Sep 20 14:25:06 2001 UTC (24 years, 9 months ago) by parser
Branches: MAIN
CVS tags: HEAD
Pool::transcode 0

/** @file
	Parser: pool class decl.

	Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)

	Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)

	$Id: pa_pool.h,v 1.55 2001/09/20 14:25:06 parser Exp $
*/

#ifndef PA_POOL_H
#define PA_POOL_H

#include "pa_config_includes.h"

#include <XalanDOM/XalanDOMString.hpp>
#include <util/TransService.hpp>
#include <PlatformSupport/XSLException.hpp>


// forwards

class Exception;
class Temp_exception;
class String;

void Pool_cleanup(void *);

/** 
	Pool mechanizm allows users not to free up allocated memory,
	leaving that problem to 'pools'.

	Also holds Exception object, which can be temporary set using 
	Temp_exception auto-object.

	@see Pooled
*/

class Pool {
	friend Temp_exception;
	friend void Pool_cleanup(void *);
public:

	Pool(void *astorage);

private:
	void cleanup() {
		delete transcoder;
	}
public:
	void set_context(void *acontext) { fcontext=acontext; }
	void *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);
	}
	/// allocates some bytes clearing them with zeros
	void *calloc(size_t size) {
		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();
	}

	/// current exception object of the pool
	Exception& exception() const { return *fexception; }

	/// resets transcoder if they change charset 
	void set_charset(const String &charset);
	/// converts Xalan string to char *
	const char *transcode(const XalanDOMString& s);
	/// converts XSL exception to parser exception
	void _throw(const String *source, const XSLException& e);

private:

	void set_charset(const char *charset);
	void update_transcoder();

private:

	void *fstorage;
	void *fcontext;
	void *ftag;
	const char *charset;
	XMLTranscoder *transcoder;

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;
	}
	/// throws allocation exception
	void fail_alloc(size_t size) const;

	/// throws register cleanup exception
	void fail_register_cleanup() const;

private: // exception handling

	// exception replacement mechanism is 'private'zed from direct usage
	// Temp_exception object enforces paired set/restore
	Exception *set_exception(Exception *e){
		Exception *r=fexception;
		fexception=e;
		return r;
	}
	void restore_exception(Exception *e) {
		fexception=e;
	}

private:

	// current request's exception object
	Exception *fexception;

private: //disabled

	// Pool(const Pool&) {}
	Pool& operator = (const Pool&) { return *this; }
};

/** 
	Base for all classes that are allocated in 'pools'.

	Holds Pool object. Contains useful wrappers to it's methods.

	@see NEW, Temp_exception
*/
class Pooled {
	// the pool i'm allocated on
	Pool *fpool;
public:

	/// the Pooled-sole: Pooled instances can be allocated in Pool rather then on heap
	static void *operator new(size_t size, Pool& apool) { 
		return apool.malloc(size/*, 1*/);
	}

	Pooled(Pool& apool) : fpool(&apool) {}

	/// 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; }

	/// useful wrapper around pool
	void *malloc(size_t size) const { return fpool->malloc(size); }
	/// useful wrapper around pool
	void *calloc(size_t size) const { return fpool->calloc(size); }
	/// useful wrapper around pool
	void register_cleanup(void (*cleanup) (void *), void *data) { 
		fpool->register_cleanup(cleanup, data);
	}
	/// useful wrapper around pool
	Exception& exception() const { return fpool->exception(); }
	/// useful wrapper around pool
	const char *transcode(const XalanDOMString& s) { return fpool->transcode(s); }
	/// useful wrapper around pool
	void _throw(const String *source, const XSLException& e) { fpool->_throw(source, e); }
};
/// useful macro for creating objects on current Pooled object Pooled::pool()
#define NEW new(pool())

/** 
	Auto-object used for temporary changing Pool's exception().

	Use by with these macros:
	@code
		TRY { 
			// ... 
			if(?) 
				THROW(?); 
			// ...
		} CATCH(e) { 
			// code, using e fields
			// e.comment() 
		}
		END_CATCH
	@endcode

	@see TRY, THROW
*/
class Temp_exception {
	Pool& fpool;
	Exception *saved_exception;
public:
	Temp_exception(Pool& apool, Exception& exception) : 
		fpool(apool),
		saved_exception(apool.set_exception(&exception)) {
	}
	~Temp_exception() { 
		fpool.restore_exception(saved_exception); 
	}
};

#define XTRY(pool) \
	{ \
		Exception temp_exception; \
		Temp_exception le(pool, temp_exception); \
		if(setjmp(temp_exception.mark)==0)

#define XTHROW(exception) exception._throw
#define XCATCH(e) \
		else{ \
			Exception& e=temp_exception;

#define XEND_CATCH \
		} \
	}

//@{
/// @see Temp_exception 
#define TRY XTRY(pool())
#define THROW XTHROW(exception())
#define CATCH(e) XCATCH(e)
#define END_CATCH XEND_CATCH 

#define PTRY XTRY(pool)
#define PTHROW XTHROW(pool.exception())
#define PCATCH(e) XCATCH(e)
#define PEND_CATCH XEND_CATCH 
//@}

#endif

E-mail: