Merge branch 'master' of git://github.com/mono/mono
[mono.git] / mcs / class / System.Data / System.Data.ProviderBase.jvm / regex.cs
1 //\r
2 // System.Data.ProviderBase.regex.cs\r
3 //\r
4 // Authors:\r
5 //      Konstantin Triger <kostat@mainsoft.com>\r
6 //      \r
7 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)\r
8 //\r
9 \r
10 //\r
11 // Permission is hereby granted, free of charge, to any person obtaining\r
12 // a copy of this software and associated documentation files (the\r
13 // "Software"), to deal in the Software without restriction, including\r
14 // without limitation the rights to use, copy, modify, merge, publish,\r
15 // distribute, sublicense, and/or sell copies of the Software, and to\r
16 // permit persons to whom the Software is furnished to do so, subject to\r
17 // the following conditions:\r
18 // \r
19 // The above copyright notice and this permission notice shall be\r
20 // included in all copies or substantial portions of the Software.\r
21 // \r
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
29 //\r
30 \r
31 using System.Data;\r
32 using System.Data.Common;\r
33 using System.Data.OleDb;\r
34 \r
35 namespace System.Data.ProviderBase {\r
36         public abstract class SimpleRegex {\r
37                 abstract protected internal SimpleMatch Match(string input, int beginning, int length);\r
38                 protected internal SimpleMatch Match(string input) {\r
39                         return Match(input, 0, input.Length);\r
40                 }\r
41 \r
42                 protected bool IsWordChar(char c) { //regexp w ([a-zA-Z_0-9]) + #@$\r
43                         if (c < '@') {\r
44                                 return (c >= '0' && c <= '9') ||\r
45                                                 (c == '#' || c == '$');\r
46                         }\r
47                         else {\r
48                                 return (c <= 'Z') ||\r
49                                         (c <= 'z' && c >= '_' && c != '`');\r
50                         }\r
51                 }\r
52         }\r
53         public class SimpleCapture {\r
54                 readonly int _index;\r
55                 readonly int _length;\r
56                 readonly string _input;\r
57 \r
58                 protected SimpleCapture(int index, int length, string input) {\r
59                         _index = index;\r
60                         _length = length;\r
61                         _input = input;\r
62                 }\r
63 \r
64                 protected internal int Index {\r
65                         get {\r
66                                 return _index;\r
67                         }\r
68                 }\r
69 \r
70                 protected internal int Length {\r
71                         get {\r
72                                 return _length;\r
73                         }\r
74                 }\r
75 \r
76                 protected internal string Value {\r
77                         get {\r
78                                 return Input.Substring(Index, Length);\r
79                         }\r
80                 }\r
81 \r
82                 protected string Input {\r
83                         get {\r
84                                 return _input;\r
85                         }\r
86                 }\r
87         }\r
88 \r
89         public class SimpleMatch : SimpleCapture {\r
90                 readonly bool _success;\r
91                 readonly SimpleRegex _regex;\r
92                 readonly int _total;\r
93                 readonly int _skip;\r
94 \r
95                 public SimpleMatch(SimpleRegex regex, int total, bool success, int index, int length, string input)\r
96                         : this(regex, total, success, index, length, 0, input) {}\r
97 \r
98                 public SimpleMatch(SimpleRegex regex, int total, bool success, int index, int length, int skip, string input)\r
99                         : base(index, length, input) {\r
100                         _success = success;\r
101                         _regex = regex;\r
102                         _total = total;\r
103                         _skip = skip;\r
104                 }\r
105 \r
106                 protected internal SimpleMatch NextMatch() {\r
107                         return _regex.Match(Input, Index+Length+_skip, _total);\r
108                 }\r
109 \r
110                 protected internal bool Success {\r
111                         get {\r
112                                 return _success;\r
113                         }\r
114                 }\r
115         }\r
116 \r
117         internal class OleDbParamsRegex : SimpleRegex {\r
118                 protected internal override SimpleMatch Match(string input, int beginning, int length) {\r
119 \r
120                         for (int i = beginning; i < length; i++) {\r
121                                 char ch = input[i];\r
122                                 switch(ch) {\r
123                                         case '\'': {\r
124                                                 int end = input.IndexOf('\'', i+1);\r
125                                                 if (end < 0)\r
126                                                         break;\r
127 \r
128                                                 i = end;\r
129                                                 break;\r
130                                         }\r
131                                         case '"': {\r
132                                                 int end = input.IndexOf('"', i+1);\r
133                                                 if (end < 0)\r
134                                                         break;\r
135 \r
136                                                 i = end;\r
137                                                 break;\r
138                                         }\r
139                                         case '[': {\r
140                                                 int end = input.IndexOf(']', i+1);\r
141                                                 if (end < 0)\r
142                                                         break;\r
143 \r
144                                                 i = end;\r
145                                                 break;\r
146                                         }\r
147                                         case '?': {\r
148                                                 return new SimpleMatch(this, length, true, i, 1, input);\r
149                                         }\r
150                                 }\r
151                         }\r
152 \r
153                         return new SimpleMatch(this, length, false, length, 0, input);\r
154                 }\r
155         }\r
156 \r
157         internal class SqlParamsRegex : SimpleRegex {\r
158                 //static readonly char[] charsEnd = new char[] {' ', '\f', '\t', '\v', '\r', '\n',  ',', ';', '(', ')', '[', ']','='};\r
159                 protected internal override SimpleMatch Match(string input, int beginning, int length) {\r
160 \r
161                         int actualLen = length-1; //there must be something after @\r
162                         for (int i = beginning; i < actualLen; i++) {\r
163                                 char ch = input[i];\r
164                                 switch(ch) {\r
165                                         case '\'': {\r
166                                                 int end = input.IndexOf('\'', i+1);\r
167                                                 if (end < 0)\r
168                                                         break;\r
169 \r
170                                                 i = end;\r
171                                                 break;\r
172                                         }\r
173                                         case '"': {\r
174                                                 int end = input.IndexOf('"', i+1);\r
175                                                 if (end < 0)\r
176                                                         break;\r
177 \r
178                                                 i = end;\r
179                                                 break;\r
180                                         }\r
181                                         case '[': {\r
182                                                 int end = input.IndexOf(']', i+1);\r
183                                                 if (end < 0)\r
184                                                         break;\r
185 \r
186                                                 i = end;\r
187                                                 break;\r
188                                         }\r
189                                         case '@': {\r
190                                                 int start = i;\r
191 \r
192                                                 do {\r
193                                                         i++;\r
194                                                 }while (i < length && input[i] == '@');\r
195 \r
196                                                 if (i - start > 1)\r
197                                                         break;\r
198 \r
199                                                 while (i < length && IsWordChar(input[i]))\r
200                                                         i++;\r
201         \r
202                                                 return new SimpleMatch(this, length, true, start, i-start, input);\r
203                                         }\r
204                                 }\r
205                         }\r
206 \r
207                         return new SimpleMatch(this, length, false, length, 0, input);\r
208                 }\r
209         }\r
210 \r
211         internal class CharacterSplitterRegex : SimpleRegex {\r
212                 char _delimiter;\r
213                 internal CharacterSplitterRegex(char delimiter) {\r
214                         _delimiter = delimiter;\r
215                 }\r
216                 protected internal override SimpleMatch Match(string input, int beginning, int length) {\r
217 \r
218                         for (int i = beginning; i < length; i++) {\r
219                                 char ch = input[i];\r
220                                 switch(ch) {\r
221                                         case '\'': {\r
222                                                 int end = input.IndexOf('\'', i+1);\r
223                                                 if (end < 0)\r
224                                                         break;\r
225 \r
226                                                 i = end;\r
227                                                 break;\r
228                                         }\r
229                                         case '"': {\r
230                                                 int end = input.IndexOf('"', i+1);\r
231                                                 if (end < 0)\r
232                                                         break;\r
233 \r
234                                                 i = end;\r
235                                                 break;\r
236                                         }\r
237                                         case '[': {\r
238                                                 int end = input.IndexOf(']', i+1);\r
239                                                 if (end < 0)\r
240                                                         break;\r
241 \r
242                                                 i = end;\r
243                                                 break;\r
244                                         }\r
245                                         default: {\r
246                                                 if (ch != _delimiter)\r
247                                                         break;\r
248 \r
249                                                 return new SimpleMatch(this, length, true, beginning, i-beginning, 1, input);\r
250                                         }\r
251                                 }\r
252                         }\r
253 \r
254                         int matchLength = length-beginning;\r
255                         return new SimpleMatch(this, length, matchLength > 0, beginning, matchLength, input);\r
256                 }\r
257         }\r
258 }