summaryrefslogtreecommitdiffstats
path: root/squirrel_3_0_1_stable/_OLD_sqplus/SqPlusOCharBuf.h
blob: 24fe16b1660e68acbcf551978c47c009b26665eb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

#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