Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Linq\JTokenReader.cs

Symbol Coverage: 90.91% (100 of 110)

Branch Coverage: 95.74% (45 of 47)

Cyclomatic Complexity Avg: 3.92 Max:14

Code Lines: 109


L V Source
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using Newtonsoft.Json.Utilities;
6
using System.Globalization;
7

  
8
namespace Newtonsoft.Json.Linq
9
{
10
  /// <summary>
11
  /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
12
  /// </summary>
13
  public class JTokenReader : JsonReader, IJsonLineInfo
14
  {
15
    private readonly JToken _root;
16
    private JToken _parent;
17
    private JToken _current;
18

  
19
    /// <summary>
20
    /// Initializes a new instance of the <see cref="JTokenReader"/> class.
21
    /// </summary>
22
    /// <param name="token">The token to read from.</param>
23
 48
    public JTokenReader(JToken token)
24
    {
25
 48
      ValidationUtils.ArgumentNotNull(token, "token");
26

  
27
 48
      _root = token;
28
 48
      _current = token;
29
 48
    }
30

  
31
    /// <summary>
32
    /// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
33
    /// </summary>
34
    /// <returns>
35
    /// A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.
36
    /// </returns>
37
    public override byte[] ReadAsBytes()
38
    {
39
 4
      Read();
40

  
41
      // attempt to convert possible base 64 string to bytes
42
 4
      if (TokenType == JsonToken.String)
43
      {
44
 2
        string s = (string) Value;
45
 2
        byte[] data = (s.Length == 0) ? new byte[0] : Convert.FromBase64String(s);
46
 2
        SetToken(JsonToken.Bytes, data);
47
      }
48

  
49
 4
      if (TokenType != JsonToken.Bytes)
50
 1
        throw new JsonReaderException("Error reading bytes. Expected bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
51

  
52
 3
      return (byte[])Value;
53
 3
    }
54

  
55
    /// <summary>
56
    /// Reads the next JSON token from the stream.
57
    /// </summary>
58
    /// <returns>
59
    /// true if the next token was read successfully; false if there are no more tokens to read.
60
    /// </returns>
61
    public override bool Read()
62
    {
63
 408
      if (CurrentState != State.Start)
64
      {
65
 360
        JContainer container = _current as JContainer;
66
 360
        if (container != null && _parent != container)
67
 173
          return ReadInto(container);
68
        else
69
 187
          return ReadOver(_current);
70
      }
71

  
72
 48
      SetToken(_current);
73
 48
      return true;
74
 408
    }
75

  
76
    private bool ReadOver(JToken t)
77
    {
78
 311
      if (t == _root)
79
 34
        return ReadToEnd();
80

  
81
 277
      JToken next = t.Next;
82
 277
      if ((next == null || next == t) || t == t.Parent.Last)
83
      {
84
 168
        if (t.Parent == null)
85
 0
          return ReadToEnd();
86

  
87
 168
        return SetEnd(t.Parent);
88
      }
89
      else
90
      {
91
 109
        _current = next;
92
 109
        SetToken(_current);
93
 109
        return true;
94
      }
95
 311
    }
96

  
97
    private bool ReadToEnd()
98
    {
99
      //CurrentState = State.Finished;
100
 34
      return false;
101
 34
    }
102

  
103
    private bool IsEndElement
104
    {
105
 148
      get { return (_current == _parent); }
106
    }
107

  
108
    private JsonToken? GetEndToken(JContainer c)
109
    {
110
 171
      switch (c.Type)
111
      {
112
        case JTokenType.Object:
113
 38
          return JsonToken.EndObject;
114
        case JTokenType.Array:
115
 9
          return JsonToken.EndArray;
116
        case JTokenType.Constructor:
117
 0
          return JsonToken.EndConstructor;
118
        case JTokenType.Property:
119
 124
          return null;
120
        default:
121
 0
          throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", c.Type, "Unexpected JContainer type.");
122
      }
123
 171
    }
124

  
125
    private bool ReadInto(JContainer c)
126
    {
127
 173
      JToken firstChild = c.First;
128
 173
      if (firstChild == null)
129
      {
130
 3
        return SetEnd(c);
131
      }
132
      else
133
      {
134
 170
        SetToken(firstChild);
135
 170
        _current = firstChild;
136
 170
        _parent = c;
137
 170
        return true;
138
      }
139
 173
    }
140

  
141
    private bool SetEnd(JContainer c)
142
    {
143
 171
      JsonToken? endToken = GetEndToken(c);
144
 171
      if (endToken != null)
145
      {
146
 47
        SetToken(endToken.Value);
147
 47
        _current = c;
148
 47
        _parent = c;
149
 47
        return true;
150
      }
151
      else
152
      {
153
 124
        return ReadOver(c);
154
      }
155
 171
    }
156

  
157
    private void SetToken(JToken token)
158
    {
159
 327
      switch (token.Type)
160
      {
161
        case JTokenType.Object:
162
 39
          SetToken(JsonToken.StartObject);
163
 39
          break;
164
        case JTokenType.Array:
165
 9
          SetToken(JsonToken.StartArray);
166
 9
          break;
167
        case JTokenType.Constructor:
168
 0
          SetToken(JsonToken.StartConstructor);
169
 0
          break;
170
        case JTokenType.Property:
171
 125
          SetToken(JsonToken.PropertyName, ((JProperty)token).Name);
172
 125
          break;
173
        case JTokenType.Comment:
174
 0
          SetToken(JsonToken.Comment, ((JValue)token).Value);
175
 0
          break;
176
        case JTokenType.Integer:
177
 25
          SetToken(JsonToken.Integer, ((JValue)token).Value);
178
 25
          break;
179
        case JTokenType.Float:
180
 4
          SetToken(JsonToken.Float, ((JValue)token).Value);
181
 4
          break;
182
        case JTokenType.String:
183
 79
          SetToken(JsonToken.String, ((JValue)token).Value);
184
 79
          break;
185
        case JTokenType.Boolean:
186
 3
          SetToken(JsonToken.Boolean, ((JValue)token).Value);
187
 3
          break;
188
        case JTokenType.Null:
189
 27
          SetToken(JsonToken.Null, ((JValue)token).Value);
190
 27
          break;
191
        case JTokenType.Undefined:
192
 0
          SetToken(JsonToken.Undefined, ((JValue)token).Value);
193
 0
          break;
194
        case JTokenType.Date:
195
 13
          SetToken(JsonToken.Date, ((JValue)token).Value);
196
 13
          break;
197
        case JTokenType.Raw:
198
 2
          SetToken(JsonToken.Raw, ((JValue)token).Value);
199
 2
          break;
200
        case JTokenType.Bytes:
201
 1
          SetToken(JsonToken.Bytes, ((JValue)token).Value);
202
 1
          break;
203
        default:
204
 0
          throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", token.Type, "Unexpected JTokenType.");
205
      }
206
 327
    }
207

  
208
    bool IJsonLineInfo.HasLineInfo()
209
    {
210
 51
      if (CurrentState == State.Start)
211
 1
        return false;
212

  
213
 50
      IJsonLineInfo info = IsEndElement ? null : _current;
214
 50
      return (info != null && info.HasLineInfo());
215
 51
    }
216

  
217
    int IJsonLineInfo.LineNumber
218
    {
219
      get
220
      {
221
 50
        if (CurrentState == State.Start)
222
 1
          return 0;
223

  
224
 49
        IJsonLineInfo info = IsEndElement ? null : _current;
225
 49
        if (info != null)
226
 46
          return info.LineNumber;
227
        
228
 3
        return 0;
229
 50
      }
230
    }
231

  
232
    int IJsonLineInfo.LinePosition
233
    {
234
      get
235
      {
236
 50
        if (CurrentState == State.Start)
237
 1
          return 0;
238

  
239
 49
        IJsonLineInfo info = IsEndElement ? null : _current;
240
 49
        if (info != null)
241
 46
          return info.LinePosition;
242

  
243
 3
        return 0;
244
 50
      }
245
    }
246
  }
247
}