Json.NET
Code Coverage Statistics for Source File

Newtonsoft.Json\Converters\RegexConverter.cs

Symbol Coverage: 100.00% (62 of 62)

Branch Coverage: 100.00% (26 of 26)

Cyclomatic Complexity Avg: 2.33 Max:7

Code Lines: 60


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

  
8
namespace Newtonsoft.Json.Converters
9
{
10
  /// <summary>
11
  /// Converts a <see cref="Regex"/> to and from JSON and BSON.
12
  /// </summary>
13
  public class RegexConverter : JsonConverter
14
  {
15
    /// <summary>
16
    /// Writes the JSON representation of the object.
17
    /// </summary>
18
    /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
19
    /// <param name="value">The value.</param>
20
    /// <param name="serializer">The calling serializer.</param>
21
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
22
    {
23
 5
      Regex regex = (Regex) value;
24

  
25
 5
      BsonWriter bsonWriter = writer as BsonWriter;
26
 5
      if (bsonWriter != null)
27
 3
        WriteBson(bsonWriter, regex);
28
      else
29
 2
        WriteJson(writer, regex);
30
 5
    }
31

  
32
    private bool HasFlag(RegexOptions options, RegexOptions flag)
33
    {
34
 12
      return ((options & flag) == flag);
35
 12
    }
36

  
37
    private void WriteBson(BsonWriter writer, Regex regex)
38
    {
39
      // Regular expression - The first cstring is the regex pattern, the second
40
      // is the regex options string. Options are identified by characters, which 
41
      // must be stored in alphabetical order. Valid options are 'i' for case 
42
      // insensitive matching, 'm' for multiline matching, 'x' for verbose mode, 
43
      // 'l' to make \w, \W, etc. locale dependent, 's' for dotall mode 
44
      // ('.' matches everything), and 'u' to make \w, \W, etc. match unicode.
45

  
46
 3
      string options = null;
47

  
48
 3
      if (HasFlag(regex.Options, RegexOptions.IgnoreCase))
49
 2
        options += "i";
50

  
51
 3
      if (HasFlag(regex.Options, RegexOptions.Multiline))
52
 1
        options += "m";
53

  
54
 3
      if (HasFlag(regex.Options, RegexOptions.Singleline))
55
 1
        options += "s";
56

  
57
 3
      options += "u";
58

  
59
 3
      if (HasFlag(regex.Options, RegexOptions.ExplicitCapture))
60
 1
        options += "x";
61

  
62
 3
      writer.WriteRegex(regex.ToString(), options);
63
 3
    }
64

  
65
    private void WriteJson(JsonWriter writer, Regex regex)
66
    {
67
 2
      writer.WriteStartObject();
68
 2
      writer.WritePropertyName("Pattern");
69
 2
      writer.WriteValue(regex.ToString());
70
 2
      writer.WritePropertyName("Options");
71
 2
      writer.WriteValue(regex.Options);
72
 2
      writer.WriteEndObject();
73
 2
    }
74

  
75
    /// <summary>
76
    /// Reads the JSON representation of the object.
77
    /// </summary>
78
    /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
79
    /// <param name="objectType">Type of the object.</param>
80
    /// <param name="existingValue">The existing value of object being read.</param>
81
    /// <param name="serializer">The calling serializer.</param>
82
    /// <returns>The object value.</returns>
83
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
84
    {
85
 5
      BsonReader bsonReader = reader as BsonReader;
86

  
87
 5
      if (bsonReader != null)
88
 3
        return ReadBson(bsonReader);
89
      else
90
 2
        return ReadJson(reader);
91
 5
    }
92

  
93
    private object ReadBson(BsonReader reader)
94
    {
95
 3
      string regexText = (string)reader.Value;
96
 3
      int patternOptionDelimiterIndex = regexText.LastIndexOf(@"/");
97

  
98
 3
      string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1);
99
 3
      string optionsText = regexText.Substring(patternOptionDelimiterIndex + 1);
100

  
101
 3
      RegexOptions options = RegexOptions.None;
102
 3
      foreach (char c in optionsText)
103
      {
104
 8
        switch (c)
105
        {
106
          case 'i':
107
 2
            options |= RegexOptions.IgnoreCase;
108
 2
            break;
109
          case 'm':
110
 1
            options |= RegexOptions.Multiline;
111
 1
            break;
112
          case 's':
113
 1
            options |= RegexOptions.Singleline;
114
 1
            break;
115
          case 'x':
116
 1
            options |= RegexOptions.ExplicitCapture;
117
 1
            break;
118
        }
119
      }
120

  
121
 3
      return new Regex(patternText, options);
122
 3
    }
123

  
124
    private Regex ReadJson(JsonReader reader)
125
    {
126
 2
      reader.Read();
127
 2
      reader.Read();
128
 2
      string pattern = (string) reader.Value;
129

  
130
 2
      reader.Read();
131
 2
      reader.Read();
132
 2
      int options = Convert.ToInt32(reader.Value);
133

  
134
 2
      reader.Read();
135

  
136
 2
      return new Regex(pattern, (RegexOptions)options);
137
 2
    }
138

  
139
    /// <summary>
140
    /// Determines whether this instance can convert the specified object type.
141
    /// </summary>
142
    /// <param name="objectType">Type of the object.</param>
143
    /// <returns>
144
    /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
145
    /// </returns>
146
    public override bool CanConvert(Type objectType)
147
    {
148
 20
      return (objectType == typeof (Regex));
149
 20
    }
150
  }
151
}