summaryrefslogtreecommitdiff
path: root/l10ntools/inc/tagtest.hxx
blob: f301a3539bcf2a1925d772351a69602cdd86f82f (plain)
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
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _TAGTEST_HXX_
#define _TAGTEST_HXX_

#include <tools/string.hxx>
#include <tools/list.hxx>
#include <hash_map> /* std::hashmap*/
#include <vector>

class GSILine;

typedef USHORT TokenId;

#define TOK_INVALIDPOS  USHORT( 0xFFFF )

class ParserMessage;
typedef ::std::vector< ParserMessage* > Impl_ParserMessageList;

class ParserMessageList;

struct equalByteString{
        bool operator()( const ByteString& rKey1, const ByteString& rKey2 ) const {
            return rKey1.CompareTo( rKey2 )==COMPARE_EQUAL;
    }
};
struct lessByteString{
        bool operator()( const ByteString& rKey1, const ByteString& rKey2 ) const {
            return rKey1.CompareTo( rKey2 )==COMPARE_LESS;
    }
};

struct hashByteString{
    size_t operator()( const ByteString& rName ) const{
                std::hash< const char* > myHash;
                return myHash( rName.GetBuffer() );
    }
};



typedef std::hash_map<ByteString , String , hashByteString,equalByteString>
                                StringHashMap;

class TokenInfo
{
private:
    void SplitTag( ParserMessageList &rErrorList );

    String aTagName;
    StringHashMap aProperties;
    BOOL bClosed;    // tag is closed  <sdnf/>
    BOOL bCloseTag;  // tag is close Tag  </sdnf>


    BOOL bIsBroken;
    BOOL bHasBeenFixed;
    BOOL bDone;

public:

    String aTokenString;
    TokenId nId;
    USHORT nPos;            // Position in String

    TokenInfo():bClosed(FALSE),bCloseTag(FALSE),bIsBroken(FALSE),bHasBeenFixed(FALSE),bDone(FALSE),nId( 0 ){;}
explicit    TokenInfo( TokenId pnId, USHORT nP ):bClosed(FALSE),bCloseTag(FALSE),bIsBroken(FALSE),bHasBeenFixed(FALSE),bDone(FALSE),nId( pnId ),nPos(nP){;}
explicit    TokenInfo( TokenId pnId, USHORT nP, String paStr ):bClosed(FALSE),bCloseTag(FALSE),bIsBroken(FALSE),bHasBeenFixed(FALSE),bDone(FALSE),aTokenString( paStr ),nId( pnId ),nPos(nP) {;}
explicit    TokenInfo( TokenId pnId, USHORT nP, String paStr, ParserMessageList &rErrorList );

    String GetTagName() const;

    String MakeTag() const;

    /**
        Is the property to be ignored or does it have the default value anyways
    **/
    BOOL IsPropertyRelevant( const ByteString &aName, const String &aValue ) const;
    BOOL IsPropertyValueValid( const ByteString &aName, const String &aValue ) const;
    /**
        Does the property contain the same value for all languages
        e.g.: the href in a link tag
    **/
    BOOL IsPropertyInvariant( const ByteString &aName, const String &aValue ) const;
    /**
        a subset of IsPropertyInvariant but containing only those that are fixable
        we dont wat to fix e.g.: ahelp :: visibility
    **/
    BOOL IsPropertyFixable( const ByteString &aName ) const;
    BOOL MatchesTranslation( TokenInfo& rInfo, BOOL bGenErrors, ParserMessageList &rErrorList, BOOL bFixTags = FALSE ) const;

    BOOL IsDone() const { return bDone; }
    void SetDone( BOOL bNew = TRUE ) { bDone = bNew; }

    BOOL HasBeenFixed() const { return bHasBeenFixed; }
    void SetHasBeenFixed( BOOL bNew = TRUE ) { bHasBeenFixed = bNew; }
};


class ParserMessageList
{
private:
    Impl_ParserMessageList maList;

public:
    ~ParserMessageList() { clear(); }
    void AddError( USHORT nErrorNr, ByteString aErrorText, const TokenInfo &rTag );
    void AddWarning( USHORT nErrorNr, ByteString aErrorText, const TokenInfo &rTag );

    BOOL HasErrors();
    bool empty() const { return maList.empty(); }
    size_t size() const { return maList.size(); }
    ParserMessage* operator [] ( size_t i ) { return ( i < maList.size() ) ? maList[ i ] : NULL; }
    void clear();
};


