Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Persistence/3.3/Default/CompositeSerializers/CompactNumberArray2StringSerializer.cs @ 3036

Last change on this file since 3036 was 3036, checked in by epitzer, 14 years ago

make most serializers internal and complete API documentation (#548)

File size: 4.2 KB
Line 
1using System;
2using HeuristicLab.Persistence.Interfaces;
3using HeuristicLab.Persistence.Core;
4using System.Collections.Generic;
5using System.Reflection;
6using System.Globalization;
7using System.Text;
8using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
9
10namespace HeuristicLab.Persistence.Default.CompositeSerializers {
11
12  [StorableClass]
13  internal sealed class CompactNumberArray2StringSerializer : ICompositeSerializer {
14
15    public int Priority {
16      get { return 200; }
17    }
18
19    private static readonly Number2StringSerializer numberConverter =
20      new Number2StringSerializer();
21
22    public bool CanSerialize(Type type) {
23      return
24        (type.IsArray || type == typeof(Array)) &&
25        numberConverter.CanSerialize(type.GetElementType());
26    }
27
28    public string JustifyRejection(Type type) {
29      if (!type.IsArray && type != typeof(Array))
30        return "not an array";
31      return string.Format("number converter cannot serialize elements: " +
32        numberConverter.JustifyRejection(type.GetElementType()));
33    }
34
35    public IEnumerable<Tag> CreateMetaInfo(object obj) {
36      Array a = (Array)obj;
37      int[] lengths = new int[a.Rank];
38      int[] lowerBounds = new int[a.Rank];
39      StringBuilder sb = new StringBuilder();
40      sb.Append(a.Rank).Append(';');
41      for (int i = 0; i < a.Rank; i++) {
42        sb.Append(a.GetLength(i)).Append(';');
43        lengths[i] = a.GetLength(i);
44      }
45      for (int i = 0; i < a.Rank; i++) {
46        sb.Append(a.GetLowerBound(i)).Append(';');
47        lowerBounds[i] = a.GetLowerBound(i);
48      }
49      int[] positions = (int[])lowerBounds.Clone();
50      while (positions[a.Rank - 1] < lengths[a.Rank - 1] + lowerBounds[a.Rank - 1]) {
51        sb.Append(numberConverter.Format(a.GetValue(positions))).Append(';');
52        positions[0] += 1;
53        for (int i = 0; i < a.Rank - 1; i++) {
54          if (positions[i] >= lengths[i] + lowerBounds[i]) {
55            positions[i] = lowerBounds[i];
56            positions[i + 1] += 1;
57          } else {
58            break;
59          }
60        }
61      }
62      yield return new Tag("compact array", sb.ToString());
63    }
64
65    public IEnumerable<Tag> Decompose(object obj) {
66      return new Tag[] { };
67    }
68
69    public object CreateInstance(Type type, IEnumerable<Tag> metaInfo) {
70      try {
71        var tagIter = metaInfo.GetEnumerator();
72        tagIter.MoveNext();
73        var valueIter = ((string)tagIter.Current.Value)
74          .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
75          .GetEnumerator();
76        valueIter.MoveNext();
77        int rank = int.Parse((string)valueIter.Current);
78        int[] lengths = new int[rank];
79        int[] lowerBounds = new int[rank];
80        for (int i = 0; i < rank; i++) {
81          valueIter.MoveNext();
82          lengths[i] = int.Parse((string)valueIter.Current);
83        }
84        for (int i = 0; i < rank; i++) {
85          valueIter.MoveNext();
86          lowerBounds[i] = int.Parse((string)valueIter.Current);
87        }
88        Type elementType = type.GetElementType();
89        Array a = Array.CreateInstance(elementType, lengths, lowerBounds);
90        int[] positions = (int[])lowerBounds.Clone();
91        while (valueIter.MoveNext()) {
92          a.SetValue(
93            numberConverter.Parse((string)valueIter.Current, elementType),
94            positions);
95          positions[0] += 1;
96          for (int i = 0; i < rank - 1; i++) {
97            if (positions[i] >= lengths[i] + lowerBounds[i]) {
98              positions[i + 1] += 1;
99              positions[i] = lowerBounds[i];
100            } else {
101              break;
102            }
103          }
104        }
105        return a;
106      } catch (InvalidOperationException e) {
107        throw new PersistenceException("Insufficient data to deserialize compact array", e);
108      } catch (InvalidCastException e) {
109        throw new PersistenceException("Invalid element data during compact array deserialization", e);
110      }
111    }
112
113    public void Populate(object instance, IEnumerable<Tag> tags, Type type) {
114      // Nothing to do: Compact arrays are already populated during instance creation.
115    }
116
117  }
118
119}
Note: See TracBrowser for help on using the repository browser.