00001
00002
00003
00004
00005
00006 namespace NewGamePhysics.Utilities
00007 {
00008 using System;
00009 using System.Collections;
00010 using System.Collections.Generic;
00011 using System.Globalization;
00012 using System.Linq;
00013 using System.Text;
00014 using System.Text.RegularExpressions;
00015
00019 internal enum ParseType
00020 {
00021 Null,
00022 Int16,
00023 UInt16,
00024 UInt16Oct,
00025 UInt16Hex,
00026 Int32,
00027 UInt32,
00028 UInt32Oct,
00029 UInt32Hex,
00030 Int64,
00031 UInt64,
00032 UInt64Oct,
00033 UInt64Hex,
00034 Single,
00035 String,
00036 Double,
00037 Char
00038 }
00039
00044 public class Scanf
00045 {
00049 private const string integerPattern = @"[-+]?[0-9]+";
00050
00054 private const string octalIntegerPattern = @"[0-7]+";
00055
00059 private const string hexadecimalIntegerPattern = @"[0-9a-fA-F]+";
00060
00064 private const string floatingPointPattern = @"[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?";
00065
00069 private const string stringPattern = @"[\w\d\S]+";
00070
00074 private const string characterPattern = @"[\w\S]{1}";
00075
00079 private static char[] seperator = { '_' };
00080
00084 protected readonly Hashtable patterns;
00085
00089 protected readonly Hashtable types;
00090
00095 public static bool EnableTrace = false;
00096
00100 private MatchEvaluator matchEvaluator;
00101
00106 private int typeCount;
00107
00112 private string lastFormat;
00113
00117 private Regex conversionRegex;
00118
00123 public Scanf()
00124 {
00125
00126 patterns = new Hashtable();
00127
00128
00129 patterns.Add("%d", integerPattern);
00130 patterns.Add("%i", integerPattern);
00131 patterns.Add("%o", octalIntegerPattern);
00132 patterns.Add("%u", integerPattern);
00133 patterns.Add("%x", hexadecimalIntegerPattern);
00134 patterns.Add("%X", hexadecimalIntegerPattern);
00135 patterns.Add("%f", floatingPointPattern);
00136 patterns.Add("%g", floatingPointPattern);
00137 patterns.Add("%G", floatingPointPattern);
00138 patterns.Add("%s", stringPattern);
00139 patterns.Add("%c", characterPattern);
00140
00141
00142 patterns.Add("%lf", floatingPointPattern);
00143 patterns.Add("%lg", floatingPointPattern);
00144 patterns.Add("%lG", floatingPointPattern);
00145 patterns.Add("%ld", integerPattern);
00146 patterns.Add("%li", integerPattern);
00147 patterns.Add("%lo", octalIntegerPattern);
00148 patterns.Add("%lu", integerPattern);
00149 patterns.Add("%lx", hexadecimalIntegerPattern);
00150 patterns.Add("%lX", hexadecimalIntegerPattern);
00151
00152
00153 patterns.Add("%hd", integerPattern);
00154 patterns.Add("%hi", integerPattern);
00155 patterns.Add("%ho", octalIntegerPattern);
00156 patterns.Add("%hu", integerPattern);
00157 patterns.Add("%hx", hexadecimalIntegerPattern);
00158 patterns.Add("%hX", hexadecimalIntegerPattern);
00159
00160
00161 patterns.Add(@"%\*d", integerPattern);
00162 patterns.Add(@"%\*i", integerPattern);
00163 patterns.Add(@"%\*o", octalIntegerPattern);
00164 patterns.Add(@"%\*u", integerPattern);
00165 patterns.Add(@"%\*x", hexadecimalIntegerPattern);
00166 patterns.Add(@"%\*X", hexadecimalIntegerPattern);
00167 patterns.Add(@"%\*f", floatingPointPattern);
00168 patterns.Add(@"%\*g", floatingPointPattern);
00169 patterns.Add(@"%\*G", floatingPointPattern);
00170 patterns.Add(@"%\*s", stringPattern);
00171 patterns.Add(@"%\*c", characterPattern);
00172
00173 patterns.Add(@"%\*lf", floatingPointPattern);
00174 patterns.Add(@"%\*lg", floatingPointPattern);
00175 patterns.Add(@"%\*lG", floatingPointPattern);
00176 patterns.Add(@"%\*ld", integerPattern);
00177 patterns.Add(@"%\*li", integerPattern);
00178 patterns.Add(@"%\*lo", octalIntegerPattern);
00179 patterns.Add(@"%\*lu", integerPattern);
00180 patterns.Add(@"%\*lx", hexadecimalIntegerPattern);
00181 patterns.Add(@"%\*lX", hexadecimalIntegerPattern);
00182
00183 patterns.Add(@"%\*hd", integerPattern);
00184 patterns.Add(@"%\*hi", integerPattern);
00185 patterns.Add(@"%\*ho", octalIntegerPattern);
00186 patterns.Add(@"%\*hu", integerPattern);
00187 patterns.Add(@"%\*hx", hexadecimalIntegerPattern);
00188 patterns.Add(@"%\*hX", hexadecimalIntegerPattern);
00189
00190
00191 types = new Hashtable();
00192
00193 types.Add("%d", ParseType.Int32);
00194 types.Add("%i", ParseType.Int32);
00195 types.Add("%o", ParseType.UInt32Oct);
00196 types.Add("%u", ParseType.UInt32);
00197 types.Add("%x", ParseType.UInt32Hex);
00198 types.Add("%X", ParseType.UInt32Hex);
00199 types.Add("%f", ParseType.Single);
00200 types.Add("%g", ParseType.Single);
00201 types.Add("%G", ParseType.Single);
00202 types.Add("%s", ParseType.String);
00203 types.Add("%c", ParseType.Char);
00204
00205 types.Add("%lf", ParseType.Double);
00206 types.Add("%lg", ParseType.Double);
00207 types.Add("%lG", ParseType.Double);
00208 types.Add("%ld", ParseType.Int64);
00209 types.Add("%li", ParseType.Int64);
00210 types.Add("%lo", ParseType.UInt64Oct);
00211 types.Add("%lu", ParseType.UInt64);
00212 types.Add("%lx", ParseType.UInt64Hex);
00213 types.Add("%lX", ParseType.UInt64Hex);
00214
00215 types.Add("%hd", ParseType.Int16);
00216 types.Add("%hi", ParseType.Int16);
00217 types.Add("%ho", ParseType.UInt16Oct);
00218 types.Add("%hu", ParseType.UInt16);
00219 types.Add("%hx", ParseType.UInt16Hex);
00220 types.Add("%hX", ParseType.UInt16Hex);
00221
00222
00223 matchEvaluator = new MatchEvaluator(ReplaceFormatCode);
00224 }
00225
00241 public object[] Scan(string text, string format)
00242 {
00243
00244 if ((String.IsNullOrEmpty(lastFormat)) ||
00245 (lastFormat != format))
00246 {
00247
00248 string formatPattern = format;
00249
00250
00251 formatPattern = Regex.Replace(formatPattern, @"\s+", @"\s+");
00252
00253
00254
00255 typeCount = 0;
00256
00257
00258 foreach (string formatCode in patterns.Keys)
00259 {
00260 formatPattern = Regex.Replace(
00261 formatPattern,
00262 formatCode,
00263 matchEvaluator);
00264 }
00265 Trace("scanf_trace: format_pattern: ", formatPattern);
00266
00267
00268 conversionRegex = new Regex(formatPattern);
00269
00270
00271 lastFormat = format;
00272 }
00273
00274
00275 string[] groupNames = conversionRegex.GetGroupNames();
00276
00277
00278 List<object> targets = new List<object>();
00279
00280 if (groupNames.Length > 0)
00281 {
00282
00283 MatchCollection matchCollection = conversionRegex.Matches(text);
00284 foreach (Match match in matchCollection)
00285 {
00286 if (match.Success)
00287 {
00288 foreach (string groupName in groupNames)
00289 {
00290 if (groupName.Contains(seperator[0]))
00291 {
00292
00293 string typeName = groupName.Remove(groupName.LastIndexOfAny(seperator));
00294 ParseType parseType = (ParseType)Enum.Parse(typeof(ParseType), typeName);
00295
00296
00297 string valueText = match.Groups[groupName].Value;
00298
00299
00300 object target = null;
00301 try
00302 {
00303 target = Parse(parseType, valueText);
00304 }
00305 catch (Exception e)
00306 {
00307 Trace("scanf_trace: exception:", e.ToString());
00308 }
00309 finally
00310 {
00311 targets.Add(target);
00312 }
00313
00314
00315
00316 if (targets.Count == typeCount)
00317 {
00318 return targets.ToArray();
00319 }
00320 }
00321 }
00322 }
00323 }
00324 }
00325
00326
00327 return targets.ToArray();
00328 }
00329
00335 private string ReplaceFormatCode(Match m)
00336 {
00337 string groupName;
00338
00339
00340 typeCount++;
00341
00342
00343 if (types.ContainsKey(m.Value))
00344 {
00345 groupName = types[m.Value].ToString();
00346 }
00347 else
00348 {
00349
00350 groupName = "Null";
00351 }
00352
00353
00354 StringBuilder sb = new StringBuilder();
00355 sb.Append("(?<");
00356 sb.Append(groupName);
00357 sb.Append(seperator[0]);
00358 sb.Append(typeCount);
00359 sb.Append(">");
00360 sb.Append(patterns[m.Value]);
00361 sb.Append(")");
00362
00363 return sb.ToString();
00364 }
00365
00373 private object Parse(ParseType parseType, string text)
00374 {
00375 switch (parseType)
00376 {
00377 case ParseType.Null:
00378 return null;
00379 case ParseType.String:
00380 return text;
00381 case ParseType.Int16:
00382 return Int16.Parse(text, CultureInfo.InvariantCulture);
00383 case ParseType.UInt16:
00384 return UInt16.Parse(text, CultureInfo.InvariantCulture);
00385 case ParseType.UInt16Hex:
00386 return UInt16.Parse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
00387 case ParseType.UInt16Oct:
00388 return Convert.ToUInt16(text, 8);
00389 case ParseType.Int32:
00390 return Int32.Parse(text, CultureInfo.InvariantCulture);
00391 case ParseType.UInt32:
00392 return UInt32.Parse(text, CultureInfo.InvariantCulture);
00393 case ParseType.UInt32Hex:
00394 return UInt32.Parse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
00395 case ParseType.UInt32Oct:
00396 return Convert.ToUInt32(text, 8);
00397 case ParseType.Int64:
00398 return Int64.Parse(text, CultureInfo.InvariantCulture);
00399 case ParseType.UInt64:
00400 return UInt64.Parse(text, CultureInfo.InvariantCulture);
00401 case ParseType.UInt64Hex:
00402 return UInt64.Parse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
00403 case ParseType.UInt64Oct:
00404 return Convert.ToUInt64(text, 8);
00405 case ParseType.Single:
00406 return Single.Parse(text, CultureInfo.InvariantCulture);
00407 case ParseType.Double:
00408 return Double.Parse(text, CultureInfo.InvariantCulture);
00409 case ParseType.Char:
00410 return Char.Parse(text);
00411 }
00412
00413 return null;
00414 }
00415
00420 private static void Trace(string label, string message)
00421 {
00422 if (EnableTrace)
00423 {
00424 System.Console.Write(label);
00425 System.Console.Write(": ");
00426 System.Console.WriteLine(message);
00427 }
00428 }
00429 }
00430 }