123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Globalization;
- #pragma warning disable
- namespace Svg
- {
- internal class CoordinateParser
- {
- private enum NumState
- {
- invalid,
- separator,
- prefix,
- integer,
- decPlace,
- fraction,
- exponent,
- expPrefix,
- expValue
- }
- private string _coords;
- private int _pos = 0;
- private NumState _currState = NumState.separator;
- private NumState _newState = NumState.separator;
- private int i = 0;
- private bool _parseWorked = true;
- public int Position { get { return _pos; } }
- public CoordinateParser(string coords)
- {
- _coords = coords;
- if (string.IsNullOrEmpty(_coords)) _parseWorked = false;
- if (char.IsLetter(coords[0])) i++;
- }
- public bool HasMore { get { return _parseWorked; } }
- private bool MarkState(bool state)
- {
- _parseWorked = state;
- i++;
- return state;
- }
- public bool TryGetBool(out bool result)
- {
- while (i < _coords.Length && _parseWorked)
- {
- switch (_currState)
- {
- case NumState.separator:
- if (IsCoordSeparator(_coords[i]))
- {
- _newState = NumState.separator;
- }
- else if (_coords[i] == '0')
- {
- result = false;
- _newState = NumState.separator;
- _pos = i + 1;
- return MarkState(true);
- }
- else if (_coords[i] == '1')
- {
- result = true;
- _newState = NumState.separator;
- _pos = i + 1;
- return MarkState(true);
- }
- else
- {
- result = false;
- return MarkState(false);
- }
- break;
- default:
- result = false;
- return MarkState(false);
- }
- i++;
- }
- result = false;
- return MarkState(false);
- }
- public bool TryGetFloat(out float result)
- {
- while (i < _coords.Length && _parseWorked)
- {
- switch (_currState)
- {
- case NumState.separator:
- if (char.IsNumber(_coords[i]))
- {
- _newState = NumState.integer;
- }
- else if (IsCoordSeparator(_coords[i]))
- {
- _newState = NumState.separator;
- }
- else
- {
- switch (_coords[i])
- {
- case '.':
- _newState = NumState.decPlace;
- break;
- case '+':
- case '-':
- _newState = NumState.prefix;
- break;
- default:
- _newState = NumState.invalid;
- break;
- }
- }
- break;
- case NumState.prefix:
- if (char.IsNumber(_coords[i]))
- {
- _newState = NumState.integer;
- }
- else if (_coords[i] == '.')
- {
- _newState = NumState.decPlace;
- }
- else
- {
- _newState = NumState.invalid;
- }
- break;
- case NumState.integer:
- if (char.IsNumber(_coords[i]))
- {
- _newState = NumState.integer;
- }
- else if (IsCoordSeparator(_coords[i]))
- {
- _newState = NumState.separator;
- }
- else
- {
- switch (_coords[i])
- {
- case '.':
- _newState = NumState.decPlace;
- break;
- case 'E':
- case 'e':
- _newState = NumState.exponent;
- break;
- case '+':
- case '-':
- _newState = NumState.prefix;
- break;
- default:
- _newState = NumState.invalid;
- break;
- }
- }
- break;
- case NumState.decPlace:
- if (char.IsNumber(_coords[i]))
- {
- _newState = NumState.fraction;
- }
- else if (IsCoordSeparator(_coords[i]))
- {
- _newState = NumState.separator;
- }
- else
- {
- switch (_coords[i])
- {
- case 'E':
- case 'e':
- _newState = NumState.exponent;
- break;
- case '+':
- case '-':
- _newState = NumState.prefix;
- break;
- default:
- _newState = NumState.invalid;
- break;
- }
- }
- break;
- case NumState.fraction:
- if (char.IsNumber(_coords[i]))
- {
- _newState = NumState.fraction;
- }
- else if (IsCoordSeparator(_coords[i]))
- {
- _newState = NumState.separator;
- }
- else
- {
- switch (_coords[i])
- {
- case '.':
- _newState = NumState.decPlace;
- break;
- case 'E':
- case 'e':
- _newState = NumState.exponent;
- break;
- case '+':
- case '-':
- _newState = NumState.prefix;
- break;
- default:
- _newState = NumState.invalid;
- break;
- }
- }
- break;
- case NumState.exponent:
- if (char.IsNumber(_coords[i]))
- {
- _newState = NumState.expValue;
- }
- else if (IsCoordSeparator(_coords[i]))
- {
- _newState = NumState.invalid;
- }
- else
- {
- switch (_coords[i])
- {
- case '+':
- case '-':
- _newState = NumState.expPrefix;
- break;
- default:
- _newState = NumState.invalid;
- break;
- }
- }
- break;
- case NumState.expPrefix:
- if (char.IsNumber(_coords[i]))
- {
- _newState = NumState.expValue;
- }
- else
- {
- _newState = NumState.invalid;
- }
- break;
- case NumState.expValue:
- if (char.IsNumber(_coords[i]))
- {
- _newState = NumState.expValue;
- }
- else if (IsCoordSeparator(_coords[i]))
- {
- _newState = NumState.separator;
- }
- else
- {
- switch (_coords[i])
- {
- case '.':
- _newState = NumState.decPlace;
- break;
- case '+':
- case '-':
- _newState = NumState.prefix;
- break;
- default:
- _newState = NumState.invalid;
- break;
- }
- }
- break;
- }
- if (_newState < _currState)
- {
- result = float.Parse(_coords.Substring(_pos, i - _pos), NumberStyles.Float, CultureInfo.InvariantCulture);
- _pos = i;
- _currState = _newState;
- return MarkState(true);
- }
- else if (_newState != _currState && _currState == NumState.separator)
- {
- _pos = i;
- }
- if (_newState == NumState.invalid)
- {
- result = float.MinValue;
- return MarkState(false);
- }
- _currState = _newState;
- i++;
- }
- if (_currState == NumState.separator || !_parseWorked || _pos >= _coords.Length)
- {
- result = float.MinValue;
- return MarkState(false);
- }
- else
- {
- result = float.Parse(_coords.Substring(_pos, _coords.Length - _pos), NumberStyles.Float, CultureInfo.InvariantCulture);
- _pos = _coords.Length;
- return MarkState(true);
- }
- }
- private static bool IsCoordSeparator(char value)
- {
- switch (value)
- {
- case ' ':
- case '\t':
- case '\n':
- case '\r':
- case ',':
- return true;
- }
- return false;
- }
- }
- }
- #pragma warning restore
|