#define TAG_GROUPMASK               0xF000
#define TAG_GROUPSHIFT              12

#define TAG_GROUP( nTag )           (( nTag & TAG_GROUPMASK ) >> TAG_GROUPSHIFT )
#define TAG_NOGROUP( nTag )         ( nTag & ~TAG_GROUPMASK )   // ~ = Bitweises NOT

#define TAG_NOMORETAGS              0x0

#define TAG_GROUP_FORMAT            0x1
#define TAG_ON                      0x100
#define TAG_BOLDON                  ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x001 )
#define TAG_BOLDOFF                 ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT |          0x001 )
#define TAG_ITALICON                ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x002 )
#define TAG_ITALICOFF               ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT |          0x002 )
#define TAG_UNDERLINEON             ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT | TAG_ON | 0x004 )
#define TAG_UNDERLINEOFF            ( TAG_GROUP_FORMAT << TAG_GROUPSHIFT |          0x004 )

#define TAG_GROUP_NOTALLOWED        0x2
#define TAG_HELPID                  ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x001 )
#define TAG_MODIFY                  ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x002 )
#define TAG_REFNR                   ( TAG_GROUP_NOTALLOWED << TAG_GROUPSHIFT | 0x004 )

#define TAG_GROUP_STRUCTURE         0x3
#define TAG_NAME                    ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x001 )
#define TAG_HREF                    ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x002 )
#define TAG_AVIS                    ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x004 )
#define TAG_AHID                    ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x008 )

#define TAG_TITEL                   ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x020 )
#define TAG_KEY                     ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x040 )
#define TAG_INDEX                   ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x080 )

#define TAG_REFSTART                ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x100 )

#define TAG_GRAPHIC                 ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x200 )
#define TAG_NEXTVERSION             ( TAG_GROUP_STRUCTURE << TAG_GROUPSHIFT | 0x400 )

#define TAG_GROUP_SYSSWITCH         0x4
#define TAG_WIN                     ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x001 )
#define TAG_UNIX                    ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x002 )
#define TAG_MAC                     ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x004 )
#define TAG_OS2                     ( TAG_GROUP_SYSSWITCH << TAG_GROUPSHIFT | 0x008 )

#define TAG_GROUP_PROGSWITCH        0x5
#define TAG_WRITER                  ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x001 )
#define TAG_CALC                    ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x002 )
#define TAG_DRAW                    ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x004 )
#define TAG_IMPRESS                 ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x008 )
#define TAG_SCHEDULE                ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x010 )
#define TAG_IMAGE                   ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x020 )
#define TAG_MATH                    ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x040 )
#define TAG_CHART                   ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x080 )
#define TAG_OFFICE                  ( TAG_GROUP_PROGSWITCH << TAG_GROUPSHIFT | 0x100 )


#define TAG_GROUP_META              0x6
#define TAG_OFFICEFULLNAME          ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x001 )
#define TAG_OFFICENAME              ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x002 )
#define TAG_OFFICEPATH              ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x004 )
#define TAG_OFFICEVERSION           ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x008 )
#define TAG_PORTALNAME              ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x010 )
#define TAG_PORTALFULLNAME          ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x020 )
#define TAG_PORTALPATH              ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x040 )
#define TAG_PORTALVERSION           ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x080 )
#define TAG_PORTALSHORTNAME         ( TAG_GROUP_META << TAG_GROUPSHIFT | 0x100 )


#define TAG_GROUP_SINGLE            0x7
#define TAG_REFINSERT               ( TAG_GROUP_SINGLE << TAG_GROUPSHIFT | 0x001 )


#define TAG_GROUP_MULTI             0x8
#define TAG_END                     ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x010 )
#define TAG_ELSE                    ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x020 )
#define TAG_AEND                    ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x040 )
#define TAG_VERSIONEND              ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x080 )
#define TAG_ENDGRAPHIC              ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x100 )

#define TAG_GROUP_MISC              0x9
#define TAG_COMMONSTART             ( TAG_GROUP_MISC << TAG_GROUPSHIFT | 0x001 )
#define TAG_COMMONEND               ( TAG_GROUP_MISC << TAG_GROUPSHIFT | 0x002 )

#define TAG_UNKNOWN_TAG             ( TAG_GROUP_MULTI << TAG_GROUPSHIFT | 0x800 )

