• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2008 Google Inc.  All rights reserved.
4 // https://developers.google.com/protocol-buffers/
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #endregion
32 
33 using System;
34 
35 namespace Google.Protobuf
36 {
37     internal sealed class JsonToken : IEquatable<JsonToken>
38     {
39         // Tokens with no value can be reused.
40         private static readonly JsonToken _true = new JsonToken(TokenType.True);
41         private static readonly JsonToken _false = new JsonToken(TokenType.False);
42         private static readonly JsonToken _null = new JsonToken(TokenType.Null);
43         private static readonly JsonToken startObject = new JsonToken(TokenType.StartObject);
44         private static readonly JsonToken endObject = new JsonToken(TokenType.EndObject);
45         private static readonly JsonToken startArray = new JsonToken(TokenType.StartArray);
46         private static readonly JsonToken endArray = new JsonToken(TokenType.EndArray);
47         private static readonly JsonToken endDocument = new JsonToken(TokenType.EndDocument);
48 
49         internal static JsonToken Null { get { return _null; } }
50         internal static JsonToken False { get { return _false; } }
51         internal static JsonToken True { get { return _true; } }
52         internal static JsonToken StartObject{ get { return startObject; } }
53         internal static JsonToken EndObject { get { return endObject; } }
54         internal static JsonToken StartArray { get { return startArray; } }
55         internal static JsonToken EndArray { get { return endArray; } }
56         internal static JsonToken EndDocument { get { return endDocument; } }
57 
Name(string name)58         internal static JsonToken Name(string name)
59         {
60             return new JsonToken(TokenType.Name, stringValue: name);
61         }
62 
Value(string value)63         internal static JsonToken Value(string value)
64         {
65             return new JsonToken(TokenType.StringValue, stringValue: value);
66         }
67 
Value(double value)68         internal static JsonToken Value(double value)
69         {
70             return new JsonToken(TokenType.Number, numberValue: value);
71         }
72 
73         internal enum TokenType
74         {
75             Null,
76             False,
77             True,
78             StringValue,
79             Number,
80             Name,
81             StartObject,
82             EndObject,
83             StartArray,
84             EndArray,
85             EndDocument
86         }
87 
88         // A value is a string, number, array, object, null, true or false
89         // Arrays and objects have start/end
90         // A document consists of a value
91         // Objects are name/value sequences.
92 
93         private readonly TokenType type;
94         private readonly string stringValue;
95         private readonly double numberValue;
96 
97         internal TokenType Type { get { return type; } }
98         internal string StringValue { get { return stringValue; } }
99         internal double NumberValue { get { return numberValue; } }
100 
JsonToken(TokenType type, string stringValue = null, double numberValue = 0)101         private JsonToken(TokenType type, string stringValue = null, double numberValue = 0)
102         {
103             this.type = type;
104             this.stringValue = stringValue;
105             this.numberValue = numberValue;
106         }
107 
Equals(object obj)108         public override bool Equals(object obj)
109         {
110             return Equals(obj as JsonToken);
111         }
112 
GetHashCode()113         public override int GetHashCode()
114         {
115             unchecked
116             {
117                 int hash = 17;
118                 hash = hash * 31 + (int) type;
119                 hash = hash * 31 + stringValue == null ? 0 : stringValue.GetHashCode();
120                 hash = hash * 31 + numberValue.GetHashCode();
121                 return hash;
122             }
123         }
124 
ToString()125         public override string ToString()
126         {
127             switch (type)
128             {
129                 case TokenType.Null:
130                     return "null";
131                 case TokenType.True:
132                     return "true";
133                 case TokenType.False:
134                     return "false";
135                 case TokenType.Name:
136                     return "name (" + stringValue + ")";
137                 case TokenType.StringValue:
138                     return "value (" + stringValue + ")";
139                 case TokenType.Number:
140                     return "number (" + numberValue + ")";
141                 case TokenType.StartObject:
142                     return "start-object";
143                 case TokenType.EndObject:
144                     return "end-object";
145                 case TokenType.StartArray:
146                     return "start-array";
147                 case TokenType.EndArray:
148                     return "end-array";
149                 case TokenType.EndDocument:
150                     return "end-document";
151                 default:
152                     throw new InvalidOperationException("Token is of unknown type " + type);
153             }
154         }
155 
Equals(JsonToken other)156         public bool Equals(JsonToken other)
157         {
158             if (ReferenceEquals(other, null))
159             {
160                 return false;
161             }
162             // Note use of other.numberValue.Equals rather than ==, so that NaN compares appropriately.
163             return other.type == type && other.stringValue == stringValue && other.numberValue.Equals(numberValue);
164         }
165     }
166 }
167