using System; using System.Collections.Generic; using System.Linq; namespace SpriteWave { public class Suffix { private bool _insert = false; private string _preIns = null; private string _postIns = null; private int _fmtBase = 0; private int _nDigits = 0; private bool _upperCase = false; public bool HasInsert { get { return _insert; } } public int Base { get { return _fmtBase; } } public int Digits { get { return _nDigits; } } public Suffix(string fmt) { var subs = new[] { new { start = 0, len = 0} }.ToList(); string ins = null; int insOff = -1; int level = 0; int idx = 0; foreach (char c in fmt) { if (c == '{') { if (level == 0) insOff = idx; level++; } if (c == '}') { if (level == 1 && insOff >= 0 && idx - insOff > 1) { if (insOff > 0) _preIns = fmt.Substring(0, insOff); ins = fmt.Substring(insOff + 1, idx - (insOff + 1)); int post = idx + 1; if (post < fmt.Length - 1) _postIns = fmt.Substring(post); _insert = true; } level--; } idx++; if (_insert) break; } if (level != 0) throw new ArgumentException("Trailing curly-braces in suffix format"); if (!_insert) { _preIns = fmt; return; } if (ins.Length <= 1) throw new ArgumentException("Suffix format is too short (must include a base type and a length, eg. d3)"); switch (Char.ToLower(ins[0])) { case 'b': _fmtBase = 2; break; case 'o': _fmtBase = 8; break; case 'd': _fmtBase = 10; break; case 'x': _fmtBase = 16; break; default: throw new ArgumentException("Invalid base type '" + ins[0] + "' in suffix format \"" + ins + "\""); } _upperCase = Char.IsUpper(ins[0]); _nDigits = Convert.ToInt32(ins.Substring(1)); if (_nDigits < 1) throw new ArgumentException("The suffix number must take at least one digit"); } public string Generate(int num) { if (!_insert) return _preIns; if (num < 0) throw new ArgumentException("Negative numbers are not permitted in the suffix"); int maxNum = (int)Math.Pow(_fmtBase, _nDigits) - 1; if (num > maxNum) throw new ArgumentException("The given number " + num + " exceeds the number limit of the given format (" + maxNum + ")"); int n = num; string str = ""; for (int i = 0; i < _nDigits; i++) { int d = n % _fmtBase; n /= _fmtBase; char c; if (d >= 10) { int a = _upperCase ? (int)'A' : (int)'a'; c = Convert.ToChar(a - 10 + d); } else c = Convert.ToChar((int)'0' + d); str = c + str; } return _preIns + str + _postIns; } public int ValueOf(string str) { if (!_insert) throw new InvalidOperationException("This suffix does not contain a number insert (eg. {d3})"); int preLen = _preIns != null ? _preIns.Length : 0; int postLen = _postIns != null ? _postIns.Length : 0; int len = preLen + _nDigits + postLen; if (str.Length != len) throw new ArgumentException( "The given string is the wrong size to be of this suffix\n" + "Expected: " + len + ", actual: " + str.Length ); string pre = preLen > 0 ? str.Substring(0, preLen) : null; string post = postLen > 0 ? str.Substring(str.Length - postLen) : null; if (pre != _preIns || post != _postIns) { throw new ArgumentException( "The given string does not have the surrounding components of the suffix\n" + "(\"" + pre + "\" & \"" + post + "\" != \"" + _preIns + "\" & \"" + _postIns + "\")" ); } int num = 0; for (int i = 0; i < _nDigits; i++) { num *= _fmtBase; char c = str[preLen + i]; int d; if (c >= '0' && c <= '9') d = c - '0'; else if (c >= 'A' && c <= 'Z') d = c - 'A' + 10; else if (c >= 'a' && c <= 'z') d = c - 'a' + 10; else throw new ArgumentOutOfRangeException("Character '" + c + "' at offset " + i + " is not an acceptable digit"); if (d >= _fmtBase) throw new ArgumentOutOfRangeException("The number " + d + " inside the given string does not fit within this base (base-" + _fmtBase + ")"); num += d; } return num; } public int[] ListOfValues(string[] strList) { if (strList == null) return null; var values = new List(); foreach (string str in strList) { int n; try { n = this.ValueOf(str); values.Add(n); } catch (Exception ex) { if (ex is InvalidOperationException) return null; if (ex is ArgumentNullException || ex is ArgumentException || ex is ArgumentOutOfRangeException) { continue; } } } if (values.Count < 1) return null; values.Sort(); return values.ToArray(); } } }