source: trunk/ETSI-Testsuites/ETSI_auto_IOT/codec/c++/Regex.h

Last change on this file was 22, checked in by rings, 14 years ago
  • Property svn:executable set to *
File size: 5.2 KB
Line 
1#include <boost/regex.hpp>
2#include <t3devlib/t3devlib.h>
3
4namespace t3devlib { namespace gen {
5
6/** Implementation of perl-like regular expressions to be used in a decoder
7 * generated by T3DevKit.
8 *
9 * This class handles the regex compilation and execution. The result of
10 * group matching is stored internally.
11 *
12 * It is designed to be used seamlessly in codets for T3DevKit, thus:
13 *  - it can interact with t3devlib data (Buffer, Variable, DecodeError)
14 *  - it reports errors using T3DevKit's exceptions
15 *  - it returns the length of the matches in bits
16 *
17 *
18 * The regular expression is compiled at the construction of the object. Then
19 * it can be used multiple times to search the regex in the buffer (with
20 * Match() or AssertMatch()).
21 *
22 * After a regex search, it is possible to inspect the result at to take
23 * actions with other member functions (GetMatchedLength(), MoveAt(), ...)
24 *
25 * \warning     Apart from moving the cursor, the buffer MUST NOT be modified
26 *              between the call of Match() or AssertMatch() and the use of
27 *              inspection/action member functions (GetMatchedLength(),
28 *              MoveAt() ...)
29 */
30class Regex {
31public:
32        typedef std::string::const_iterator     iterator;
33
34        /** Constructor
35         *
36         * This constructor compiles the regular expression given as a
37         * parameter. It is based on the format of perl regular expressions.
38         *
39         * \warning     it is assumed that regex is a static const string
40         */
41        Regex(const char* regex)
42         : mSource (regex), mRegex (regex, boost::regex_constants::perl | boost::regex_constants::no_mod_m)
43        {}
44
45        /** Try to match the regular expression in the buffer.
46         *
47         * The regular expression is searched in the buffer between the
48         * position of its cursor and the first end marker set (thus between
49         * the positions given by Buffer::GetPosition() and
50         * Buffer::GetEndMarker())
51         *
52         * \param buffer        buffer on which the regex shall be searched
53         *
54         * \return      true in case of success
55         */
56        bool Match (Buffer& buffer) {
57                mStart = iterator (reinterpret_cast<const char*> (buffer.GetValueBin()) + (buffer.GetPosition() / 8));
58                mStop = iterator (reinterpret_cast<const char*> (buffer.GetValueBin()) + (buffer.GetEndMarker() / 8));
59
60                int result = boost::regex_search (mStart, mStop, mResults, mRegex);
61
62                return result;
63        }
64
65        /** Match the regular expression in the buffer or throw an exeption
66         * if not successful.
67         *
68         * \param buffer        buffer on which the regex shall be searched
69         * \param v             reference of the value being decoded; it is
70         *                      used to allow locating the error in case an
71         *                      exception is thrown
72         */
73        void AssertMatch (Buffer& buffer, Variable* v) throw (DecodeError) {
74                if (!Match (buffer)) {
75                        Error (v, buffer);
76                }
77        }
78
79        /** Get the length of a group match
80         *
81         * \param       id      index of the '(...)' group to analyse (or 0
82         *                      to refer to the whole regular expression)
83         *
84         * \return              the length of the group in bits
85         */
86        int GetMatchedLength(int id = 0) {
87                return mResults[id].length()*8;
88        }
89
90        /** Get the content of a group match
91         *
92         * \param       id      index of the '(...)' group to analyse (or 0
93         *                      to refer to the whole regular expression)
94         *
95         * \return              the string matched by the group
96         */
97        std::string GetMatchedString(int id = 0) {
98                return std::string (mResults[id].first, mResults[id].second);
99        }
100
101        /** Move the cursor of the buffer past a group match
102         *
103         * \param       id      index of the '(...)' group to analyse (or 0
104         *                      to refer to the whole regular expression)
105         */
106        void MovePast (Buffer& buffer, int id = 0)
107        {
108                buffer.SetPosition ((&*mResults[id].second - reinterpret_cast<const char*> (buffer.GetValueBin())) * 8);
109        }
110       
111        /** Move the cursor of the buffer at the beginning of group match
112         *
113         * \param       id      index of the '(...)' group to analyse (or 0
114         *                      to refer to the whole regular expression)
115         */
116        void MoveAt (Buffer& buffer, int id = 0)
117        {
118                buffer.SetPosition ((&*mResults[id].first - reinterpret_cast<const char*> (buffer.GetValueBin())) * 8);
119        }
120
121        /** Throw a decoding error
122         *
123         * This function will throw an exception telling that the codec
124         * could not match the regular expression. The error message will
125         * also contains details about the regular expression and the
126         * content of the buffer at the position where the exception could
127         * not be matched.
128         *
129         * \param       v       reference to the value being decoded
130         *                      (used to locate the position of the error)
131         * \param       buffer  buffer on which the regex could no be matched
132         */
133        void Error (Variable* v, Buffer& buffer) throw (DecodeError) {
134
135                std::string message ("cannot match regex /");
136                message += mSource;
137                message += "/ in '";
138                if ((mStop - mStart) > 40) {
139                        message.append (&*mStart, 40);
140                        message += "...";
141                } else {
142                        message.append (mStart, mStop);
143                }
144                message += "'\n";
145                throw DecodeError (v, message);
146        }
147
148private:
149        /** source of the regular expression (should be a static string) */
150        const char*     mSource;
151
152        /** boost regex object used to implement the regular expression */
153        boost::regex    mRegex;
154
155        /** iterators delimiting the positions in the buffer where the regex
156         * is applied (between GetPosition() and GetEndMarker)
157         */
158        iterator        mStart, mStop;
159
160        /** boost match result used to store the results of the regex search */
161        boost::match_results<iterator>  mResults;
162};
163
164
165}} //namespaces
Note: See TracBrowser for help on using the repository browser.