Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 4068 was 4068, checked in by swagner, 14 years ago

Sorted usings and removed unused usings in entire solution (#1094)

File size: 5.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2010 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Text;
25using HeuristicLab.Persistence.Auxiliary;
26using HeuristicLab.Persistence.Core;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28using HeuristicLab.Persistence.Interfaces;
29
30namespace HeuristicLab.Persistence.Default.CompositeSerializers {
31
32  [StorableClass]
33  public sealed class CompactNumberArray2StringSerializer : ICompositeSerializer {
34
35    public const int SPLIT_THRESHOLD = 1024 * 1024;
36
37    public int Priority {
38      get { return 200; }
39    }
40
41    private static readonly Number2StringSerializer numberConverter =
42      new Number2StringSerializer();
43
44    public bool CanSerialize(Type type) {
45      return
46        (type.IsArray || type == typeof(Array)) &&
47        numberConverter.CanSerialize(type.GetElementType());
48    }
49
50    public string JustifyRejection(Type type) {
51      if (!type.IsArray && type != typeof(Array))
52        return "not an array";
53      return string.Format("number converter cannot serialize elements: " +
54        numberConverter.JustifyRejection(type.GetElementType()));
55    }
56
57    public IEnumerable<Tag> CreateMetaInfo(object obj) {
58      Array a = (Array)obj;
59      int[] lengths = new int[a.Rank];
60      int[] lowerBounds = new int[a.Rank];
61      StringBuilder sb = new StringBuilder(a.Rank * 6);
62      sb.Append(a.Rank).Append(';');
63      for (int i = 0; i < a.Rank; i++) {
64        sb.Append(a.GetLength(i)).Append(';');
65        lengths[i] = a.GetLength(i);
66      }
67      for (int i = 0; i < a.Rank; i++) {
68        sb.Append(a.GetLowerBound(i)).Append(';');
69        lowerBounds[i] = a.GetLowerBound(i);
70      }
71      yield return new Tag(sb.ToString());
72      int nElements = 1;
73      for (int i = 0; i < a.Rank; i++) {
74        lowerBounds[i] = a.GetLowerBound(i);
75        lengths[i] = a.GetLength(i);
76        nElements *= lengths[i];
77      }
78      sb = new StringBuilder(Math.Min(nElements * 3, SPLIT_THRESHOLD));
79      int[] positions = (int[])lowerBounds.Clone();
80      while (positions[a.Rank - 1] < lengths[a.Rank - 1] + lowerBounds[a.Rank - 1]) {
81        sb.Append(numberConverter.Format(a.GetValue(positions))).Append(';');
82        if (sb.Length > SPLIT_THRESHOLD && sb.Length > sb.Capacity - 18) {
83          yield return new Tag(sb.ToString());
84          sb = new StringBuilder(Math.Min(nElements * 3, SPLIT_THRESHOLD));
85        }
86        positions[0] += 1;
87        for (int i = 0; i < a.Rank - 1; i++) {
88          if (positions[i] >= lengths[i] + lowerBounds[i]) {
89            positions[i] = lowerBounds[i];
90            positions[i + 1] += 1;
91          } else {
92            break;
93          }
94        }
95      }
96      if (sb.Length > 0)
97        yield return new Tag(sb.ToString());
98    }
99
100    private static Tag[] emptyTag = new Tag[0];
101    public IEnumerable<Tag> Decompose(object obj) {
102      return emptyTag;
103    }
104
105    public object CreateInstance(Type type, IEnumerable<Tag> metaInfo) {
106      try {
107        var tagIter = metaInfo.GetEnumerator();
108        tagIter.MoveNext();
109        var valueIter = ((string)tagIter.Current.Value).GetSplitEnumerator(';');
110        valueIter.MoveNext();
111        int rank = int.Parse(valueIter.Current);
112        int[] lengths = new int[rank];
113        int[] lowerBounds = new int[rank];
114        for (int i = 0; i < rank; i++) {
115          valueIter.MoveNext();
116          lengths[i] = int.Parse(valueIter.Current);
117        }
118        for (int i = 0; i < rank; i++) {
119          valueIter.MoveNext();
120          lowerBounds[i] = int.Parse(valueIter.Current);
121        }
122        Type elementType = type.GetElementType();
123        Array a = Array.CreateInstance(elementType, lengths, lowerBounds);
124        if (a == null) throw new PersistenceException("invalid instance data type, expected array");
125        int[] positions = (int[])lowerBounds.Clone();
126        while (tagIter.MoveNext()) {
127          valueIter = ((string)tagIter.Current.Value).GetSplitEnumerator(';');
128          while (valueIter.MoveNext()) {
129            a.SetValue(numberConverter.Parse(valueIter.Current, elementType), positions);
130            positions[0] += 1;
131            for (int i = 0; i < a.Rank - 1; i++) {
132              if (positions[i] >= lengths[i] + lowerBounds[i]) {
133                positions[i + 1] += 1;
134                positions[i] = lowerBounds[i];
135              } else {
136                break;
137              }
138            }
139          }
140        }
141        return a;
142      }
143      catch (InvalidOperationException e) {
144        throw new PersistenceException("Insuffictient data to deserialize compact array", e);
145      }
146      catch (InvalidCastException e) {
147        throw new PersistenceException("Invalid element data during compact array deserialization", e);
148      }
149    }
150
151    public void Populate(object instance, IEnumerable<Tag> tags, Type type) {
152      // Nothing to do. Arrays are populated during instance creation;
153    }
154
155  }
156
157}
Note: See TracBrowser for help on using the repository browser.