typedef ::std::vector< TokenInfo* > TokenListImpl;

class TokenList
{
private:
    TokenListImpl maList;
    TokenList&   operator =( const TokenList& rList );

public:
    TokenList() {};
    ~TokenList(){ clear(); };

    size_t size() const { return maList.size(); }
    void clear()
        {
            for ( size_t i = 0 ; i < maList.size() ; i++ )
                delete maList[ i ];
            maList.clear();
        }

    void insert( TokenInfo p, size_t nIndex = LIST_APPEND )
        {
            if ( nIndex < maList.size() ) {
                TokenListImpl::iterator it = maList.begin();
                ::std::advance( it, nIndex );
                maList.insert( it, new TokenInfo(p) );
            } else {
                maList.push_back( new TokenInfo(p) );
            }
        }
    TokenInfo& operator [] ( size_t nIndex ) const
        {
            return *maList[ nIndex ];
        }

    TokenList( const TokenList& rList );
};

class ParserMessage
{
    USHORT nErrorNr;
    ByteString aErrorText;
    USHORT nTagBegin,nTagLength;

protected:
    ParserMessage( USHORT PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag );
public:

    USHORT GetErrorNr() { return nErrorNr; }
    ByteString GetErrorText() { return aErrorText; }

    USHORT GetTagBegin() { return nTagBegin; }
    USHORT GetTagLength() { return nTagLength; }

    virtual ~ParserMessage() {}
    virtual BOOL IsError() =0;
    virtual ByteString Prefix() =0;
};

class ParserError : public ParserMessage
{
public:
    ParserError( USHORT PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag );

    virtual BOOL IsError() {return TRUE;};
    virtual ByteString Prefix() {return "Error:"; };
};

class ParserWarning : public ParserMessage
{
public:
    ParserWarning( USHORT PnErrorNr, ByteString PaErrorText, const TokenInfo &rTag );

    virtual BOOL IsError() {return FALSE;};
    virtual ByteString Prefix() {return "Warning:"; };
};

class SimpleParser
{
private:
    USHORT nPos;
    String aSource;
    String aLastToken;
    TokenList aTokenList;

    TokenInfo aNextTag;     // to store closetag in case of combined tags like <br/>

    String GetNextTokenString( ParserMessageList &rErrorList, USHORT &rTokeStartPos );

public:
    SimpleParser();
    void Parse( String PaSource );
    TokenInfo GetNextToken( ParserMessageList &rErrorList );
    static String GetLexem( TokenInfo const &aToken );
    TokenList& GetTokenList(){ return aTokenList; }
};

class TokenParser
{
    BOOL match( const TokenInfo &aCurrentToken, const TokenId &aExpectedToken );
    BOOL match( const TokenInfo &aCurrentToken, const TokenInfo &aExpectedToken );
    void ParseError( USHORT nErrNr, ByteString aErrMsg, const TokenInfo &rTag );
    void Paragraph();
    void PfCase();
    void PfCaseBegin();
    void AppCase();
    void AppCaseBegin();
    void CaseEnd();
    void SimpleTag();
    void TagPair();
    void TagRef();

    SimpleParser aParser;
    TokenInfo aTag;

    TokenId nPfCaseOptions;
    TokenId nAppCaseOptions;
    BOOL bPfCaseActive ,bAppCaseActive;

    TokenId nActiveRefTypes;

    ParserMessageList *pErrorList;

public:
    TokenParser();
    void Parse( const String &aCode, ParserMessageList* pList );
    TokenList& GetTokenList(){ return aParser.GetTokenList(); }
};

class LingTest
{
private:
    TokenParser aReferenceParser;
    TokenParser aTesteeParser;
    ParserMessageList aCompareWarningList;
    void CheckTags( TokenList &aReference, TokenList &aTestee, BOOL bFixTags );
    BOOL IsTagMandatory( TokenInfo const &aToken, TokenId &aMetaTokens );
    String aFixedTestee;
public:
    void CheckReference( GSILine *aReference );
    void CheckTestee( GSILine *aTestee, BOOL bHasSourceLine, BOOL bFixTags );

    ParserMessageList& GetCompareWarnings(){ return aCompareWarningList; }
    BOOL HasCompareWarnings(){ return ( !aCompareWarningList.empty() ); }

    String GetFixedTestee(){ return aFixedTestee; }
};

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */