Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 3004 was 2994, checked in by epitzer, 15 years ago

Make StorableClass attribute compulsory for StorableSerializer to work, add named property StorableClassType to choose between Empty and MarkedOnly, later other options will be added. (#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(StorableClassType.Empty)]
13  public 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.