summaryrefslogtreecommitdiff
path: root/indra/llui/llkeywords.h
blob: 5892238593e45e91ae6469a5615ea7b694e108b7 (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
/**
 * @file llkeywords.h
 * @brief Keyword list for LSL
 *
 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library 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 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#ifndef LL_LLKEYWORDS_H
#define LL_LLKEYWORDS_H


#include "lldir.h"
#include "llstyle.h"
#include "llstring.h"
#include "v3color.h"
#include "v4color.h"
#include <map>
#include <list>
#include <deque>
#include "llpointer.h"

class LLTextSegment;
typedef LLPointer<LLTextSegment> LLTextSegmentPtr;

class LLKeywordToken
{
public:
    /**
     * @brief Types of tokens/delimters being parsed.
     *
     * @desc Tokens/delimiters that need to be identified/highlighted. All are terminated if an EOF is encountered.
     * - TT_WORD are keywords in the normal sense, i.e. constants, events, etc.
     * - TT_LINE are for entire lines (currently only flow control labels use this).
     * - TT_ONE_SIDED_DELIMITER are for open-ended delimiters which are terminated by EOL.
     * - TT_TWO_SIDED_DELIMITER are for delimiters that end with a different delimiter than they open with.
     * - TT_DOUBLE_QUOTATION_MARKS are for delimiting areas using the same delimiter to open and close.
     */
    typedef enum e_token_type
    {
        TT_UNKNOWN,
        TT_WORD,
        TT_LINE,
        TT_TWO_SIDED_DELIMITER,
        TT_ONE_SIDED_DELIMITER,
        TT_DOUBLE_QUOTATION_MARKS,
        // Following constants are more specific versions of the preceding ones
        TT_CONSTANT,                        // WORD
        TT_CONTROL,                         // WORD
        TT_EVENT,                           // WORD
        TT_FUNCTION,                        // WORD
        TT_LABEL,                           // LINE
        TT_SECTION,                         // WORD
        TT_TYPE                             // WORD
    } ETokenType;

    LLKeywordToken( ETokenType type, const LLUIColor& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter  )
        :
        mType( type ),
        mToken( token ),
        mColor( color ),
        mToolTip( tool_tip ),
        mDelimiter( delimiter )     // right delimiter
    {
    }

    S32                 getLengthHead() const   { return static_cast<S32>(mToken.size()); }
    S32                 getLengthTail() const   { return static_cast<S32>(mDelimiter.size()); }
    bool                isHead(const llwchar* s) const;
    bool                isTail(const llwchar* s) const;
    const LLWString&    getToken() const        { return mToken; }
    const LLUIColor&     getColor() const        { return mColor; }
    ETokenType          getType()  const        { return mType; }
    const LLWString&    getToolTip() const      { return mToolTip; }
    const LLWString&    getDelimiter() const    { return mDelimiter; }

#ifdef _DEBUG
    void        dump();
#endif

private:
    ETokenType  mType;
    LLWString   mToken;
    LLUIColor    mColor;
    LLWString   mToolTip;
    LLWString   mDelimiter;
};

class LLKeywords
{
public:
    LLKeywords();
    ~LLKeywords();

    void        clearLoaded() { mLoaded = false; }
    LLUIColor    getColorGroup(std::string_view key_in) const;
    bool        isLoaded() const { return mLoaded; }

    void        findSegments(std::vector<LLTextSegmentPtr> *seg_list,
                             const LLWString& text,
                             class LLTextEditor& editor,
                             LLStyleConstSP style);
    void        initialize(LLSD SyntaxXML);
    void        processTokens();

    // Add the token as described
    void addToken(LLKeywordToken::ETokenType type,
                    const std::string& key,
                    const LLUIColor& color,
                    const std::string& tool_tip = LLStringUtil::null,
                    const std::string& delimiter = LLStringUtil::null);

    // This class is here as a performance optimization.
    // The word token map used to be defined as std::map<LLWString, LLKeywordToken*>.
    // This worked, but caused a performance bottleneck due to memory allocation and string copies
    //  because it's not possible to search such a map without creating an LLWString.
    // Using this class as the map index instead allows us to search using segments of an existing
    //  text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments().
    class WStringMapIndex
    {
    public:
        // copy constructor
        WStringMapIndex(const WStringMapIndex& other);
        // constructor from a string (copies the string's data into the new object)
        WStringMapIndex(const LLWString& str);
        // constructor from pointer and length
        // NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object!
        WStringMapIndex(const llwchar *start, size_t length);
        ~WStringMapIndex();
        bool operator<(const WStringMapIndex &other) const;
    private:
        void copyData(const llwchar *start, size_t length);
        const llwchar *mData;
        size_t mLength;
        bool mOwner;


        LLUIColor            mColor;
    };

    typedef std::map<WStringMapIndex, LLKeywordToken*> word_token_map_t;
    typedef word_token_map_t::const_iterator keyword_iterator_t;
    keyword_iterator_t begin() const { return mWordTokenMap.begin(); }
    keyword_iterator_t end() const { return mWordTokenMap.end(); }

    typedef std::map<WStringMapIndex, LLUIColor> group_color_map_t;
    typedef group_color_map_t::const_iterator color_iterator_t;
    group_color_map_t   mColorGroupMap;

#ifdef _DEBUG
    void        dump();
#endif

protected:
    void        processTokensGroup(const LLSD& Tokens, std::string_view Group);
    void        insertSegment(std::vector<LLTextSegmentPtr>& seg_list,
                              LLTextSegmentPtr new_segment,
                              S32 text_len,
                              const LLUIColor &defaultColor,
                              class LLTextEditor& editor);
    void        insertSegments(const LLWString& wtext,
                               std::vector<LLTextSegmentPtr>& seg_list,
                               LLKeywordToken* token,
                               S32 text_len,
                               S32 seg_start,
                               S32 seg_end,
                               LLStyleConstSP style,
                               LLTextEditor& editor);

    void insertSegment(std::vector<LLTextSegmentPtr>& seg_list, LLTextSegmentPtr new_segment, S32 text_len, LLStyleConstSP style, LLTextEditor& editor );

    bool        mLoaded;
    LLSD        mSyntax;
    word_token_map_t mWordTokenMap;
    typedef std::deque<LLKeywordToken*> token_list_t;
    token_list_t mLineTokenList;
    token_list_t mDelimiterTokenList;

    typedef  std::map<std::string, std::string, std::less<>> element_attributes_t;
    typedef element_attributes_t::const_iterator attribute_iterator_t;
    element_attributes_t mAttributes;
    std::string getAttribute(std::string_view key);

    std::string getArguments(LLSD& arguments);
};

#endif  // LL_LLKEYWORDS_H