| @@ -1,9 +1,9 | |||||
| 1 |  | 1 | |||
| 2 | namespace Implab.Automaton { |  | 2 | namespace Implab.Automaton { | |
| 3 | public static class |  | 3 | public static class AutomatonConst { | |
| 4 | public const int UNREACHABLE_STATE = -1; |  | 4 | public const int UNREACHABLE_STATE = -1; | |
| 5 |  | 5 | |||
| 6 | public const int UNCLASSIFIED_INPUT = 0; |  | 6 | public const int UNCLASSIFIED_INPUT = 0; | |
| 7 | } |  | 7 | } | |
| 8 | } |  | 8 | } | |
| 9 |  | 9 | |||
| @@ -1,83 +1,83 | |||||
| 1 | using System.Collections.Generic; |  | 1 | using System.Collections.Generic; | |
| 2 | using System.Linq; |  | 2 | using System.Linq; | |
| 3 |  | 3 | |||
| 4 | namespace Implab.Automaton.RegularExpressions { |  | 4 | namespace Implab.Automaton.RegularExpressions { | |
| 5 | public class |  | 5 | public class RegularDFA<TInput, TTag> : DFATable, ITaggedDFABuilder<TTag> { | |
| 6 |  | 6 | |||
| 7 | readonly Dictionary<int,TTag[]> m_tags = new Dictionary<int, TTag[]>(); |  | 7 | readonly Dictionary<int,TTag[]> m_tags = new Dictionary<int, TTag[]>(); | |
| 8 | readonly IAlphabet<TInput> m_alphabet; |  | 8 | readonly IAlphabet<TInput> m_alphabet; | |
| 9 |  | 9 | |||
| 10 | public |  | 10 | public RegularDFA(IAlphabet<TInput> alphabet) { | |
| 11 | Safe.ArgumentNotNull(alphabet, "aplhabet"); |  | 11 | Safe.ArgumentNotNull(alphabet, "aplhabet"); | |
| 12 |  | 12 | |||
| 13 | m_alphabet = alphabet; |  | 13 | m_alphabet = alphabet; | |
| 14 | } |  | 14 | } | |
| 15 |  | 15 | |||
| 16 |  | 16 | |||
| 17 | public IAlphabet<TInput> InputAlphabet { |  | 17 | public IAlphabet<TInput> InputAlphabet { | |
| 18 | get { |  | 18 | get { | |
| 19 | return m_alphabet; |  | 19 | return m_alphabet; | |
| 20 | } |  | 20 | } | |
| 21 | } |  | 21 | } | |
| 22 |  | 22 | |||
| 23 | public void MarkFinalState(int s, TTag[] tags) { |  | 23 | public void MarkFinalState(int s, TTag[] tags) { | |
| 24 | MarkFinalState(s); |  | 24 | MarkFinalState(s); | |
| 25 | SetStateTag(s, tags); |  | 25 | SetStateTag(s, tags); | |
| 26 | } |  | 26 | } | |
| 27 |  | 27 | |||
| 28 | public void SetStateTag(int s, TTag[] tags) { |  | 28 | public void SetStateTag(int s, TTag[] tags) { | |
| 29 | Safe.ArgumentNotNull(tags, "tags"); |  | 29 | Safe.ArgumentNotNull(tags, "tags"); | |
| 30 | m_tags[s] = tags; |  | 30 | m_tags[s] = tags; | |
| 31 | } |  | 31 | } | |
| 32 |  | 32 | |||
| 33 | public TTag[] GetStateTag(int s) { |  | 33 | public TTag[] GetStateTag(int s) { | |
| 34 | TTag[] tags; |  | 34 | TTag[] tags; | |
| 35 | return m_tags.TryGetValue(s, out tags) ? tags : new TTag[0]; |  | 35 | return m_tags.TryGetValue(s, out tags) ? tags : new TTag[0]; | |
| 36 | } |  | 36 | } | |
| 37 |  | 37 | |||
| 38 | public TTag[][] CreateTagTable() { |  | 38 | public TTag[][] CreateTagTable() { | |
| 39 | var table = new TTag[StateCount][]; |  | 39 | var table = new TTag[StateCount][]; | |
| 40 |  | 40 | |||
| 41 | foreach (var pair in m_tags) |  | 41 | foreach (var pair in m_tags) | |
| 42 | table[pair.Key] = pair.Value; |  | 42 | table[pair.Key] = pair.Value; | |
| 43 |  | 43 | |||
| 44 | return table; |  | 44 | return table; | |
| 45 | } |  | 45 | } | |
| 46 |  | 46 | |||
| 47 | /// <summary> |  | 47 | /// <summary> | |
| 48 | /// Optimize the specified alphabet. |  | 48 | /// Optimize the specified alphabet. | |
| 49 | /// </summary> |  | 49 | /// </summary> | |
| 50 | /// <param name="alphabet">ΠΡΡΡΠΎΠΉ Π°Π»ΡΠ°Π²ΠΈΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅Ρ Π·ΠΏΠΎΠ»Π½Π΅Π½ Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ.</param> |  | 50 | /// <param name="alphabet">ΠΡΡΡΠΎΠΉ Π°Π»ΡΠ°Π²ΠΈΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅Ρ Π·ΠΏΠΎΠ»Π½Π΅Π½ Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ.</param> | |
| 51 | public |  | 51 | public RegularDFA<TInput,TTag> Optimize(IAlphabetBuilder<TInput> alphabet) { | |
| 52 | Safe.ArgumentNotNull(alphabet, "alphabet"); |  | 52 | Safe.ArgumentNotNull(alphabet, "alphabet"); | |
| 53 |  | 53 | |||
| 54 | var dfa = new |  | 54 | var dfa = new RegularDFA<TInput, TTag>(alphabet); | |
| 55 |  | 55 | |||
| 56 | var states = new DummyAlphabet(StateCount); |  | 56 | var states = new DummyAlphabet(StateCount); | |
| 57 | var alphaMap = new Dictionary<int,int>(); |  | 57 | var alphaMap = new Dictionary<int,int>(); | |
| 58 | var stateMap = new Dictionary<int,int>(); |  | 58 | var stateMap = new Dictionary<int,int>(); | |
| 59 |  | 59 | |||
| 60 | Optimize(dfa, alphaMap, stateMap); |  | 60 | Optimize(dfa, alphaMap, stateMap); | |
| 61 |  | 61 | |||
| 62 | // mark tags in the new DFA |  | 62 | // mark tags in the new DFA | |
| 63 | foreach (var g in m_tags.Where(x => x.Key < StateCount).GroupBy(x => stateMap[x.Key], x => x.Value )) |  | 63 | foreach (var g in m_tags.Where(x => x.Key < StateCount).GroupBy(x => stateMap[x.Key], x => x.Value )) | |
| 64 | dfa.SetStateTag(g.Key, g.SelectMany(x => x).ToArray()); |  | 64 | dfa.SetStateTag(g.Key, g.SelectMany(x => x).ToArray()); | |
| 65 |  | 65 | |||
| 66 | // make the alphabet for the new DFA |  | 66 | // make the alphabet for the new DFA | |
| 67 | foreach (var pair in alphaMap) |  | 67 | foreach (var pair in alphaMap) | |
| 68 | alphabet.DefineClass(m_alphabet.GetSymbols(pair.Key), pair.Value); |  | 68 | alphabet.DefineClass(m_alphabet.GetSymbols(pair.Key), pair.Value); | |
| 69 |  | 69 | |||
| 70 | return dfa; |  | 70 | return dfa; | |
| 71 | } |  | 71 | } | |
| 72 |  | 72 | |||
| 73 | protected override IEnumerable<HashSet<int>> GroupFinalStates() { |  | 73 | protected override IEnumerable<HashSet<int>> GroupFinalStates() { | |
| 74 | var arrayComparer = new CustomEqualityComparer<TTag[]>( |  | 74 | var arrayComparer = new CustomEqualityComparer<TTag[]>( | |
| 75 | (x,y) => x.Length == y.Length && x.All(it => y.Contains(it)), |  | 75 | (x,y) => x.Length == y.Length && x.All(it => y.Contains(it)), | |
| 76 | x => x.Sum(it => x.GetHashCode()) |  | 76 | x => x.Sum(it => x.GetHashCode()) | |
| 77 | ); |  | 77 | ); | |
| 78 | return FinalStates.GroupBy(x => m_tags[x], arrayComparer).Select(g => new HashSet<int>(g)); |  | 78 | return FinalStates.GroupBy(x => m_tags[x], arrayComparer).Select(g => new HashSet<int>(g)); | |
| 79 | } |  | 79 | } | |
| 80 |  | 80 | |||
| 81 | } |  | 81 | } | |
| 82 | } |  | 82 | } | |
| 83 |  | 83 | |||
| @@ -1,104 +1,104 | |||||
| 1 | using System; |  | 1 | using System; | |
| 2 | using System.Globalization; |  | 2 | using System.Globalization; | |
| 3 | using Implab.Automaton; |  | 3 | using Implab.Automaton; | |
| 4 | using System.Text; |  | 4 | using System.Text; | |
| 5 | using Implab.Components; |  | 5 | using Implab.Components; | |
| 6 | using System.IO; |  | 6 | using System.IO; | |
| 7 |  | 7 | |||
| 8 | namespace Implab.Formats.JSON { |  | 8 | namespace Implab.Formats.JSON { | |
| 9 | /// <summary> |  | 9 | /// <summary> | |
| 10 | /// Π‘ΠΊΠ°Π½Π½Π΅Ρ (Π»Π΅ΠΊΡΠ΅Ρ), ΡΠ°Π·Π±ΠΈΠ²Π°ΡΡΠΈΠΉ ΠΏΠΎΡΠΎΠΊ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² Π½Π° ΡΠΎΠΊΠ΅Π½Ρ JSON. |  | 10 | /// Π‘ΠΊΠ°Π½Π½Π΅Ρ (Π»Π΅ΠΊΡΠ΅Ρ), ΡΠ°Π·Π±ΠΈΠ²Π°ΡΡΠΈΠΉ ΠΏΠΎΡΠΎΠΊ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² Π½Π° ΡΠΎΠΊΠ΅Π½Ρ JSON. | |
| 11 | /// </summary> |  | 11 | /// </summary> | |
| 12 | public class JSONScanner : Disposable { |  | 12 | public class JSONScanner : Disposable { | |
| 13 | readonly StringBuilder m_builder = new StringBuilder(); |  | 13 | readonly StringBuilder m_builder = new StringBuilder(); | |
| 14 |  | 14 | |||
| 15 | readonly ScannerContext<JSONGrammar.TokenType> m_jsonContext = JSONGrammar.Instance.Json |  | 15 | readonly ScannerContext<JSONGrammar.TokenType> m_jsonContext = JSONGrammar.Instance.JsonExpression; | |
| 16 | readonly ScannerContext<JSONGrammar.TokenType> m_stringContext = JSONGrammar.Instance.JsonString |  | 16 | readonly ScannerContext<JSONGrammar.TokenType> m_stringContext = JSONGrammar.Instance.JsonStringExpression; | |
| 17 |  | 17 | |||
| 18 |  | 18 | |||
| 19 | readonly TextScanner m_scanner; |  | 19 | readonly TextScanner m_scanner; | |
| 20 |  | 20 | |||
| 21 | /// <summary> |  | 21 | /// <summary> | |
| 22 | /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ Π½ΠΎΠ²ΡΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ ΡΠΊΠ°Π½Π½Π΅ΡΠ° |  | 22 | /// Π‘ΠΎΠ·Π΄Π°Π΅Ρ Π½ΠΎΠ²ΡΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ ΡΠΊΠ°Π½Π½Π΅ΡΠ° | |
| 23 | /// </summary> |  | 23 | /// </summary> | |
| 24 | public JSONScanner(string text) { |  | 24 | public JSONScanner(string text) { | |
| 25 | Safe.ArgumentNotEmpty(text, "text"); |  | 25 | Safe.ArgumentNotEmpty(text, "text"); | |
| 26 |  | 26 | |||
| 27 | m_scanner = new StringScanner(text); |  | 27 | m_scanner = new StringScanner(text); | |
| 28 | } |  | 28 | } | |
| 29 |  | 29 | |||
| 30 | public JSONScanner(TextReader reader, int bufferMax, int chunkSize) { |  | 30 | public JSONScanner(TextReader reader, int bufferMax, int chunkSize) { | |
| 31 | Safe.ArgumentNotNull(reader, "reader"); |  | 31 | Safe.ArgumentNotNull(reader, "reader"); | |
| 32 |  | 32 | |||
| 33 | m_scanner = new ReaderScanner(reader, bufferMax, chunkSize); |  | 33 | m_scanner = new ReaderScanner(reader, bufferMax, chunkSize); | |
| 34 | } |  | 34 | } | |
| 35 |  | 35 | |||
| 36 | /// <summary> |  | 36 | /// <summary> | |
| 37 | /// Π§ΠΈΡΠ°Π΅Ρ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ Π»Π΅ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΠ»Π΅ΠΌΠ΅Π½Ρ ΠΈΠ· Π²Ρ ΠΎΠ΄Π½ΡΡ Π΄Π°Π½Π½ΡΡ . |  | 37 | /// Π§ΠΈΡΠ°Π΅Ρ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ Π»Π΅ΠΊΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΠ»Π΅ΠΌΠ΅Π½Ρ ΠΈΠ· Π²Ρ ΠΎΠ΄Π½ΡΡ Π΄Π°Π½Π½ΡΡ . | |
| 38 | /// </summary> |  | 38 | /// </summary> | |
| 39 | /// <param name="tokenValue">ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΎΡΠΈΡΠ°Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠΊΠ΅Π½Π°.</param> |  | 39 | /// <param name="tokenValue">ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΎΡΠΈΡΠ°Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠΊΠ΅Π½Π°.</param> | |
| 40 | /// <param name="tokenType">ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠΈΠΏ ΠΏΡΠΎΡΠΈΡΠ°Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠΊΠ΅Π½Π°.</param> |  | 40 | /// <param name="tokenType">ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠΈΠΏ ΠΏΡΠΎΡΠΈΡΠ°Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠΊΠ΅Π½Π°.</param> | |
| 41 | /// <returns><c>true</c> - ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΎ ΡΡΠΏΠ΅ΡΠ½ΠΎ. <c>false</c> - Π΄ΠΎΡΡΠΈΠ³Π½ΡΡ ΠΊΠΎΠ½Π΅Ρ Π²Ρ ΠΎΠ΄Π½ΡΡ Π΄Π°Π½Π½ΡΡ </returns> |  | 41 | /// <returns><c>true</c> - ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΎ ΡΡΠΏΠ΅ΡΠ½ΠΎ. <c>false</c> - Π΄ΠΎΡΡΠΈΠ³Π½ΡΡ ΠΊΠΎΠ½Π΅Ρ Π²Ρ ΠΎΠ΄Π½ΡΡ Π΄Π°Π½Π½ΡΡ </returns> | |
| 42 | /// <remarks>Π ΡΠ»ΡΡΠ΅ Π΅ΡΠ»ΠΈ ΡΠΎΠΊΠ΅Π½ Π½Π΅ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π΅ΡΡΡ, Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅. ΠΠ½Π°ΡΠ΅Π½ΠΈΡ ΡΠΎΠΊΠ΅Π½ΠΎΠ² ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ, Ρ.Π΅. |  | 42 | /// <remarks>Π ΡΠ»ΡΡΠ΅ Π΅ΡΠ»ΠΈ ΡΠΎΠΊΠ΅Π½ Π½Π΅ ΡΠ°ΡΠΏΠΎΠ·Π½Π°Π΅ΡΡΡ, Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅. ΠΠ½Π°ΡΠ΅Π½ΠΈΡ ΡΠΎΠΊΠ΅Π½ΠΎΠ² ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ, Ρ.Π΅. | |
| 43 | /// Π² ΡΡΡΠΎΠΊΠ°Ρ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ ΡΠΊΡΠ°Π½ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΡΠΈΠΌΠ²ΠΎΠ»Ρ, ΡΠΈΡΠ»Π° ΡΡΠ°Π½ΠΎΠ²ΡΡΡ ΡΠΈΠΏΠ° double.</remarks> |  | 43 | /// Π² ΡΡΡΠΎΠΊΠ°Ρ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ ΡΠΊΡΠ°Π½ΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ ΡΠΈΠΌΠ²ΠΎΠ»Ρ, ΡΠΈΡΠ»Π° ΡΡΠ°Π½ΠΎΠ²ΡΡΡ ΡΠΈΠΏΠ° double.</remarks> | |
| 44 | public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) { |  | 44 | public bool ReadToken(out object tokenValue, out JsonTokenType tokenType) { | |
| 45 | JSONGrammar.TokenType[] tag; |  | 45 | JSONGrammar.TokenType[] tag; | |
| 46 | if (m_jsonContext.Execute(m_scanner, out tag)) { |  | 46 | if (m_jsonContext.Execute(m_scanner, out tag)) { | |
| 47 | switch (tag[0]) { |  | 47 | switch (tag[0]) { | |
| 48 | case JSONGrammar.TokenType.StringBound: |  | 48 | case JSONGrammar.TokenType.StringBound: | |
| 49 | tokenValue = ReadString(); |  | 49 | tokenValue = ReadString(); | |
| 50 | tokenType = JsonTokenType.String; |  | 50 | tokenType = JsonTokenType.String; | |
| 51 | break; |  | 51 | break; | |
| 52 | case JSONGrammar.TokenType.Number: |  | 52 | case JSONGrammar.TokenType.Number: | |
| 53 | tokenValue = Double.Parse(m_scanner.GetTokenValue(), CultureInfo.InvariantCulture); |  | 53 | tokenValue = Double.Parse(m_scanner.GetTokenValue(), CultureInfo.InvariantCulture); | |
| 54 | tokenType = JsonTokenType.Number; |  | 54 | tokenType = JsonTokenType.Number; | |
| 55 | break; |  | 55 | break; | |
| 56 | default: |  | 56 | default: | |
| 57 | tokenType = (JsonTokenType)tag[0]; |  | 57 | tokenType = (JsonTokenType)tag[0]; | |
| 58 | tokenValue = m_scanner.GetTokenValue(); |  | 58 | tokenValue = m_scanner.GetTokenValue(); | |
| 59 | break; |  | 59 | break; | |
| 60 | } |  | 60 | } | |
| 61 | return true; |  | 61 | return true; | |
| 62 | } |  | 62 | } | |
| 63 | tokenValue = null; |  | 63 | tokenValue = null; | |
| 64 | tokenType = JsonTokenType.None; |  | 64 | tokenType = JsonTokenType.None; | |
| 65 | return false; |  | 65 | return false; | |
| 66 | } |  | 66 | } | |
| 67 |  | 67 | |||
| 68 | string ReadString() { |  | 68 | string ReadString() { | |
| 69 | int pos = 0; |  | 69 | int pos = 0; | |
| 70 | var buf = new char[6]; // the buffer for unescaping chars |  | 70 | var buf = new char[6]; // the buffer for unescaping chars | |
| 71 |  | 71 | |||
| 72 | JSONGrammar.TokenType[] tag; |  | 72 | JSONGrammar.TokenType[] tag; | |
| 73 | m_builder.Clear(); |  | 73 | m_builder.Clear(); | |
| 74 |  | 74 | |||
| 75 | while (m_stringContext.Execute(m_scanner, out tag)) { |  | 75 | while (m_stringContext.Execute(m_scanner, out tag)) { | |
| 76 | switch (tag[0]) { |  | 76 | switch (tag[0]) { | |
| 77 | case JSONGrammar.TokenType.StringBound: |  | 77 | case JSONGrammar.TokenType.StringBound: | |
| 78 | return m_builder.ToString(); |  | 78 | return m_builder.ToString(); | |
| 79 | case JSONGrammar.TokenType.UnescapedChar: |  | 79 | case JSONGrammar.TokenType.UnescapedChar: | |
| 80 | m_scanner.CopyTokenTo(m_builder); |  | 80 | m_scanner.CopyTokenTo(m_builder); | |
| 81 | break; |  | 81 | break; | |
| 82 | case JSONGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence |  | 82 | case JSONGrammar.TokenType.EscapedUnicode: // \xXXXX - unicode escape sequence | |
| 83 | m_scanner.CopyTokenTo(buf, 0); |  | 83 | m_scanner.CopyTokenTo(buf, 0); | |
| 84 | m_builder.Append(StringTranslator.TranslateHexUnicode(buf, 2)); |  | 84 | m_builder.Append(StringTranslator.TranslateHexUnicode(buf, 2)); | |
| 85 | pos++; |  | 85 | pos++; | |
| 86 | break; |  | 86 | break; | |
| 87 | case JSONGrammar.TokenType.EscapedChar: // \t - escape sequence |  | 87 | case JSONGrammar.TokenType.EscapedChar: // \t - escape sequence | |
| 88 | m_scanner.CopyTokenTo(buf, 0); |  | 88 | m_scanner.CopyTokenTo(buf, 0); | |
| 89 | m_builder.Append(StringTranslator.TranslateEscapedChar(buf[1])); |  | 89 | m_builder.Append(StringTranslator.TranslateEscapedChar(buf[1])); | |
| 90 | break; |  | 90 | break; | |
| 91 | } |  | 91 | } | |
| 92 |  | 92 | |||
| 93 | } |  | 93 | } | |
| 94 |  | 94 | |||
| 95 | throw new ParserException("Unexpected end of data"); |  | 95 | throw new ParserException("Unexpected end of data"); | |
| 96 | } |  | 96 | } | |
| 97 |  | 97 | |||
| 98 | protected override void Dispose(bool disposing) { |  | 98 | protected override void Dispose(bool disposing) { | |
| 99 | if (disposing) |  | 99 | if (disposing) | |
| 100 | Safe.Dispose(m_scanner); |  | 100 | Safe.Dispose(m_scanner); | |
| 101 | base.Dispose(disposing); |  | 101 | base.Dispose(disposing); | |
| 102 | } |  | 102 | } | |
| 103 | } |  | 103 | } | |
| 104 | } |  | 104 | } | |
        
        General Comments 0
    
    
  
  
                      You need to be logged in to leave comments.
                      Login now
                    
                