Update contrib.
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // SQL parser tokeniser
20 // optimised tables for ASCII character set
22 const TUint8 KAlpha=0x1;
23 const TUint8 KDigitOr_=0x2;
25 const TUint8 KCharAttrib[]=
27 KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,KDigitOr_,
28 KDigitOr_,KDigitOr_,0,0,0,0,0,0,
29 0,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,
30 KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,
31 KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,
32 KAlpha,KAlpha,KAlpha,0,0,0,0,KDigitOr_,
33 0,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,
34 KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,
35 KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,KAlpha,
39 #define ISALPHA(aChar) (TUint(aChar-'0')<=TUint('z'-'0') && KCharAttrib[aChar-'0']&KAlpha)
40 #define ISALPHA_DIGIT_OR_(aChar) (TUint(aChar-'0')<=TUint('z'-'0') && KCharAttrib[aChar-'0']&(KAlpha|KDigitOr_))
41 #define LCASE(aChar) (aChar|0x20)
44 // These are always stored as ASCII because DBMS has its own
46 const TInt KMaxKeywordLength=9;
48 static const TText8 KSqlKeywords[][KMaxKeywordLength+1]=
54 const TInt KSqlKeywordCount=sizeof(KSqlKeywords)/sizeof(*KSqlKeywords);
56 #if defined(_ASSERTIONS)
59 // ensure that the keyword table is in alphabetical order
62 for (TInt ii=1;ii<KSqlKeywordCount;++ii)
63 __ASSERT(TPtrC8(KSqlKeywords[ii-1])<TPtrC8(KSqlKeywords[ii]));
70 TInt TSqlLexer::CompareKeyword(TInt aKeyword,const RSqlLiteral& aIdentifier)
72 // Check if the identifer in aIdentifier is a keyword
73 // uses a case-insensitive match, not folding
76 __ASSERT(TUint(aKeyword)<TUint(KSqlKeywordCount));
78 const TText* ptr=aIdentifier.Ptr();
79 const TText* end=aIdentifier.End();
80 const TText8* pk=&KSqlKeywords[aKeyword][0];
88 TInt d=ck-LCASE(TUint(*ptr++));
94 TSqlKeyword TSqlLexer::Keyword(const TSqlToken& aToken)
96 // non-member function: Return the keyword value
99 if (aToken==ESqlIdentifier)
101 TInt r=KSqlKeywordCount;
106 TInt k=CompareKeyword(m,aToken.Literal());
112 return TSqlKeyword(m); // keyword
116 return ESqlNotKeyword;
119 TSqlLexer::TSqlLexer(const TDesC& aSql)
120 : iNext(aSql.Ptr()),iEnd(iNext+aSql.Length())
122 __ASSERT(CheckKeywords());
125 TSqlTokenType TSqlLexer::GetIdentifier(TSqlToken& aToken)
127 // Get a keyword or identifier. Do not resolve a keyword at this stage
130 const TText* end=iEnd;
131 const TText* next=iNext-1;
135 if (ISALPHA_DIGIT_OR_(ch))
137 if (!TChar(ch).IsAlphaDigit())
140 aToken.iLiteral.SetText(iNext-1,next);
142 return ESqlIdentifier;
145 TInt TSqlLexer::GetInteger(TInt64 &aVal)
147 // A rather more optimised version of TLex::Val(TInt64&)
148 // initially accumulate the value in a TUint32, and only switch to 64-bit arithmetic
149 // if the value overflows. Always return a 64-bit value
152 const TUint KPreMultiplyLimit32=429496728; //(KMaxTUint-9)/10
153 const TUint KPreMultiplyLimit64=214748364; //(KMaxTInt+1)/10
155 const TText* ptr=iNext;
156 const TText* const end=iEnd;
175 return KErrGeneral; // no digits at all
182 if (val32>KPreMultiplyLimit32)
183 goto overflow64; // will not fit into 32 bit arithmetic
187 // we have result, just set the sign and finish
191 // continue the accumulation with a 64-bit integer
203 if (I64HIGH(aVal)>KPreMultiplyLimit64)
204 return KErrOverflow; // the value is certain to overflow
206 if (I64HIGH(aVal)&0x80000000u)
207 { // greater than the "half way mark"
220 TSqlTokenType TSqlLexer::GetNumber(TSqlToken& aToken)
222 const TText* mark=--iNext; // rewind past initial character
223 // attempt to parse a integer
224 TInt r=GetInteger(aToken.iLiteral.SetInt());
230 if (c!='.' && c!='e' && c!='E')
231 return ESqlLiteralInt; // it is an integer
234 return ESqlLiteralInt; // it is an integer
236 TLex lex(TPtrC(mark,iEnd-mark));
237 r=lex.Val(aToken.iLiteral.SetReal(),TChar('.'));
240 iNext=mark+lex.Offset();
241 return ESqlLiteralReal;
244 TSqlTokenType TSqlLexer::GetString(TSqlToken& aToken)
246 const TText* next=iNext;
247 const TText* end=iEnd;
262 aToken.iLiteral.SetText(iNext,next-1);
264 return ESqlLiteralText;
267 TSqlTokenType TSqlLexer::GetDate(TSqlToken& aToken)
269 const TText* end=iEnd;
270 const TText* next=iNext;
275 } while (*next++!='#');
276 TInt r=aToken.iLiteral.SetTime().Parse(TPtrC(iNext,(next-1)-iNext));
280 return ESqlLiteralTime;
283 TSqlTokenType TSqlLexer::GetNextToken(TSqlToken& aToken)
285 const TText* ptr=iNext;
286 const TText* const end=iEnd;
295 case ' ': // a "normal" space
297 case '0': case '1': case '2': case '3': case '4': // literal number
298 case '5': case '6': case '7': case '8': case '9':
299 case '+': case '-': case '.':
300 return GetNumber(aToken);
302 return GetString(aToken);
304 return GetDate(aToken);
310 return ESqlLeftBracket;
312 return ESqlRightBracket;
321 return ESqlLessEqual;
336 return ESqlGreaterEqual;
344 return GetIdentifier(aToken); // keyword or identifier
347 return GetIdentifier(aToken); // keyword or identifier
353 const TText* TSqlLexer::Next() const
357 void TSqlLexer::Set(const TText* aNext)