summaryrefslogblamecommitdiffstats
path: root/squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.h
blob: c27e7c803e4c810a1e04c0b463a4c97e24a3bbff (plain) (tree)
































































































































































































                                                                                                           

#ifndef SQPLUS_OCHARBUF_H
#define SQPLUS_OCHARBUF_H

// Conversion routines between different character encodings, to be used in
// Push/Get/Match handlers of SqPlus. It enables using both of char* and 
// wchar_t* as function arguments.
//
// When converting from wchar_t to char, the choice is between using a Latin1 
// or a UTF8 representation in 8-bit mode. This is probably most useful if 
// Squirrel is compiled in ANSI mode and the app uses some wchar_t strings 
// (UNICODE mode on Win32). 
//

// A char is either
//  - A Latin1 character (first code page, coincides with Unicode points 0..255)
//  - Part of an UTF8 character
//
// Note: SQUTF8 requires Squirrel sources that have been patched for UTF8 strings 
// internally (when converting function arguments). 

#ifndef SQUTF8
  // Default to Latin1 conversion 
  //#undef SQPLUS_USE_LATIN1
  #ifndef SQPLUS_USE_LATIN1
    #define SQPLUS_USE_LATIN1 1
  #endif
#else
  // Using Squirrel with internal UTF8 string encoding 
  //#undef SQPLUS_USE_LATIN1
  #ifndef SQPLUS_USE_LATIN1
    #define SQPLUS_USE_LATIN1 0
  #endif
#endif 
 

// The various ol_... functions sets up for a conversion scheme 
// that can be used in both wchar_t => char and  char => wchar_t.
int ol_strlen(const wchar_t* pwc);
int ol_buflen(const wchar_t* pwc);
int ol_charlen(const wchar_t* pwc);
int ol_char(const wchar_t* pwc);
bool ol_writechar(wchar_t*& pwc, int ch);

int ol_strlen(const char* pc);
int ol_buflen(const char* pc);
int ol_charlen(const char* pc);
int ol_char(const char* pc);
bool ol_writechar(char*& pc, int ch);

#ifdef SQUNICODE
  // SQChar is wchar_t, convert to/from either Latin1 or UTF8
  typedef char SQOtherChar;
#else
  // SQChar is char, convert to/from wchar_t
  typedef wchar_t SQOtherChar;
#endif


// Buffer to hold a string and release it in destructor. 
// SQT is input character type 
// SQOT is the opposite type of SQChar
// If 'try_borrow' is set, it will not allocate a new buffer when no 
// conversion is done, it will just keep the input pointer (beware).
template<class SQT, class SQOT, bool use_latin1>
struct SQCharBufImpl {

	// Allocate a buffer from string of same type
	SQCharBufImpl(const SQT *poc=NULL, bool try_borrow=true ) : m_poc(0), m_own(false) { 
		Init( poc, try_borrow );
	}

	// This does conversion from other char type
	SQCharBufImpl(const SQOT *ps, bool try_borrow=false ) : m_poc(0), m_own(false) { 
		Init( ps ); // Cannot borrow pointer when doing conversion
	}

	void Init( const SQT *poc, bool try_borrow ){
		m_own = !try_borrow;
		if( try_borrow ){ 
			m_poc = (SQT*)poc;
		}
		else {
			int sl = poc ? ol_buflen(poc) : 0;
			if( poc ){
				m_poc = poc ? new SQT[sl+1] : NULL; 
				if( m_poc ) memcpy( m_poc, poc, (sl+1)*sizeof(SQT) );
			}
			else
				m_poc = NULL;
		}
    }

	void Init( const SQOT *ps ){
		m_own = true;
        if( ps ){
            int sl = ps ? ol_strlen(ps) : 0;	// Length of string in characters (not bytes)
		    int scl = 0;                        // Length of converted string in char/wchar_t count
			// How much storage needed? 
			if( !use_latin1 && sizeof(SQT)<sizeof(SQOT) ){
				// Converting wchar_t => UTF8 
				const SQOT *ps1 = ps;   // It is wchar_t* here
				SQT tmp_buf[8];
				SQT *ptmp;
				while( *ps1 ){
				    ptmp = tmp_buf;
                    if( ol_writechar(ptmp,*ps1++) )
                        scl += ol_charlen(tmp_buf);
                    else
                        scl++;
				}
			}
			else scl = sl;  // Converting to wchar_t or Latin1, keep length 

            m_poc = new SQT[scl+1]; 
			if( !m_poc ) return;

			// Convert 
			SQT *poc = m_poc;
			while( *ps ){
				ol_writechar( poc, ol_char(ps) );
				ps += ol_charlen(ps);
			}
			*poc = 0;	// Terminating zero
        }
        else
            m_poc = NULL;
    }
    
    ~SQCharBufImpl(){ Release(); }
    
	void Release( ){
		if(m_poc && m_own ) 
			delete [] m_poc; 
		m_poc = NULL;
	}

	SQT* Set( const SQOT *ps ){
		Release( );
		Init( ps );
		return m_poc;
	}

    operator SQT*() const { return m_poc; }
    
	SQCharBufImpl<SQT,SQOT,use_latin1>& operator = (const SQT *ps){
		Release();
		Init( ps, false );
		return *this;
	}

	SQCharBufImpl<SQT,SQOT,use_latin1>& operator = (const SQOT *ps){
		Release();
		Init( ps );
		return *this;
	}

	// Move string from other here - Note: Empties the input argument (other)
	SQCharBufImpl<SQT,SQOT,use_latin1>& operator = (const SQCharBufImpl<SQT,SQOT,use_latin1>& other){
		Release();
		m_poc = other.m_poc;
		m_own = other.m_own;
		SQT **psqt = (SQT**)&other.m_poc;
		*psqt = NULL;
		return *this;
	}

protected:
    SQT *m_poc;
	bool m_own;
};

typedef SQCharBufImpl<SQOtherChar, SQChar, bool(SQPLUS_USE_LATIN1)> SQOthCharBuf;
typedef SQCharBufImpl<SQChar, SQOtherChar, bool(SQPLUS_USE_LATIN1)> SQDefCharBuf;
typedef SQCharBufImpl<wchar_t, char, bool(SQPLUS_USE_LATIN1)>       SQWCharBuf;
typedef SQCharBufImpl<char, wchar_t, bool(SQPLUS_USE_LATIN1)>       SQACharBuf;

#ifdef SQUNICODE
  // SQChar is wchar_t, convert to/from to either Latin1 or UTF8
  #define WC2SQ(s) s
  #define SQ2WC(s) s
  SQDefCharBuf CH2SQ( const char* ps );
  SQOthCharBuf SQ2CH( const wchar_t* pws );
#else
  // SQChar is char, convert to/from wchar_t
  SQDefCharBuf WC2SQ( const wchar_t* pws );
  SQOthCharBuf SQ2WC( const char* pws );
  #define CH2SQ(s) s
  #define SQ2CH(s) s
#endif

#endif // SQPLUS_CHARBUF_H