1 /*
2  * lineranges.h
3  *
4  *  Created on: Sep 17, 2008
5  *      Author: Lorenzo Bettini <http://www.lorenzobettini.it>, (C) 2008
6  *  Copyright: See COPYING file that comes with this distribution
7  */
8 
9 #ifndef LINERANGES_H_
10 #define LINERANGES_H_
11 
12 #include <set>
13 #include <string>
14 
15 namespace srchilite {
16 
17 /// a possible error in specifying a range
18 enum RangeError {
19     NO_ERROR = 0, INVALID_RANGE_NUMBER
20 };
21 
22 /// result for a check whether a number is in a range (or in a context)
23 enum RangeResult {
24     NOT_IN_RANGE = 0, CONTEXT_RANGE, IN_RANGE
25 };
26 
27 /**
28  * Functionalities for detecting whether a line is in one of the
29  * stored line ranges (or in the context of a range).
30  *
31  * This also performs some optimization: ranges are stored in a set
32  * in ascending order; if we have ranges, e.g., 1-20, 50-70, 100-200, and
33  * we check whether 23 is in range, we first check if it's in 1-20, then,
34  * since it's not there, we check whether it's in 50-70; it is not, and since the
35  * range is 50-70 it makes no sense searching for it in other ranges.  The next search
36  * will start from range 50-70, since we assume that line numbers are always increasing.
37  */
38 class LineRanges {
39 public:
40     LineRanges(unsigned int contextLines = 0);
41     ~LineRanges();
42 
43     typedef int RangeElemType;
44     typedef std::pair<RangeElemType, RangeElemType> RangeType;
45 
46     typedef std::set<RangeType> LineRangeSet;
47 
48     /**
49      * Adds a range to the set.
50      * The argument can be:
51      *
52      * - a single element (means only one line)
53      * - a complete range (e.g., 20-35)
54      * - a partial range (e.g., 10- : from line 10 to the end,
55      *   -20 : from the beginning to line 20)
56      *
57      * @param range the string representing the range.
58      * @return code specifying a possible error
59      */
60     RangeError addRange(const std::string &range);
61 
getLineRangeSet()62     const LineRangeSet &getLineRangeSet() const {
63         return lineRangeSet;
64     }
65 
66     /**
67      * The next isInRange search will start from the first element of
68      * the set.  This should be called before searching for lines of a file,
69      * that we started to process.
70      */
reset()71     void reset() {
72         searchFromTheStart = true;
73     }
74 
75     /**
76      * Checks whether the passed element is in a range of this set.
77      * If it's not in the range it might be in the surrounding context.
78      *
79      * @param e
80      * @return whether the passed element is in a range or in the surrounding context.
81      */
82     RangeResult isInRange(const RangeElemType e);
83 
setContextLines(unsigned int context)84     void setContextLines(unsigned int context) {
85         contextLines = context;
86     }
87 
88 private:
89     LineRangeSet lineRangeSet;
90 
91     /**
92      * whether to perform the search from the first element of the set
93      */
94     bool searchFromTheStart;
95 
96     /**
97      * The current range for performing the search of isInRange.
98      */
99     LineRangeSet::const_iterator currentRange;
100 
101     /**
102      * The number of lines making the context (i.e., the number of lines
103      * that are not part of a range but are in the specified line number context)
104      */
105     int contextLines;
106 };
107 
108 }
109 
110 #endif /* LINERANGES_H_ */
111