Multi-culture implementation ValueSerializers, Parse and ToString for types from...
[mono.git] / mcs / class / WindowsBase / System.Windows / NumericListTokenizer.cs
1 using System.Globalization;
2
3 namespace System.Windows
4 {
5         /// <summary>
6         /// Helper class for parsing serialized data structures from the System.Windows namespace.
7         /// </summary>
8         internal class NumericListTokenizer
9         {
10                 private readonly string _str;
11                 private readonly char _separator;
12                 private int _position;
13
14                 private enum Symbol
15                 {
16                         Token,
17                         Separator,
18                         Whitspace,
19                         EndOfLine
20                 }
21
22                 public NumericListTokenizer (string str, IFormatProvider formatProvider)
23                 {
24                         _str = str ?? throw new ArgumentNullException (nameof(str));
25                         _separator = GetSeparator (formatProvider ?? throw new ArgumentNullException (nameof(formatProvider)));
26                 }
27
28                 public static char GetSeparator (IFormatProvider formatProvider)
29                 {
30                         // By convention, string representations of target classes always use ';' as a separator
31                         // if the decimal number separator is ','. Otherwise, the separator is ','.
32                         return NumberFormatInfo.GetInstance (formatProvider).NumberDecimalSeparator != "," ? ',' : ';';
33                 }
34
35                 private Symbol GetCurrentSymbol ()
36                 {
37                         if (_position >= _str.Length)
38                                 return Symbol.EndOfLine;
39                         if (_str[_position] == _separator)
40                                 return Symbol.Separator;
41                         if (char.IsWhiteSpace (_str, _position))
42                                 return Symbol.Whitspace;
43                         return Symbol.Token;
44                 }
45
46                 private void SkipAllWhitespaces ()
47                 {
48                         while (GetCurrentSymbol () == Symbol.Whitspace)
49                         {
50                                 _position++;
51                         }
52                 }
53
54                 private void SkipNextDelimeter ()
55                 {
56                         SkipAllWhitespaces ();
57                         switch (GetCurrentSymbol ())
58                         {
59                                 case Symbol.Token:
60                                         return;
61                                 case Symbol.Separator:
62                                         _position++;
63                                         SkipAllWhitespaces ();
64                                         return;
65                                 default:
66                                         throw new InvalidOperationException ("Separator not found");
67                         }
68                 }
69
70                 public bool HasNoMoreTokens ()
71                 {
72                         SkipAllWhitespaces ();
73                         return GetCurrentSymbol () == Symbol.EndOfLine;
74                 }
75
76                 public string GetNextToken ()
77                 {
78                         var length = 0;
79                         if (_position == 0)
80                         {
81                                 SkipAllWhitespaces ();
82                         }
83                         else
84                         {
85                                 SkipNextDelimeter ();
86                         }
87
88                         while (GetCurrentSymbol () == Symbol.Token)
89                         {
90                                 _position++;
91                                 length++;
92                         }
93
94                         if (length == 0)
95                         {
96                                 throw new InvalidOperationException ("Next token not found");
97                         }
98
99                         return _str.Substring (_position - length, length);
100                 }
101         }
102 }