1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 #ifndef _TAGTEST_HXX_ 25 #define _TAGTEST_HXX_ 26 27 #include <tools/string.hxx> 28 #include <tools/list.hxx> 29 #include <hash_map> /* std::hashmap*/ 30 31 class GSILine; 32 33 typedef sal_uInt16 TokenId; 34 35 #define TOK_INVALIDPOS sal_uInt16( 0xFFFF ) 36 37 class ParserMessage; 38 39 DECLARE_LIST( Impl_ParserMessageList, ParserMessage* ) 40 class ParserMessageList; 41 42 43 struct equalByteString{ 44 bool operator()( const ByteString& rKey1, const ByteString& rKey2 ) const { 45 return rKey1.CompareTo( rKey2 )==COMPARE_EQUAL; 46 } 47 }; 48 struct lessByteString{ 49 bool operator()( const ByteString& rKey1, const ByteString& rKey2 ) const { 50 return rKey1.CompareTo( rKey2 )==COMPARE_LESS; 51 } 52 }; 53 54 struct hashByteString{ 55 size_t operator()( const ByteString& rName ) const{ 56 std::hash< const char* > myHash; 57 return myHash( rName.GetBuffer() ); 58 } 59 }; 60 61 62 63 typedef std::hash_map<ByteString , String , hashByteString,equalByteString> 64 StringHashMap; 65 66 class TokenInfo 67 { 68 private: 69 void SplitTag( ParserMessageList &rErrorList ); 70 71 String aTagName; 72 StringHashMap aProperties; 73 sal_Bool bClosed; // tag is closed <sdnf/> 74 sal_Bool bCloseTag; // tag is close Tag </sdnf> 75 76 77 sal_Bool bIsBroken; 78 sal_Bool bHasBeenFixed; 79 sal_Bool bDone; 80 81 public: 82 83 String aTokenString; 84 TokenId nId; 85 sal_uInt16 nPos; // Position in String 86 87 TokenInfo():bClosed(sal_False),bCloseTag(sal_False),bIsBroken(sal_False),bHasBeenFixed(sal_False),bDone(sal_False),nId( 0 ){;} 88 explicit TokenInfo( TokenId pnId, sal_uInt16 nP ):bClosed(sal_False),bCloseTag(sal_False),bIsBroken(sal_False),bHasBeenFixed(sal_False),bDone(sal_False),nId( pnId ),nPos(nP){;} 89 explicit TokenInfo( TokenId pnId, sal_uInt16 nP, String paStr ):bClosed(sal_False),bCloseTag(sal_False),bIsBroken(sal_False),bHasBeenFixed(sal_False),bDone(sal_False),aTokenString( paStr ),nId( pnId ),nPos(nP) {;} 90 explicit TokenInfo( TokenId pnId, sal_uInt16 nP, String paStr, ParserMessageList &rErrorList ); 91 92 String GetTagName() const; 93 94 String MakeTag() const; 95 96 /** 97 Is the property to be ignored or does it have the default value anyways 98 **/ 99 sal_Bool IsPropertyRelevant( const ByteString &aName, const String &aValue ) const; 100 sal_Bool IsPropertyValueValid( const ByteString &aName, const String &aValue ) const; 101 /** 102 Does the property contain the same value for all languages 103 e.g.: the href in a link tag 104 **/ 105 sal_Bool IsPropertyInvariant( const ByteString &aName, const String &aValue ) const; 106 /** 107 a subset of IsPropertyInvariant but containing only those that are fixable 108 we dont wat to fix e.g.: ahelp :: visibility 109 **/ 110 sal_Bool IsPropertyFixable( const ByteString &aName ) const; 111 sal_Bool MatchesTranslation( TokenInfo& rInfo, sal_Bool bGenErrors, ParserMessageList &rErrorList, sal_Bool bFixTags = sal_False ) const; 112 113 sal_Bool IsDone() const { return bDone; } 114 void SetDone( sal_Bool bNew = sal_True ) { bDone = bNew; } 115 116 sal_Bool HasBeenFixed() const { return bHasBeenFixed; } 117 void SetHasBeenFixed( sal_Bool bNew = sal_True ) { bHasBeenFixed = bNew; } 118 }; 119 120 121 class ParserMessageList : public Impl_ParserMessageList 122 { 123 public: 124 void AddError( sal_uInt16 nErrorNr, ByteString aErrorText, const TokenInfo &rTag ); 125 void AddWarning( sal_uInt16 nErrorNr, ByteString aErrorText, const TokenInfo &rTag ); 126 127 sal_Bool HasErrors(); 128 }; 129 130 131 #define TAG_GROUPMASK 0xF000 132 #define TAG_GROUPSHIFT 12 133 134 #define TAG_GROUP( nTag ) (( nTag & TAG_GROUPMASK ) >> TAG_GROUPSHIFT ) 135 #define TAG_NOGROUP( nTag ) ( nTag & ~TAG_GROUPMASK ) // ~ = Bitweises NOT 136 137 #define TAG_NOMORETAGS 0x0 138 139 #define TAG_GROUP_FORMAT 0x1 140 #define TAG_ON 0x100 141 #define TAG_BOLDON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x001 ) 142 #define TAG_BOLDOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x001 ) 143 #define TAG_ITALICON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x002 ) 144 #define TAG_ITALICOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x002 ) 145 #define TAG_UNDERLINEON ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x004 ) 146 #define TAG_UNDERLINEOFF ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | 0x004 ) 147 148 #define TAG_GROUP_NOTALLOWED 0x2 149 #define TAG_HELPID ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x001 ) 150 #define TAG_MODIFY ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x002 ) 151 #define TAG_REFNR ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x004 ) 152 153 #define TAG_GROUP_STRUCTURE 0x3 154 #define TAG_NAME ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x001 ) 155 #define TAG_HREF ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x002 ) 156 #define TAG_AVIS ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x004 ) 157 #define TAG_AHID ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x008 ) 158 159 #define TAG_TITEL ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x020 ) 160 #define TAG_KEY ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x040 ) 161 #define TAG_INDEX ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x080 ) 162 163 #define TAG_REFSTART ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x100 ) 164 165 #define TAG_GRAPHIC ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x200 ) 166 #define TAG_NEXTVERSION ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x400 ) 167 168 #define TAG_GROUP_SYSSWITCH 0x4 169 #define TAG_WIN ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x001 ) 170 #define TAG_UNIX ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x002 ) 171 #define TAG_MAC ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x004 ) 172 #define TAG_OS2 ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x008 ) 173 174 #define TAG_GROUP_PROGSWITCH 0x5 175 #define TAG_WRITER ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x001 ) 176 #define TAG_CALC ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x002 ) 177 #define TAG_DRAW ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x004 ) 178 #define TAG_IMPRESS ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x008 ) 179 #define TAG_SCHEDULE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x010 ) 180 #define TAG_IMAGE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x020 ) 181 #define TAG_MATH ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x040 ) 182 #define TAG_CHART ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x080 ) 183 #define TAG_OFFICE ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x100 ) 184 185 186 #define TAG_GROUP_META 0x6 187 #define TAG_OFFICEFULLNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x001 ) 188 #define TAG_OFFICENAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x002 ) 189 #define TAG_OFFICEPATH ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x004 ) 190 #define TAG_OFFICEVERSION ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x008 ) 191 #define TAG_PORTALNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x010 ) 192 #define TAG_PORTALFULLNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x020 ) 193 #define TAG_PORTALPATH ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x040 ) 194 #define TAG_PORTALVERSION ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x080 ) 195 #define TAG_PORTALSHORTNAME ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x100 ) 196 197 198 #define TAG_GROUP_SINGLE 0x7 199 #define TAG_REFINSERT ( TAG_GROUP_SINGLE << TAG_GROUPSHIFT | 0x001 ) 200 201 202 #define TAG_GROUP_MULTI 0x8 203 #define TAG_END ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x010 ) 204 #define TAG_ELSE ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x020 ) 205 #define TAG_AEND ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x040 ) 206 #define TAG_VERSIONEND ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x080 ) 207 #define TAG_ENDGRAPHIC ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x100 ) 208 209 #define TAG_GROUP_MISC 0x9 210 #define TAG_COMMONSTART ( TAG_GROUP_MISC << TAG_GROUPSHIFT | 0x001 ) 211 #define TAG_COMMONEND ( TAG_GROUP_MISC << TAG_GROUPSHIFT | 0x002 ) 212 213 #define TAG_UNKNOWN_TAG ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x800 ) 214 215 DECLARE_LIST( TokenListImpl, TokenInfo* ) 216 217 class TokenList : private TokenListImpl 218 { 219 private: 220 221 TokenList& operator =( const TokenList& rList ); 222 // { TokenListImpl::operator =( rList ); return *this; } 223 224 225 public: 226 using TokenListImpl::Count; 227 228 229 TokenList() : TokenListImpl(){}; 230 ~TokenList(){ Clear(); }; 231 232 void Clear() 233 { 234 for ( sal_uLong i = 0 ; i < Count() ; i++ ) 235 delete TokenListImpl::GetObject( i ); 236 TokenListImpl::Clear(); 237 } 238 void Insert( TokenInfo p, sal_uLong nIndex = LIST_APPEND ) 239 { TokenListImpl::Insert( new TokenInfo(p), nIndex ); } 240 /* TokenInfo Remove( sal_uLong nIndex ) 241 { 242 TokenInfo aT = GetObject( nIndex ); 243 delete TokenListImpl::GetObject( nIndex ); 244 TokenListImpl::Remove( nIndex ); 245 return aT; 246 }*/ 247 // TokenInfo Remove( TokenInfo p ){ return Remove( GetPos( p ) ); } 248 // TokenInfo GetCurObject() const { return *TokenListImpl::GetCurObject(); } 249 TokenInfo& GetObject( sal_uLong nIndex ) const 250 { 251 // if ( TokenListImpl::GetObject(nIndex) ) 252 return *TokenListImpl::GetObject(nIndex); 253 // else 254 // return TokenInfo(); 255 } 256 /* sal_uLong GetPos( const TokenInfo p ) const 257 { 258 for ( sal_uLong i = 0 ; i < Count() ; i++ ) 259 if ( p == GetObject( i ) ) 260 return i; 261 return LIST_ENTRY_NOTFOUND; 262 }*/ 263 264 TokenList( const TokenList& rList ); 265 /* { 266 for ( sal_uLong i = 0 ; i < rList.Count() ; i++ ) 267 { 268 Insert( rList.GetObject( i ), LIST_APPEND ); 269 } 270 }*/ 271 }; 272 273 class ParserMessage 274 { 275 sal_uInt16 nErrorNr; 276 ByteString aErrorText; 277 sal_uInt16 nTagBegin,nTagLength; 278 279 protected: 280 ParserMessage( sal_uInt16 PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag ); 281 public: 282 283 sal_uInt16 GetErrorNr() { return nErrorNr; } 284 ByteString GetErrorText() { return aErrorText; } 285 286 sal_uInt16 GetTagBegin() { return nTagBegin; } 287 sal_uInt16 GetTagLength() { return nTagLength; } 288 289 virtual ~ParserMessage() {} 290 virtual sal_Bool IsError() =0; 291 virtual ByteString Prefix() =0; 292 }; 293 294 class ParserError : public ParserMessage 295 { 296 public: 297 ParserError( sal_uInt16 PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag ); 298 299 virtual sal_Bool IsError() {return sal_True;}; 300 virtual ByteString Prefix() {return "Error:"; }; 301 }; 302 303 class ParserWarning : public ParserMessage 304 { 305 public: 306 ParserWarning( sal_uInt16 PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag ); 307 308 virtual sal_Bool IsError() {return sal_False;}; 309 virtual ByteString Prefix() {return "Warning:"; }; 310 }; 311 312 class SimpleParser 313 { 314 private: 315 sal_uInt16 nPos; 316 String aSource; 317 String aLastToken; 318 TokenList aTokenList; 319 320 TokenInfo aNextTag; // to store closetag in case of combined tags like <br/> 321 322 String GetNextTokenString( ParserMessageList &rErrorList, sal_uInt16 &rTokeStartPos ); 323 324 public: 325 SimpleParser(); 326 void Parse( String PaSource ); 327 TokenInfo GetNextToken( ParserMessageList &rErrorList ); 328 static String GetLexem( TokenInfo const &aToken ); 329 TokenList& GetTokenList(){ return aTokenList; } 330 }; 331 332 class TokenParser 333 { 334 sal_Bool match( const TokenInfo &aCurrentToken, const TokenId &aExpectedToken ); 335 sal_Bool match( const TokenInfo &aCurrentToken, const TokenInfo &aExpectedToken ); 336 void ParseError( sal_uInt16 nErrNr, ByteString aErrMsg, const TokenInfo &rTag ); 337 void Paragraph(); 338 void PfCase(); 339 void PfCaseBegin(); 340 void AppCase(); 341 void AppCaseBegin(); 342 void CaseEnd(); 343 void SimpleTag(); 344 void TagPair(); 345 void TagRef(); 346 347 SimpleParser aParser; 348 TokenInfo aTag; 349 350 TokenId nPfCaseOptions; 351 TokenId nAppCaseOptions; 352 sal_Bool bPfCaseActive ,bAppCaseActive; 353 354 TokenId nActiveRefTypes; 355 356 ParserMessageList *pErrorList; 357 358 public: 359 TokenParser(); 360 void Parse( const String &aCode, ParserMessageList* pList ); 361 // ParserMessageList& GetErrors(){ return aErrorList; } 362 // sal_Bool HasErrors(){ return ( aErrorList.Count() > 0 ); } 363 TokenList& GetTokenList(){ return aParser.GetTokenList(); } 364 }; 365 366 class LingTest 367 { 368 private: 369 TokenParser aReferenceParser; 370 TokenParser aTesteeParser; 371 ParserMessageList aCompareWarningList; 372 void CheckTags( TokenList &aReference, TokenList &aTestee, sal_Bool bFixTags ); 373 sal_Bool IsTagMandatory( TokenInfo const &aToken, TokenId &aMetaTokens ); 374 String aFixedTestee; 375 public: 376 void CheckReference( GSILine *aReference ); 377 void CheckTestee( GSILine *aTestee, sal_Bool bHasSourceLine, sal_Bool bFixTags ); 378 379 // ParserMessageList& GetReferenceErrors(){ return aReferenceParser.GetErrors(); } 380 // sal_Bool HasReferenceErrors(){ return aReferenceParser.HasErrors(); } 381 382 // ParserMessageList& GetTesteeErrors(){ return aTesteeParser.GetErrors(); } 383 // sal_Bool HasTesteeErrors(){ return aTesteeParser.HasErrors(); } 384 385 ParserMessageList& GetCompareWarnings(){ return aCompareWarningList; } 386 sal_Bool HasCompareWarnings(){ return ( aCompareWarningList.Count() > 0 ); } 387 388 String GetFixedTestee(){ return aFixedTestee; } 389 }; 390 391 #endif 392 393