3 * Copyright (C)2007-2008 Versabanq Innovations Inc. and contributors.
4 * See the included file named LICENSE for license information.
10 using System
.Collections
;
11 using System
.Collections
.Generic
;
12 using System
.Diagnostics
;
14 using System
.Security
.Cryptography
;
16 using System
.Threading
;
22 public partial class wv
24 public static void sleep(int msec_delay
)
27 Thread
.Sleep(Int32
.MaxValue
);
29 Thread
.Sleep(msec_delay
);
32 public static string shift(ref string[] array
, int index
)
34 string s
= array
[index
];
35 string[] outa
= new string[array
.Length
-1];
36 Array
.Copy(array
, 0, outa
, 0, index
);
37 Array
.Copy(array
, index
+1, outa
, index
, array
.Length
-index
-1);
42 public static string shift(ref string[] array
)
44 return shift(ref array
, 0);
47 public static void assert(bool b
, object msg
)
50 throw new System
.ArgumentException(msg
.ToString());
53 public static void assert(bool b
, string fmt
, params object[] args
)
56 assert(b
, (object)wv
.fmt(fmt
, args
));
59 public static void assert(bool b
)
61 assert(b
, "Assertion Failure");
64 public static void assert()
69 public static DateTime
date(object s
)
73 return DateTime
.Parse(s
.ToString());
75 catch (FormatException
)
77 return DateTime
.MinValue
;
81 public static string httpdate(DateTime d
)
83 return d
.ToUniversalTime()
84 .ToString("ddd, dd MMM yyyy HH:mm:ss") + " GMT";
87 static string intclean(object o
, bool allow_dot
)
89 if (o
== null) return "0";
91 // All this nonsense is to make it so that we can parse
92 // strings a little more liberally. Double.Parse() would
93 // give up in case of invalid characters; we just ignore
94 // anything after that point instead, like C would do.
95 string s
= o
.ToString();
97 char[] ca
= s
.ToCharArray();
99 if (ca
.Length
> 0 && ca
[0] == '-')
101 bool saw_dot
= false;
102 for (; i
< ca
.Length
; i
++)
106 if (saw_dot
|| !allow_dot
)
110 if ("0123456789.".IndexOf(ca
[i
]) < 0)
114 return s
.Substring(0, i
);
117 public static double atod(object o
)
120 return Double
.Parse(intclean(o
, true));
121 } catch (FormatException
) {
126 public static int atoi(object o
)
129 return Int32
.Parse(intclean(o
, false));
130 } catch (FormatException
) {
135 public static long atol(object o
)
138 return Int64
.Parse(intclean(o
, false));
139 } catch (FormatException
) {
144 public static bool isempty(string s
)
146 return s
== null || s
== "";
149 public static bool isempty(DateTime d
)
151 return d
== DateTime
.MinValue
;
154 public static bool isempty(TimeSpan t
)
156 return t
== TimeSpan
.Zero
;
159 public static string fmt(string format
, params object[] args
)
161 return String
.Format(format
, args
);
164 public static void print(string format
, params object[] args
)
166 Console
.Write(format
, args
);
169 public static void printerr(string format
, params object[] args
)
171 Console
.Error
.Write(format
, args
);
174 public static Array
sort(ICollection keys
, IComparer comparer
)
176 object[] sorted
= new object[keys
.Count
];
177 keys
.CopyTo(sorted
, 0);
178 Array
.Sort(sorted
, comparer
);
182 public static Array
sort(ICollection keys
)
184 return sort(keys
, Comparer
.Default
);
187 public static string[] stringify(ICollection keys
)
189 string[] a
= new string[keys
.Count
];
191 foreach (object o
in keys
)
192 a
[i
++] = o
.ToString();
196 public static string getenv(string key
)
198 string o
= Environment
.GetEnvironmentVariable(key
);
205 public static string urldecode(string s
)
207 return HttpUtility
.UrlDecode(s
);
210 public static string urlencode(string s
)
212 return HttpUtility
.UrlEncode(s
);
215 public static void urlsplit(Dictionary
<string,string> d
, string query
)
217 // Multiple values separated by & signs, as in URLs
218 foreach (string ent
in query
.Split('&'))
220 string[] kv
= ent
.Split("=".ToCharArray(), 2);
221 string k
= HttpUtility
.UrlDecode(kv
[0]);
223 kv
.Length
>1 ? HttpUtility
.UrlDecode(kv
[1]) : "1";
229 public static void cookiesplit(Dictionary
<string,string> d
,
232 // Multiple values separated by & signs, as in URLs
233 foreach (string ent
in query
.Split(';'))
235 string[] kv
= ent
.Split("=".ToCharArray(), 2);
236 string k
= wv
.urldecode(kv
[0].Trim());
237 string v
= kv
.Length
>1 ? wv
.urldecode(kv
[1]) : "1";
243 static RandomNumberGenerator randserv
= null;
244 public static byte[] randombytes(int num
)
246 // lazy initialization, since it might be expensive. But we'll
247 // keep it around to ensure "maximum randomness"
248 if (randserv
== null)
249 randserv
= new RNGCryptoServiceProvider();
251 byte[] b
= new byte[num
];
252 randserv
.GetBytes(b
);
257 * A handy tool for making timeout loops. Use it like this:
259 * foreach (int remain in wv.until(t)) {
261 * if (exit_condition) break;
264 * New iterations of the loop will continue until DateTime.Now==t,
265 * or you exit the loop by hand.
267 * If t==DateTime.MinValue, loop will continue forever.
269 * 'remain' at each iteration will be the number of milliseconds
270 * remaining, or -1 if t==DateTime.MinValue.
272 * Even if the timeout is in the past, this is guaranteed to return
275 public static IEnumerable
<int> until(DateTime t
)
277 bool forever
= (t
== DateTime
.MinValue
);
278 DateTime n
= DateTime
.Now
;
281 while (!once
|| t
==DateTime
.MinValue
|| n
< t
)
288 int s
= (int)((n
-t
).TotalMilliseconds
);
298 * Like until(DateTime t), but works with a timeout in msec instead
301 * A negative timeout means "forever".
303 public static IEnumerable
<int> until(int msec_timeout
)
306 if (msec_timeout
< 0)
307 t
= DateTime
.MinValue
;
309 t
= DateTime
.Now
+ TimeSpan
.FromMilliseconds(msec_timeout
);
310 foreach (var i
in until(t
))
314 public static string add_breaks_to_newlines(string orig
)
316 StringBuilder retval
= new StringBuilder();
317 // Add a bit of space, since we expect to get a few newlines.
318 retval
.EnsureCapacity(orig
.Length
+ 32);
319 string[] split
= orig
.Split('\n');
320 for (int i
= 0; i
< split
.Length
; i
++)
324 // Don't do anything to the very end of the string
325 if (i
!= split
.Length
- 1)
327 string trimmed
= s
.Trim();
328 if (!trimmed
.EndsWith("<br>") && !trimmed
.EndsWith("<br/>")
329 && !trimmed
.EndsWith("<br />"))
331 retval
.Append("<br/>\n");
337 return retval
.ToString();
340 /// Extend Path.Combine to work on more than two path elements.
341 public static string PathCombine(string first
, params string[] rest
)
343 string combined
= first
;
344 foreach (string elem
in rest
)
345 combined
= Path
.Combine(combined
, elem
);
349 /// An alias for PathCombine that follows the Split/Join convention
350 public static string PathJoin(string first
, params string[] rest
)
352 return PathCombine(first
, rest
);
355 public static string[] PathSplit(string path
)
357 return path
.split(new char[] {
358 Path
.DirectorySeparatorChar
,
359 Path
.AltDirectorySeparatorChar
,
364 public static bool IsMono()
366 return Type
.GetType("Mono.Runtime") != null;
371 namespace Wv
.Obsolete
375 protected string logname
;
378 static TraceListener mytrace
= null;
379 static bool disable_mytrace
= false;
381 public Log(string logname
)
384 if (mytrace
== null && !disable_mytrace
385 && Trace
.Listeners
.Count
< 2)
387 mytrace
= new TextWriterTraceListener(Console
.Error
);
388 Trace
.Listeners
.Add(mytrace
);
391 //Trace.WriteLine(String.Format("Log constructor for '{0}'.",
394 this.logname
= logname
;
403 Trace
.Listeners
.Remove(mytrace
);
408 public static void no_default_listener()
410 disable_mytrace
= true;
413 Trace
.Listeners
.Remove(mytrace
);
418 public virtual void log(string format
, params object [] arg
)
420 // Console.Error.WriteLine("<" + logname + "> " + format, arg);
421 Trace
.WriteLine(String
.Format
422 ("[" + logname
+ "] " + format
, arg
));
426 public void log(string s
)
432 public class SilentLog
: Log
434 public SilentLog(string logname
) : base(logname
)
438 public override void log(string format
, params object [] arg
)
443 // This is intended to work sort of like PHP arrays, which are a mix of
444 // hash tables and lists. Looking up an entry in the hash is O(1), but
445 // when you iterate through all the entries, the ordering is well-defined.
447 // So far, this implementation is pretty limited and lacks a bunch of the
448 // things PHP can do, such as assigning to a particular array index.
449 public class SortedHash
: IEnumerable
451 ArrayList array
= new ArrayList();
452 Hashtable hash
= new Hashtable();
454 public IEnumerator
GetEnumerator()
456 return array
.GetEnumerator();
459 public void Add(string key
, object value)
462 if (!hash
.Contains(key
))
463 hash
.Add(key
, value);
468 get { return hash.Count; }
471 public bool Contains(object key
)
473 return hash
.Contains(key
);
476 public object Find(string key
)
481 public virtual object this[int index
]
483 get { return array[index]; }
486 public virtual void Sort()
491 public virtual void Sort(IComparer comparer
)
493 array
.Sort(comparer
);
502 public static explicit operator ArrayList(SortedHash x
)
504 return ArrayList
.ReadOnly(x
.array
);
508 public class ObjectCounter
: Hashtable
510 public new virtual int this [object key
]
516 return (int)base[key
];
523 Add(key
, (int)value);