summaryrefslogtreecommitdiffstats
path: root/src/lib/log/message_reader.h
blob: a468d43213b0e80e6a39dc1c6be0c0293c4e203e (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
// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#ifndef __MESSAGE_READER_H
#define __MESSAGE_READER_H

#include <map>
#include <string>
#include <vector>

#include <log/message_dictionary.h>
#include <log/message_types.h>

namespace isc {
namespace log {

/// \brief Read Message File
///
/// Reads a message file and creates a map of identifier against the text of the
/// message.  This map can be retrieved for subsequent processing.

class MessageReader {
public:

    /// \brief Read Mode
    ///
    /// If ADD, messages are added to the dictionary if the ID does not exist
    /// there.  If it does, the ID is added to the dictionary's overflow
    /// vector.
    ///
    /// If REPLACE, the dictionary is only modified if the message ID already
    /// exists in it.  New message IDs are added to the overflow vector.
    typedef enum {
        ADD,
        REPLACE
    } Mode;

    /// \brief Visible collection types
    typedef std::vector<std::string>   MessageIDCollection;

    /// \brief Constructor
    ///
    /// Default constructor.  All work is done in the main readFile code (so
    /// that a status return can be returned instead of needing to throw an
    /// exception).
    ///
    /// \param dictionary Dictionary to which messages read read from the file
    /// are added.  (This should be a local dictionary when the class is used in
    /// the message compiler, and the global dictionary when used in a server.
    /// The ownership of the dictionary object is not transferred - the caller
    /// is responsible for managing the lifetime of the dictionary.
    MessageReader(MessageDictionary* dictionary = NULL) :
        dictionary_(dictionary), lineno_(0)
    {}

    /// \brief Virtual Destructor
    virtual ~MessageReader()
    {}

    /// \brief Get Dictionary
    ///
    /// Returns the pointer to the dictionary object.  Note that ownership is
    /// not transferred - the caller should not delete it.
    ///
    /// \return Pointer to current dictionary object
    MessageDictionary* getDictionary() const {
        return (dictionary_);
    }


    /// \brief Set Dictionary
    ///
    /// Sets the current dictionary object.
    ///
    /// \param dictionary New dictionary object. The ownership of the dictionary
    /// object is not transferred - the caller is responsible for managing the
    /// lifetime of the dictionary.
    void setDictionary(MessageDictionary* dictionary) {
        dictionary_ = dictionary;
    }


    /// \brief Read File
    ///
    /// This is the main method of the class and reads in the file, parses it,
    /// and stores the result in the message dictionary.
    ///
    /// \param file Name of the message file.
    /// \param mode Addition mode.  See the description of the "Mode" enum.
    virtual void readFile(const std::string& file, Mode mode = ADD);


    /// \brief Process Line
    ///
    /// Parses a text line and adds it to the message map.  Although this is
    /// for use in readFile, it can also be used to add individual messages
    /// to the message map.
    ///
    /// \param line Line of text to process
    /// \param mode If a message line, how to add the message to the dictionary.
    virtual void processLine(const std::string& line, Mode mode = ADD);


    /// \brief Get Namespace
    ///
    /// \return Argument to the $NAMESPACE directive (if present)
    virtual std::string getNamespace() const {
        return (ns_);
    }


    /// \brief Clear Namespace
    ///
    /// Clears the current namespace.
    virtual void clearNamespace() {
        ns_ = "";
    }


    /// \brief Get Prefix
    ///
    /// \return Argument to the $PREFIX directive (if present)
    virtual std::string getPrefix() const {
        return (prefix_);
    }


    /// \brief Clear Prefix
    ///
    /// Clears the current prefix.
    virtual void clearPrefix() {
        prefix_ = "";
    }


    /// \brief Get Not-Added List
    ///
    /// Returns the list of IDs that were not added during the last
    /// read of the file.
    ///
    /// \return Collection of messages not added
    MessageIDCollection getNotAdded() const {
        return (not_added_);
    }

private:

    /// \brief Handle a Message Definition
    ///
    /// Passed a line that should contain a message, this processes that line
    /// and adds it to the dictionary according to the mode setting.
    ///
    /// \param line Line of text
    /// \param ADD or REPLACE depending on how the reader is operating.  (See
    /// the description of the Mode typedef for details.)
    void parseMessage(const std::string& line, Mode mode);


    /// \brief Handle Directive
    ///
    /// Passed a line starting with a "$", this handles the processing of
    /// directives.
    ///
    /// \param line Line of text that starts with "$",
    void parseDirective(const std::string& line);


    /// \brief Parse $PREFIX line
    ///
    /// \param tokens $PREFIX line split into tokens
    void parsePrefix(const std::vector<std::string>& tokens);


    /// \brief Parse $NAMESPACE line
    ///
    /// \param tokens $NAMESPACE line split into tokens
    void parseNamespace(const std::vector<std::string>& tokens);

    /// \brief Check for invalid C++ symbol name
    ///
    /// The message ID (or concatenation of prefix and message ID) will be used
    /// as the name of a symbol in C++ code.  This function checks if the name
    /// is invalid (contains anything other than alphanumeric characters or
    /// underscores, or starts with a digit).
    ///
    /// \param symbol name to check to see if it is an invalid C++ symbol.
    ///
    /// \return true if the name is invalid, false if it is valid.
    bool invalidSymbol(const std::string& symbol);



    /// Attributes
    MessageDictionary*  dictionary_;    ///< Dictionary to add messages to
    MessageIDCollection not_added_;     ///< List of IDs not added
    int                 lineno_;        ///< Number of last line read
    std::string         prefix_;        ///< Argument of $PREFIX statement
    std::string         ns_;            ///< Argument of $NAMESPACE statement
};

} // namespace log
} // namespace isc

#endif // __MESSAGE_READER_H