tizen beta release
[framework/web/webkit-efl.git] / Source / WebCore / inspector / ContentSearchUtils.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
20  * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "ContentSearchUtils.h"
31
32 #if ENABLE(INSPECTOR)
33
34 #include "InspectorValues.h"
35 #include "RegularExpression.h"
36
37 using namespace std;
38
39 namespace WebCore {
40 namespace ContentSearchUtils {
41
42 namespace {
43 // This should be kept the same as the one in front-end/utilities.js
44 static const char regexSpecialCharacters[] = "[](){}+-*.,?\\^$|";
45 }
46
47 static String createSearchRegexSource(const String& text)
48 {
49     String result;
50     const UChar* characters = text.characters();
51     String specials(regexSpecialCharacters);
52
53     for (unsigned i = 0; i < text.length(); i++) {
54         if (specials.find(characters[i]) != notFound)
55             result.append("\\");
56         result.append(characters[i]);
57     }
58
59     return result;
60 }
61
62 static Vector<pair<int, String> > getRegularExpressionMatchesByLines(const RegularExpression& regex, const String& text)
63 {
64     Vector<pair<int, String> > result;
65     if (text.isEmpty())
66         return result;
67
68     int lineNumber = 0;
69     unsigned start = 0;
70     while (start < text.length()) {
71         size_t lineEnd = text.find('\n', start);
72         if (lineEnd == notFound)
73             lineEnd = text.length();
74         else
75             lineEnd++;
76
77         String line = text.substring(start, lineEnd - start);
78         if (line.endsWith("\r\n"))
79             line = line.left(line.length() - 2);
80         if (line.endsWith("\n"))
81             line = line.left(line.length() - 1);
82
83         int matchLength;
84         if (regex.match(line, 0, &matchLength) != -1)
85             result.append(pair<int, String>(lineNumber, line));
86
87         start = lineEnd;
88         lineNumber++;
89     }
90     return result;
91 }
92
93 static PassRefPtr<InspectorObject> buildObjectForSearchMatch(int lineNumber, String lineContent)
94 {
95     RefPtr<InspectorObject> result = InspectorObject::create();
96     result->setNumber("lineNumber", lineNumber);
97     result->setString("lineContent", lineContent);
98
99     return result;
100 }
101
102 RegularExpression createSearchRegex(const String& query, bool caseSensitive, bool isRegex)
103 {
104     String regexSource = isRegex ? query : createSearchRegexSource(query);
105     return RegularExpression(regexSource, caseSensitive ? TextCaseSensitive : TextCaseInsensitive);
106 }
107
108 int countRegularExpressionMatches(const RegularExpression& regex, const String& content)
109 {
110     if (content.isEmpty())
111         return 0;
112
113     int result = 0;
114     int position;
115     unsigned start = 0;
116     int matchLength;
117     while ((position = regex.match(content, start, &matchLength)) != -1) {
118         if (start >= content.length())
119             break;
120         if (matchLength > 0)
121             ++result;
122         start = position + 1;
123     }
124     return result;
125 }
126
127 PassRefPtr<InspectorArray> searchInTextByLines(const String& text, const String& query, const bool caseSensitive, const bool isRegex)
128 {
129     RefPtr<InspectorArray> result = InspectorArray::create();
130
131     RegularExpression regex = ContentSearchUtils::createSearchRegex(query, caseSensitive, isRegex);
132     Vector<pair<int, String> > matches = getRegularExpressionMatchesByLines(regex, text);
133
134     for (Vector<pair<int, String> >::const_iterator it = matches.begin(); it != matches.end(); ++it)
135         result->pushValue(buildObjectForSearchMatch(it->first, it->second));
136
137     return result;
138 }
139
140 } // namespace ContentSearchUtils
141 } // namespace WebCore
142
143 #endif // ENABLE(INSPECTOR)