Develop and Download Open Source Software

Browse CVS Repository

Contents of /netruby/netruby/string.cs

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1.1.1 - (show annotations) (download) (vendor branch)
Mon Apr 8 13:30:03 2002 UTC (22 years ago) by arton
Branch: MAIN, vendor
CVS Tags: start, HEAD
Changes since 1.1: +0 -0 lines
initial version 0.8

1 /*
2 Copyright(C) 2001-2002 arton
3
4 Permission is granted for use, copying, modification, distribution,
5 and distribution of modified versions of this work as long as the
6 above copyright notice is included.
7 */
8
9 using System;
10 using System.Text;
11 using System.Globalization;
12 using System.Collections;
13 using System.Reflection;
14 using System.Security;
15 using System.Text.RegularExpressions;
16
17 namespace arton.NETRuby
18 {
19 public class RString : RBasic, ICloneable, IComparable
20 {
21 // this class has no org ptr,
22 // because CLR manages all string, so we don't need to care.
23 public RString(NetRuby rb, string s) :
24 base(rb, rb.cString)
25 {
26 ptr = s;
27 }
28 public RString(RString rs) :
29 base(rs)
30 {
31 ptr = rs.ptr;
32 }
33 public RString(NetRuby rb, string s, bool taint) :
34 base(rb, rb.cString)
35 {
36 ptr = s;
37 if (taint)
38 flags |= FL.TAINT;
39 }
40
41 public RString Initialize(object str2)
42 {
43 if (this == str2) return this;
44 if (str2 is string)
45 {
46 ptr = (string)str2;
47 }
48 else if (str2 is RString)
49 {
50 ptr = ((RString)str2).ptr;
51 if (((RString)str2).IsTainted) Set(FL.TAINT);
52 }
53 else
54 {
55 ptr = obj_to_s(str2);
56 if (str2 is RBasic && ((RBasic)str2).IsTainted) Set(FL.TAINT);
57 }
58 return this;
59 }
60 public override bool Equals(object o)
61 {
62 if (this == o) return true;
63 if (o is string)
64 return ptr == (string)o;
65 RString r;
66 if (o is RString)
67 {
68 r = (RString)o;
69 }
70 else
71 {
72 r = (RString)ruby.CheckConvertType(o, typeof(RString), "String", "to_str");
73 if (r == null) return false;
74 }
75 return ptr == r.ptr;
76 }
77 public override int GetHashCode() // for voiding CS0659 warning.
78 {
79 return base.GetHashCode();
80 }
81 public int CompareTo(object str2)
82 {
83 string s = null;
84 if (str2 is string) s = (string)str2;
85 else if (str2 is RString) s = ((RString)str2).ptr;
86 else throw new ArgumentException("object must be the same type");
87 return ptr.CompareTo(s);
88 }
89 public int CompareMethod(object str2)
90 {
91 string s = null;
92 if (str2 is string) s = (string)str2;
93 else if (str2 is RString) s = ((RString)str2).ptr;
94 else s = StringToRString(ruby, str2).ptr;
95 return CompareTo(s);
96 }
97 public static string AsString(NetRuby ruby, object x)
98 {
99 if (x == null)
100 return String.Empty;
101 if (x is string)
102 return (string)x;
103 if (x is RString)
104 return x.ToString();
105 object o = ruby.Funcall(x, "to_s", null);
106 return o.ToString();
107 }
108 public override RInteger ToInteger()
109 {
110 object o = RInteger.StringToInteger(ruby, ptr, 0);
111 if (o is int)
112 return new RFixnum(ruby, (int)o);
113 else if (o is long)
114 return new RBignum(ruby, (long)o);
115 return (RInteger)o;
116 }
117 public override RFloat ToFloat()
118 {
119 string s = ptr.Trim().Replace("_", "");
120 return new RFloat(ruby, Convert.ToDouble(s.Trim()));
121 }
122 // create new instance(INFECTED) RString
123 public static RString AsRString(NetRuby ruby, object x)
124 {
125 if (x == null)
126 return new RString(ruby, String.Empty);
127 if (x is string)
128 return new RString(ruby, (string)x, false);
129 if (x is RString)
130 return (RString)x;
131 object o = ruby.Funcall(x, "to_s", null);
132 if (o is string)
133 return new RString(ruby, (string)o);
134 if (o is RString)
135 {
136 RString r = (RString)o;
137 if (x is RBasic && ((RBasic)x).IsTainted)
138 r.Set(FL.TAINT);
139 return r;
140 }
141 else if (o is RBasic)
142 return ((RBasic)o).ToRString();
143 else
144 return new RString(ruby, o.ToString());
145 }
146 public static string ToString(NetRuby ruby, object s)
147 {
148 if (s is string) return (string)s;
149 if (s is RString) return s.ToString();
150 return StringToRString(ruby, s).ToString();
151 }
152 public static RString StringToRString(NetRuby ruby, object s)
153 {
154 return (RString)ruby.ConvertType(s, typeof(RString), "String", "to_str");
155 }
156 public override string ToString()
157 {
158 return ptr;
159 }
160 public override RString ToRString()
161 {
162 return this;
163 }
164 internal static RString New(NetRuby rb, object[] args)
165 {
166 RString rs = new RString(rb, String.Empty);
167 rb.CallInit(rs, args);
168 return rs;
169 }
170 internal RString SetData(string s)
171 {
172 ptr = s;
173 return this;
174 }
175 public object Clone()
176 {
177 RString rs = Dup();
178 // CLONESETUP
179 return rs;
180 }
181
182 internal RString Dup(object o)
183 {
184 // any object to string
185 return null;
186 }
187 public RString Dup()
188 {
189 RString rs = new RString(this);
190 return rs;
191 }
192
193 internal object Plus(object o)
194 {
195 string s = ToString(ruby, o);
196 string result = ptr + s;
197 if (IsTainted)
198 {
199 RString n = new RString(ruby, result, true);
200 return n;
201 }
202 return result;
203 }
204
205 public object ToInteger(int radix)
206 {
207 bool sign = true;
208 bool badcheck = (radix == 0) ? true : false;
209 string s = ptr.Trim();
210 if (s[0] == '+')
211 {
212 s = s.Substring(1);
213 }
214 else if (s[0] == '-')
215 {
216 s = s.Substring(1);
217 sign = false;
218 }
219 if (s[0] == '+' || s[0] == '-')
220 {
221 if (badcheck)
222 throw new eArgError("invalid value for Integer: \"" + ptr + "\"");
223 return 0;
224 }
225 if (radix == 0)
226 {
227 if (s[0] == '0')
228 {
229 if (s[1] == 'x' || s[1] == 'X')
230 {
231 radix = 16;
232 }
233 else if (s[1] == 'b' || s[1] == 'B')
234 {
235 radix = 2;
236 }
237 else
238 {
239 radix = 8;
240 }
241 }
242 else
243 {
244 radix = 10;
245 }
246 }
247 int pos = 0;
248 if (radix == 8)
249 {
250 while (s[pos] == '0') pos++;
251 if (pos == s.Length) return 0;
252 while (s[pos] == '_') pos++;
253 s = s.Substring(pos);
254 }
255 else
256 {
257 if (radix == 16 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
258 {
259 s = s.Substring(2);
260 }
261 if (radix == 2 && s[0] == '0' && (s[1] == 'b' || s[1] == 'B'))
262 {
263 s = s.Substring(2);
264 }
265 while (s[pos] == '0') pos++;
266 if (Char.IsWhiteSpace(s[pos]))
267 {
268 if (badcheck)
269 throw new eArgError("invalid value for Integer: \"" + ptr + "\"");
270 return 0;
271 }
272 if (pos == s.Length) pos--;
273 s = s.Substring(pos);
274 }
275 s.Replace("_", "");
276 try
277 {
278 int result = Convert.ToInt32(ptr, radix);
279 return (sign) ? result : -result;
280 }
281 catch (ArgumentException)
282 {
283 if (badcheck)
284 throw new eArgError("invalid value for Integer: \"" + ptr + "\"");
285 return 0;
286 }
287 catch (OverflowException)
288 {
289 ;
290 }
291 return "bignum";
292 }
293
294 private struct EscTbl
295 {
296 internal EscTbl(char c, string s)
297 {
298 code = c;
299 result = s;
300 }
301 internal char code;
302 internal string result;
303 }
304 static EscTbl[] esctbl = new EscTbl[] {
305 new EscTbl('\n', "\\n"),
306 new EscTbl('\r', "\\r"),
307 new EscTbl('\t', "\\t"),
308 new EscTbl('\f', "\\f"),
309 new EscTbl('\v', "\\v"),
310 new EscTbl('\a', "\\a"),
311 new EscTbl('\b', "\\b"), // .NET (not ruby)
312 new EscTbl('\u001b', "\\e"),
313 };
314
315 public override object Inspect()
316 {
317 string result = "\"";
318 foreach (char c in ptr)
319 {
320 bool esc;
321 if (c == '"' || c == '\\')
322 {
323 result += "\\" + c;
324 }
325 else
326 {
327 UnicodeCategory uc = Char.GetUnicodeCategory(c);
328 if (uc == UnicodeCategory.Control ||
329 uc == UnicodeCategory.NonSpacingMark ||
330 uc == UnicodeCategory.OtherNotAssigned ||
331 uc == UnicodeCategory.Surrogate)
332 {
333 esc = false;
334 for (int i = 0; i < esctbl.Length; i++)
335 {
336 if (esctbl[i].code == c)
337 {
338 esc = true;
339 result += esctbl[i].result;
340 break;
341 }
342 }
343 if (esc == false)
344 {
345 result += String.Format("\\u{0:x4}", c);
346 }
347 }
348 else
349 {
350 result += c;
351 }
352 }
353 }
354 result += "\"";
355 if (IsTainted)
356 {
357 RString rs = new RString(ruby, result, true);
358 return rs;
359 }
360 return result;
361 }
362
363 public int Length
364 {
365 get { return ptr.Length; }
366 }
367 public bool IsEmpty
368 {
369 get { return (ptr == null || ptr.Length == 0); }
370 }
371
372 public RString UpCase()
373 {
374 RString rs = Dup();
375 return rs.UpCaseBang();
376 }
377
378 public RString DownCase()
379 {
380 RString rs = Dup();
381 return rs.DownCaseBang();
382 }
383
384 public RString Capitalize()
385 {
386 RString rs = Dup();
387 return rs.CapitalizeBang();
388 }
389
390 public RString SwapCase()
391 {
392 RString rs = Dup();
393 return rs.SwapCaseBang();
394 }
395
396 public RString UpCaseBang()
397 {
398 ptr = ptr.ToUpper();
399 return this;
400 }
401
402 public RString DownCaseBang()
403 {
404 ptr = ptr.ToLower();
405 return this;
406 }
407
408 public RString CapitalizeBang()
409 {
410 StringBuilder sb = new StringBuilder(ptr.ToLower());
411 if (sb.Length > 0)
412 sb[0] = Char.ToUpper(sb[0]);
413 ptr = sb.ToString();
414 return this;
415 }
416
417 public RString SwapCaseBang()
418 {
419 StringBuilder sb = new StringBuilder(ptr);
420 for (int i = 0; i < sb.Length; i++)
421 {
422 if (Char.IsUpper(sb[i]))
423 sb[i] = Char.ToLower(sb[i]);
424 else if (Char.IsLower(sb[i]))
425 sb[i] = Char.ToUpper(sb[i]);
426 }
427 ptr = sb.ToString();
428 return this;
429 }
430
431 public RString Sub(params object[] args)
432 {
433 RString s = Dup();
434 s.SubAt(args);
435 return s;
436 }
437 private RRegexp GetPat(object pat)
438 {
439 if (pat is RRegexp)
440 {
441 return (RRegexp)pat;
442 }
443 if (pat is string || pat is RString)
444 {
445 return (RRegexp)RRegexpClass.s_new(ruby.cRegexp, pat);
446 }
447 ruby.CheckType(pat, typeof(RRegexp));
448 return null;
449 }
450 public RString SubAt(params object[] args)
451 {
452 bool iter = false;
453 RString repl = null;
454 bool tainted = false;
455 if (args != null && args.Length == 1 && ruby.IsBlockGiven)
456 {
457 iter = true;
458 }
459 else if (args != null && args.Length == 2)
460 {
461 repl = StringToRString(ruby, args[1]);
462 tainted = repl.IsTainted;
463 }
464 else
465 {
466 throw new eArgError(String.Format("wrong # of arguments({0} for 2)",
467 (args == null) ? 0 : args.Length));
468 }
469 RRegexp pat = GetPat(args[0]);
470 if (pat.Search(ptr, 0, false, IsTainted) >= 0)
471 {
472 RThread th = ruby.GetCurrentContext();
473 RMatchData match = (RMatchData)th.BackRef;
474 int beg = match.Begin(0);
475 int len = match.End(0) - beg;
476 if (iter)
477 {
478 RRegexpClass.matchBusy(match);
479 repl = RString.AsRString(ruby, ruby.Yield(match[0]));
480 th.BackRef = match; // rescue from yield.
481 }
482 else
483 {
484 repl = new RString(ruby, match.Sub(repl.ToString(), ptr));
485 }
486 if (repl.IsTainted) tainted = true;
487 StringBuilder sb = new StringBuilder(ptr);
488 sb.Remove(beg, len);
489 sb.Insert(beg, repl.ptr, 1);
490 ptr = sb.ToString();
491 if (tainted) Taint();
492 return this;
493 }
494 return null;
495 }
496 public RString Gsub(params object[] args)
497 {
498 RString s = Dup();
499 RString x = s.GsubAt(args);
500 return (x == null) ? s : x;
501 }
502 public RString GsubAt(params object[] args)
503 {
504 bool iter = false;
505 RString repl = null;
506 bool tainted = false;
507 if (args != null && args.Length == 1 && ruby.IsBlockGiven)
508 {
509 iter = true;
510 }
511 else if (args != null && args.Length == 2)
512 {
513 repl = StringToRString(ruby, args[1]);
514 tainted = repl.IsTainted;
515 }
516 else
517 {
518 throw new eArgError(String.Format("wrong # of arguments({0} for 2)",
519 (args == null) ? 0 : args.Length));
520 }
521 RRegexp pat = GetPat(args[0]);
522 int beg = pat.Search(ptr, 0, false, IsTainted);
523 if (beg < 0) return null;
524
525 StringBuilder sb = new StringBuilder();
526 RThread th = ruby.GetCurrentContext();
527 int offset = 0;
528 RMatchData match = null;
529 while (beg >= 0)
530 {
531 string val;
532 match = (RMatchData)th.BackRef;
533 beg = match.Begin(0);
534 int len = match.End(0) - beg;
535 if (iter)
536 {
537 RRegexpClass.matchBusy(match);
538 repl = RString.AsRString(ruby, ruby.Yield(match[0]));
539 th.BackRef = match; // rescue from yield.
540 if (repl.IsTainted) tainted = true;
541 val = repl.ToString();
542 }
543 else
544 {
545 val = match.Sub(repl.ToString(), ptr);
546 }
547 if (beg > offset)
548 {
549 sb.Append(ptr, offset, beg - offset);
550 }
551 sb.Append(val);
552 if (len == 0)
553 {
554 if (ptr.Length > match.End(0))
555 {
556 sb.Append(ptr, match.End(0), 1);
557 }
558 offset = beg + 1;
559 }
560 else
561 {
562 offset = beg + len;
563 }
564 if (offset > ptr.Length) break;
565 beg = pat.Search(ptr, offset, false, IsTainted);
566 }
567 if (ptr.Length > offset)
568 {
569 sb.Append(ptr, offset, ptr.Length - offset);
570 }
571 th.BackRef = match; // rescue from yield.
572 ptr = sb.ToString();
573 if (tainted) Taint();
574 return this;
575 }
576
577 public object Dump()
578 {
579 return Inspect();
580 }
581
582 internal object str_equal(RBasic obj, params object[] o)
583 {
584 return (o[0] == obj) ? true : false;
585 }
586
587 private string ptr;
588
589 static internal void Init(NetRuby rb)
590 {
591 BindingFlags bf = BindingFlags.InvokeMethod
592 | BindingFlags.Static | BindingFlags.Public
593 | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy
594 | BindingFlags.Instance;
595 RClass str = rb.DefineClass("String", rb.cObject);
596 rb.cString = str;
597 rb.oString = new RString(rb, String.Empty);
598 #if MIXIN
599 RClass.IncludeModule(str, rb.mComparable);
600 RClass.IncludeModule(str, rb.mEnumerable);
601 #endif
602 Type obj = typeof(RString);
603 str.DefineSingletonMethod("new", obj.GetMethod("New", bf));
604 str.DefineMethod("initialize", obj.GetMethod("Initialize", bf));
605 str.DefineMethod("clone", obj.GetMethod("Clone", bf));
606 str.DefineMethod("dup", obj.GetMethod("Dup", new Type[0]));
607 str.DefineMethod("<=>", obj.GetMethod("CompareMethod", bf));
608 str.DefineMethod("eql?", obj.GetMethod("Equals", bf & (~BindingFlags.Static)));
609 str.DefineMethod("equal?", new RMethod(rb.oString.str_equal), 1);
610 str.DefineMethod("+", obj.GetMethod("Plus", bf));
611 str.DefineMethod("length", obj.GetMethod("get_Length", bf));
612 str.DefineMethod("size", obj.GetMethod("get_Length", bf));
613 str.DefineMethod("empty?", obj.GetMethod("get_IsEmpty", bf));
614
615 str.DefineMethod("to_i", obj.GetMethod("ToInteger", new Type[0]));
616 str.DefineMethod("to_f", obj.GetMethod("ToFloat", bf));
617 MethodInfo mi = obj.GetMethod("ToRString", bf);
618 str.DefineMethod("to_s", mi);
619 str.DefineMethod("to_str", mi);
620 str.DefineMethod("inspect", obj.GetMethod("Inspect", bf));
621 str.DefineMethod("dump", obj.GetMethod("Dump", bf));
622
623 str.DefineMethod("upcase", obj.GetMethod("UpCase", bf));
624 str.DefineMethod("downcase", obj.GetMethod("DownCase", bf));
625 str.DefineMethod("capitalize", obj.GetMethod("Capitalize", bf));
626 str.DefineMethod("swapcase", obj.GetMethod("SwapCase", bf));
627
628 str.DefineMethod("upcase!", obj.GetMethod("UpCaseBang", bf));
629 str.DefineMethod("downcase!", obj.GetMethod("DownCaseBang", bf));
630 str.DefineMethod("capitalize!", obj.GetMethod("CapitalizeBang", bf));
631 str.DefineMethod("swapcase!", obj.GetMethod("SwapCaseBang", bf));
632
633 str.DefineMethod("sub", obj.GetMethod("Sub", bf));
634 str.DefineMethod("gsub", obj.GetMethod("Gsub", bf));
635
636 str.DefineMethod("sub!", obj.GetMethod("SubAt", bf));
637 str.DefineMethod("gsub!", obj.GetMethod("GsubAt", bf));
638 }
639 }
640
641 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26