Allow schema files that are missing checksums on the !!SCHEMAMATIC line.
[versaplex.git] / wvdotnet / wvutils.cs
blob35006386efac3dc34e7cbbcf6c94e864e9989715
1 /*
2 * Versaplex:
3 * Copyright (C)2007-2008 Versabanq Innovations Inc. and contributors.
4 * See the included file named LICENSE for license information.
5 */
6 #define DEBUG
7 #define TRACE
9 using System;
10 using System.Collections;
11 using System.Collections.Generic;
12 using System.Diagnostics;
13 using System.IO;
14 using System.Security.Cryptography;
15 using System.Text;
16 using System.Threading;
17 using System.Web;
18 using Wv.Extensions;
20 namespace Wv
22 public partial class wv
24 public static void sleep(int msec_delay)
26 if (msec_delay < 0)
27 Thread.Sleep(Int32.MaxValue);
28 else
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);
38 array = outa;
39 return s;
42 public static string shift(ref string[] array)
44 return shift(ref array, 0);
47 public static void assert(bool b, object msg)
49 if (!b)
50 throw new System.ArgumentException(msg.ToString());
53 public static void assert(bool b, string fmt, params object[] args)
55 if (!b)
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()
66 assert(false);
69 public static DateTime date(object s)
71 try
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();
98 int i = 0;
99 if (ca.Length > 0 && ca[0] == '-')
100 i++;
101 bool saw_dot = false;
102 for (; i < ca.Length; i++)
104 if (ca[i] == '.')
106 if (saw_dot || !allow_dot)
107 break;
108 saw_dot = true;
110 if ("0123456789.".IndexOf(ca[i]) < 0)
111 break;
114 return s.Substring(0, i);
117 public static double atod(object o)
119 try {
120 return Double.Parse(intclean(o, true));
121 } catch (FormatException) {
122 return 0.0;
126 public static int atoi(object o)
128 try {
129 return Int32.Parse(intclean(o, false));
130 } catch (FormatException) {
131 return 0;
135 public static long atol(object o)
137 try {
138 return Int64.Parse(intclean(o, false));
139 } catch (FormatException) {
140 return 0;
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);
179 return sorted;
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];
190 int i = 0;
191 foreach (object o in keys)
192 a[i++] = o.ToString();
193 return a;
196 public static string getenv(string key)
198 string o = Environment.GetEnvironmentVariable(key);
199 if (o != null)
200 return o;
201 else
202 return "";
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]);
222 string v =
223 kv.Length>1 ? HttpUtility.UrlDecode(kv[1]) : "1";
224 d.Remove(k);
225 d.Add(k, v);
229 public static void cookiesplit(Dictionary<string,string> d,
230 string query)
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";
238 d.Remove(k);
239 d.Add(k, v);
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);
253 return b;
257 * A handy tool for making timeout loops. Use it like this:
259 * foreach (int remain in wv.until(t)) {
260 * do_stuff();
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
273 * at least once.
275 public static IEnumerable<int> until(DateTime t)
277 bool forever = (t == DateTime.MinValue);
278 DateTime n = DateTime.Now;
279 bool once = false;
281 while (!once || t==DateTime.MinValue || n < t)
283 once = true;
284 if (forever)
285 yield return -1;
286 else
288 int s = (int)((n-t).TotalMilliseconds);
289 if (s < 0)
290 s = 0;
291 yield return s;
293 n = DateTime.Now;
298 * Like until(DateTime t), but works with a timeout in msec instead
299 * of an exact time.
301 * A negative timeout means "forever".
303 public static IEnumerable<int> until(int msec_timeout)
305 DateTime t;
306 if (msec_timeout < 0)
307 t = DateTime.MinValue;
308 else
309 t = DateTime.Now + TimeSpan.FromMilliseconds(msec_timeout);
310 foreach (var i in until(t))
311 yield return i;
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++)
322 string s = split[i];
323 retval.Append(s);
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");
333 else
334 retval.Append("\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);
346 return combined;
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
373 public class Log
375 protected string logname;
377 static int refs = 0;
378 static TraceListener mytrace = null;
379 static bool disable_mytrace = false;
381 public Log(string logname)
383 refs++;
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}'.",
392 // logname));
393 Trace.Flush();
394 this.logname = logname;
397 ~Log()
399 refs--;
400 if (refs == 0)
402 if (mytrace != null)
403 Trace.Listeners.Remove(mytrace);
404 mytrace = null;
408 public static void no_default_listener()
410 disable_mytrace = true;
411 if (mytrace != null)
413 Trace.Listeners.Remove(mytrace);
414 mytrace = null;
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));
423 Trace.Flush();
426 public void log(string s)
428 log("{0}", 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)
461 array.Add(value);
462 if (!hash.Contains(key))
463 hash.Add(key, value);
466 public int Count
468 get { return hash.Count; }
471 public bool Contains(object key)
473 return hash.Contains(key);
476 public object Find(string key)
478 return hash[key];
481 public virtual object this[int index]
483 get { return array[index]; }
486 public virtual void Sort()
488 array.Sort();
491 public virtual void Sort(IComparer comparer)
493 array.Sort(comparer);
496 public void Clear()
498 array.Clear();
499 hash.Clear();
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]
514 if (!Contains(key))
515 Add(key, 0);
516 return (int)base[key];
521 if (Contains(key))
522 Remove(key);
523 Add(key, (int)value);