Changeset 1795
- Timestamp:
- 05/14/09 13:00:36 (16 years ago)
- Location:
- trunk/sources
- Files:
-
- 5 edited
- 1 copied
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Persistence/3.3/Auxiliary/TypeName.cs
r1794 r1795 6 6 7 7 namespace HeuristicLab.Persistence.Auxiliary { 8 9 public class ParseError : Exception { 10 public ParseError(string message) : base(message) { } 11 } 12 13 public class TypeNameParser { 14 15 /* 16 TypeSpec := SimpleTypeSpec '&'? 17 18 SimpleTypeSpec := (IDENTIFIER '.')* 19 (IDENTIFIER '+')* 20 IDENTIFIER 21 ( '`\d+[' Generics ']' )? 22 (\*|\[(\d+\.\.\d+|\d+\.\.\.|(|\*)(,(|\*))*)\])* 23 (',\s*' IDENTIFIER (',\s*' AssemblyProperty)* )? 24 25 Generics := '[' SimpleTypeSpec ']' (',[' SimpleTypeSpec ']') 26 27 AssemblyProperty := 'Version=' Version 28 | 'PublicKey(Token)?=[a-fA-F0-9]+' 29 | 'Culture=[a-zA-F0-9]+' 30 31 Version := '\d+\.\d+\.\d+\.\d+)' 32 33 IDENTIFIER = [a-zA-Z][a-ZA-Z0-9]* 34 */ 35 36 37 class Token { 38 private static Dictionary<string, string> tokens = 39 new Dictionary<string, string> { 40 {"&", "AMPERSAND"}, 41 {".", "DOT"}, 42 {"-", "DASH"}, 43 {"+", "PLUS"}, 44 {",", "COMMA"}, 45 {"[", "OPEN_BRACKET"}, 46 {"]", "CLOSE_BRACKET"}, 47 {"*", "ASTERISK"}, 48 {" ", "SPACE"}, 49 {"=", "EQUALS"}, 50 {"`", "BACKTICK"} }; 51 private static Regex NumberRegex = new Regex("^\\d+$"); 52 private static Regex TokenRegex = new Regex("[-&.+,\\[\\]* =`]|\\d+|[a-zA-Z][a-zA-Z0-9]*"); 53 public string Name { get; private set; } 54 public string Value { get; private set; } 55 public int? Number { get; private set; } 56 public int Position { get; private set; } 57 private Token(string value, int pos) { 58 Position = pos; 59 if (tokens.ContainsKey(value)) { 60 Name = tokens[value]; 61 } else if (NumberRegex.IsMatch(value)) { 62 Number = int.Parse(value); 63 } else { 64 Value = value; 65 } 66 } 67 public static IEnumerable<Token> Tokenize(string s) { 68 int pos = 0; 69 foreach (Match m in TokenRegex.Matches(s)) { 70 yield return new Token(m.Value, pos); 71 pos += m.Length; 72 } 73 } 74 public override string ToString() { 75 if (Name != null) 76 return "Token(" + Name + ")"; 77 if (Value != null) 78 return "\"" + Value + "\""; 79 if (Number != null) 80 return Number.ToString(); 81 return "<empty>"; 82 } 83 } 84 85 private Queue<Token> tokens; 86 private int Position { 87 get { 88 if (tokens.Count == 0) 89 return -1; 90 else 91 return tokens.Peek().Position; 92 } 93 } 94 95 private TypeNameParser(string s) { 96 tokens = new Queue<Token>(Token.Tokenize(s)); 97 } 98 99 public static TypeName Parse(string s) { 100 TypeNameParser p = new TypeNameParser(s); 101 try { 102 return p.TransformTypeSpec(); 103 } catch (ParseError x) { 104 if (p.Position > 0) 105 throw new ParseError(String.Format( 106 "Could not parse typename: {0}\n\"{1}====>{2}<===={3}", 107 x.Message, 108 s.Substring(0, p.Position), 109 s[p.Position], 110 s.Substring(p.Position, s.Length - p.Position))); 111 else 112 throw new ParseError(String.Format( 113 "Could not parse typenname \"{0}\" at end of input: {1}", 114 s, 115 x.Message)); 116 } 117 } 118 119 private TypeName TransformTypeSpec() { 120 TypeName t = TransformSimpleTypeSpec(); 121 t.IsReference = ConsumeToken("AMPERSAND"); 122 return t; 123 } 124 125 private TypeName TransformSimpleTypeSpec() { 126 List<string> nameSpace = new List<string>(); 127 nameSpace.Add(ConsumeIdentifier()); 128 while (ConsumeToken("DOT")) 129 nameSpace.Add(ConsumeIdentifier()); 130 List<string> className = new List<string>(); 131 if (nameSpace.Count > 0) { 132 className.Add(nameSpace[nameSpace.Count - 1]); 133 nameSpace.RemoveAt(nameSpace.Count - 1); 134 } 135 while (ConsumeToken("PLUS")) 136 className.Add(ConsumeIdentifier()); 137 TypeName typeName = new TypeName( 138 string.Join(".", nameSpace.ToArray()), 139 string.Join("+", className.ToArray())); 140 if (ConsumeToken("BACKTICK")) { 141 int nGenericArgs = ConsumeNumber(); 142 if (ConsumeToken("OPEN_BRACKET") && 143 CanConsumeToken("OPEN_BRACKET")) { 144 typeName.GenericArgs.AddRange(TransformGenerics()); 145 ConsumeToken("CLOSE_BRACKET", true); 146 } 147 } 148 StringBuilder pointerOrArray = new StringBuilder(); 149 while (true) { 150 if (ConsumeToken("ASTERSIK")) { 151 pointerOrArray.Append("*"); 152 } else if (ConsumeToken("OPEN_BRACKET")) { 153 pointerOrArray.Append('['); 154 ParseDimension(pointerOrArray); 155 while (ConsumeToken("COMMA")) { 156 pointerOrArray.Append(","); 157 ParseDimension(pointerOrArray); 158 } 159 ConsumeToken("CLOSE_BRACKET", true); 160 pointerOrArray.Append(']'); 161 } else { 162 break; 163 } 164 } 165 typeName.MemoryMagic = pointerOrArray.ToString(); 166 if (ConsumeComma()) { 167 StringBuilder sb = new StringBuilder(); 168 sb.Append(ConsumeIdentifier()); 169 while (CanConsumeToken("DOT") || 170 CanConsumeToken("DASH") || 171 CanConsumeNumber() || 172 CanConsumeIdentifier()) { 173 if (ConsumeToken("DOT")) 174 sb.Append('.'); 175 else if (ConsumeToken("DASH")) 176 sb.Append('-'); 177 else if (CanConsumeNumber()) 178 sb.Append(ConsumeNumber()); 179 else 180 sb.Append(ConsumeIdentifier()); 181 } 182 typeName.AssemblyName = sb.ToString(); 183 while (ConsumeComma()) { 184 KeyValuePair<string, string> property = 185 TransformAssemblyProperty(); 186 typeName.AssemblyAttribues.Add(property.Key, property.Value); 187 } 188 } 189 return typeName; 190 } 191 192 private void ParseDimension(StringBuilder sb) { 193 if (ConsumeToken("ASTERSIK")) { 194 sb.Append("*"); 195 } else if (CanConsumeNumber()) { 196 sb.Append(ConsumeNumber()); 197 ConsumeToken("DOT", true); 198 ConsumeToken("DOT", true); 199 if (ConsumeToken("DOT")) { 200 sb.Append("..."); 201 } else { 202 sb.Append("..").Append(ConsumeNumber()); 203 } 204 } 205 } 206 207 private IEnumerable<TypeName> TransformGenerics() { 208 ConsumeToken("OPEN_BRACKET", true); 209 yield return TransformSimpleTypeSpec(); 210 ConsumeToken("CLOSE_BRACKET", true); 211 while (ConsumeToken("COMMA")) { 212 ConsumeToken("OPEN_BRACKET", true); 213 yield return TransformSimpleTypeSpec(); 214 ConsumeToken("CLOSE_BRACKET", true); 215 } 216 } 217 218 private KeyValuePair<string, string> TransformAssemblyProperty() { 219 if (ConsumeIdentifier("Version")) { 220 ConsumeToken("EQUALS", true); 221 return new KeyValuePair<string, string>( 222 "Version", 223 TransformVersion()); 224 } else if (ConsumeIdentifier("PublicKey")) { 225 ConsumeToken("EQUALS", true); 226 return new KeyValuePair<string, string>( 227 "PublicKey", 228 ConsumeIdentifier()); 229 } else if (ConsumeIdentifier("PublicKeyToken")) { 230 ConsumeToken("EQUALS", true); 231 return new KeyValuePair<string, string>( 232 "PublicKeyToken", 233 ConsumeIdentifier()); 234 } else if (ConsumeIdentifier("Culture")) { 235 ConsumeToken("EQUALS", true); 236 return new KeyValuePair<string, string>( 237 "Culture", 238 ConsumeIdentifier()); 239 } else if (ConsumeIdentifier("Custom")) { 240 ConsumeToken("EQUALS", true); 241 return new KeyValuePair<string, string>( 242 "Custom", 243 ConsumeIdentifier()); 244 } else { 245 throw new ParseError(String.Format( 246 "Invalid assembly property \"{0}\"", 247 tokens.Peek().ToString())); 248 } 249 } 250 private string TransformVersion() { 251 StringBuilder version = new StringBuilder(); 252 version.Append(ConsumeNumber()); 253 ConsumeToken("DOT"); 254 version.Append('.').Append(ConsumeNumber()); 255 ConsumeToken("DOT"); 256 version.Append('.').Append(ConsumeNumber()); 257 ConsumeToken("DOT"); 258 version.Append('.').Append(ConsumeNumber()); 259 return version.ToString(); 260 } 261 262 private bool CanConsumeNumber() { 263 if (tokens.Count == 0) 264 return false; 265 return tokens.Peek().Number != null; 266 } 267 268 private int ConsumeNumber() { 269 if (tokens.Count == 0) 270 throw new ParseError("End of input while expecting number"); 271 if (tokens.Peek().Number != null) 272 return (int)tokens.Dequeue().Number; 273 throw new ParseError(string.Format( 274 "Number expected, found \"{0}\" instead", 275 tokens.Peek().ToString())); 276 } 277 278 private bool ConsumeIdentifier(string value) { 279 if (tokens.Count == 0) 280 return false; 281 if (tokens.Peek().Value == value) { 282 tokens.Dequeue(); 283 return true; 284 } else { 285 return false; 286 } 287 } 288 289 private bool CanConsumeIdentifier() { 290 return tokens.Count > 0 && tokens.Peek().Value != null; 291 } 292 293 private string ConsumeIdentifier() { 294 if (tokens.Count == 0) 295 throw new ParseError("End of input while expecting identifier"); 296 if (tokens.Peek().Value != null) 297 return tokens.Dequeue().Value; 298 throw new ParseError(String.Format( 299 "Identifier expected, found \"{0}\" instead", 300 tokens.Peek().ToString())); 301 } 302 303 private bool ConsumeComma() { 304 if (ConsumeToken("COMMA")) { 305 while (ConsumeToken("SPACE")) ; 306 return true; 307 } else { 308 return false; 309 } 310 } 311 312 private bool ConsumeToken(string name) { 313 return ConsumeToken(name, false); 314 } 315 316 private bool CanConsumeToken(string name) { 317 if (tokens.Count == 0) 318 return false; 319 if (tokens.Peek().Name == name) 320 return true; 321 return false; 322 } 323 324 private bool ConsumeToken(string name, bool force) { 325 if (tokens.Count == 0) 326 if (force) 327 throw new ParseError(String.Format( 328 "end of input while expecting token \"{0}\"", 329 name)); 330 else 331 return false; 332 if (tokens.Peek().Name == name) { 333 tokens.Dequeue(); 334 return true; 335 } else if (force) { 336 throw new ParseError(String.Format( 337 "expected \"{0}\" found \"{1}\"", 338 name, 339 tokens.Peek().ToString())); 340 } else { 341 return false; 342 } 343 } 344 345 346 } 347 8 348 9 public class TypeName { 349 10 public string Namespace { get; private set; } … … 397 58 } 398 59 399 public bool Is OlderThan(TypeName t) {60 public bool IsNewerThan(TypeName t) { 400 61 try { 401 62 if (this.ClassName != t.ClassName || … … 405 66 if (CompareVersions( 406 67 this.AssemblyAttribues["Version"], 407 t.AssemblyAttribues["Version"]) <0)68 t.AssemblyAttribues["Version"]) > 0) 408 69 return true; 409 70 IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator(); … … 411 72 while (thisIt.MoveNext()) { 412 73 tIt.MoveNext(); 413 if (thisIt.Current.Is OlderThan(tIt.Current))74 if (thisIt.Current.IsNewerThan(tIt.Current)) 414 75 return true; 415 76 } … … 420 81 } 421 82 83 public bool IsCompatible(TypeName t) { 84 try { 85 if (this.ClassName != t.ClassName || 86 this.Namespace != t.Namespace || 87 this.AssemblyName != t.AssemblyName) 88 throw new Exception("Cannot compare versions of different types"); 89 Version thisVersion = new Version(this.AssemblyAttribues["Version"]); 90 Version tVersion = new Version(t.AssemblyAttribues["Version"]); 91 if (thisVersion.Major != tVersion.Major || 92 thisVersion.Minor != tVersion.Minor) 93 return false; 94 IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator(); 95 IEnumerator<TypeName> tIt = t.GenericArgs.GetEnumerator(); 96 while (thisIt.MoveNext()) { 97 tIt.MoveNext(); 98 if (!thisIt.Current.IsCompatible(tIt.Current)) 99 return false; 100 } 101 return true; 102 } catch (KeyNotFoundException) { 103 throw new Exception("Could not extract version infomration from type string"); 104 } 105 } 106 422 107 private static int CompareVersions(string v1string, string v2string) { 423 108 return new Version(v1string).CompareTo(new Version(v2string)); -
trunk/sources/HeuristicLab.Persistence/3.3/Auxiliary/TypeNameParser.cs
r1794 r1795 223 223 TransformVersion()); 224 224 } else if (ConsumeIdentifier("PublicKey")) { 225 ConsumeToken("EQUALS", true); 226 return new KeyValuePair<string, string>( 227 "PublicKey", 228 ConsumeIdentifier()); 225 return ConsumeAssignment("PublicKey"); 229 226 } else if (ConsumeIdentifier("PublicKeyToken")) { 230 ConsumeToken("EQUALS", true); 231 return new KeyValuePair<string, string>( 232 "PublicKeyToken", 233 ConsumeIdentifier()); 227 return ConsumeAssignment("PublicKeyToken"); 234 228 } else if (ConsumeIdentifier("Culture")) { 235 ConsumeToken("EQUALS", true); 236 return new KeyValuePair<string, string>( 237 "Culture", 238 ConsumeIdentifier()); 229 return ConsumeAssignment("Culture"); 239 230 } else if (ConsumeIdentifier("Custom")) { 240 ConsumeToken("EQUALS", true); 241 return new KeyValuePair<string, string>( 242 "Custom", 243 ConsumeIdentifier()); 231 return ConsumeAssignment("Custom"); 244 232 } else { 245 233 throw new ParseError(String.Format( … … 248 236 } 249 237 } 238 239 private KeyValuePair<string, string> ConsumeAssignment(string name) { 240 ConsumeToken("EQUALS", true); 241 return new KeyValuePair<string, string>(name, ConsumeIdentifier()); 242 } 243 250 244 private string TransformVersion() { 251 245 StringBuilder version = new StringBuilder(); … … 342 336 } 343 337 } 344 345 346 }347 348 public class TypeName {349 public string Namespace { get; private set; }350 public string ClassName { get; private set; }351 public List<TypeName> GenericArgs { get; internal set; }352 public bool IsGeneric { get { return GenericArgs.Count > 0; } }353 public string MemoryMagic { get; internal set; }354 public string AssemblyName { get; internal set; }355 public Dictionary<string, string> AssemblyAttribues { get; internal set; }356 public bool IsReference { get; internal set; }357 358 internal TypeName(string nameSpace, string className) {359 Namespace = nameSpace;360 ClassName = className;361 GenericArgs = new List<TypeName>();362 MemoryMagic = "";363 AssemblyAttribues = new Dictionary<string, string>();364 }365 366 public string ToString(bool full) {367 return ToString(full, true);368 }369 370 public string ToString(bool full, bool includeAssembly) {371 StringBuilder sb = new StringBuilder();372 sb.Append(Namespace).Append('.').Append(ClassName);373 if (IsGeneric) {374 sb.Append('`').Append(GenericArgs.Count).Append('[');375 bool first = true;376 foreach (TypeName t in GenericArgs) {377 if (first)378 first = false;379 else380 sb.Append(',');381 sb.Append('[').Append(t.ToString(full)).Append(']');382 }383 sb.Append(']');384 }385 sb.Append(MemoryMagic);386 if (includeAssembly && AssemblyName != null) {387 sb.Append(", ").Append(AssemblyName);388 if (full)389 foreach (var property in AssemblyAttribues)390 sb.Append(", ").Append(property.Key).Append('=').Append(property.Value);391 }392 return sb.ToString();393 }394 395 public override string ToString() {396 return ToString(true);397 }398 399 public bool IsOlderThan(TypeName t) {400 try {401 if (this.ClassName != t.ClassName ||402 this.Namespace != t.Namespace ||403 this.AssemblyName != t.AssemblyName)404 throw new Exception("Cannot compare versions of different types");405 if (CompareVersions(406 this.AssemblyAttribues["Version"],407 t.AssemblyAttribues["Version"]) < 0)408 return true;409 IEnumerator<TypeName> thisIt = this.GenericArgs.GetEnumerator();410 IEnumerator<TypeName> tIt = t.GenericArgs.GetEnumerator();411 while (thisIt.MoveNext()) {412 tIt.MoveNext();413 if (thisIt.Current.IsOlderThan(tIt.Current))414 return true;415 }416 return false;417 } catch (KeyNotFoundException) {418 throw new Exception("Could not extract version information from type string");419 }420 }421 422 private static int CompareVersions(string v1string, string v2string) {423 return new Version(v1string).CompareTo(new Version(v2string));424 }425 338 } 426 339 } -
trunk/sources/HeuristicLab.Persistence/3.3/Core/DeSerializer.cs
r1780 r1795 17 17 } catch (Exception) { 18 18 Logger.Warn(String.Format( 19 "Cannot load type \"{0}\", falling back to loading withpartial name", typeNameString));19 "Cannot load type \"{0}\", falling back to partial name", typeNameString)); 20 20 try { 21 21 TypeName typeName = TypeNameParser.Parse(typeNameString); … … 28 28 } 29 29 try { 30 if ( 31 TypeNameParser.Parse(type.AssemblyQualifiedName).IsOlderThan( 32 TypeNameParser.Parse(typeNameString))) 30 TypeName requestedTypeName = TypeNameParser.Parse(typeNameString); 31 TypeName loadedTypeName = TypeNameParser.Parse(type.AssemblyQualifiedName); 32 if (!requestedTypeName.IsCompatible(loadedTypeName)) 33 throw new PersistenceException(String.Format( 34 "Serialized type is incompatible with available type: serialized: {0}, loaded: {1}", 35 typeNameString, 36 type.AssemblyQualifiedName)); 37 if (requestedTypeName.IsNewerThan(loadedTypeName)) 33 38 throw new PersistenceException(String.Format( 34 39 "Serialized type is newer than available type: serialized: {0}, loaded: {1}", -
trunk/sources/HeuristicLab.Persistence/3.3/Core/Serializer.cs
r1780 r1795 45 45 serializer = d.GetType().AssemblyQualifiedName; 46 46 } 47 //result.Add(new TypeMapping(pair.Value, pair.Key.AssemblyQualifiedName, serializer)); 48 result.Add(new TypeMapping(pair.Value, pair.Key.VersionInvariantName(), serializer)); 47 result.Add(new TypeMapping(pair.Value, pair.Key.AssemblyQualifiedName, serializer)); 49 48 } 50 49 return result; -
trunk/sources/HeuristicLab.Persistence/3.3/HeuristicLab.Persistence-3.3.csproj
r1712 r1795 93 93 </ItemGroup> 94 94 <ItemGroup> 95 <Compile Include="Auxiliary\TypeNameParser.cs" /> 95 96 <Compile Include="Auxiliary\ReflectionTools.cs" /> 96 97 <Compile Include="Core\Configuration.cs" /> … … 104 105 <Compile Include="Auxiliary\TypeExtensions.cs" /> 105 106 <Compile Include="Core\TypeMapping.cs" /> 106 <Compile Include="Auxiliary\Type StringBuilder.cs" />107 <Compile Include="Auxiliary\TypeName.cs" /> 107 108 <Compile Include="Core\GeneratorBase.cs" /> 108 109 <Compile Include="Default\DebugString\DebugString.cs" /> -
trunk/sources/HeuristicLab.Persistence/UnitTests/UseCases.cs
r1780 r1795 550 550 IntWrapper newI = (IntWrapper)d.Deserialize(p); 551 551 Assert.AreEqual(i.Value, newI.Value); 552 552 553 string newTypeString = Regex.Replace(typeString.ToString(), 553 "Version= (\\d+\\.\\d+\\.\\d+\\.\\d+)",554 "Version= 9999.9999.9999.9999");554 "Version=\\d+\\.\\d+\\.\\d+\\.\\d+", 555 "Version=0.0.9999.9999"); 555 556 try { 556 557 d = new Deserializer(XmlParser.ParseTypeCache(new StringReader(newTypeString))); 557 558 Assert.Fail("Exception expected"); 558 } catch (PersistenceException) { 559 // EXPECTED 559 } catch (PersistenceException x) { 560 Assert.IsTrue(x.Message.Contains("incompatible")); 561 } 562 newTypeString = Regex.Replace(typeString.ToString(), 563 "Version=(\\d+\\.\\d+)\\.\\d+\\.\\d+", 564 "Version=$1.9999.9999"); 565 try { 566 d = new Deserializer(XmlParser.ParseTypeCache(new StringReader(newTypeString))); 567 Assert.Fail("Exception expected"); 568 } catch (PersistenceException x) { 569 Assert.IsTrue(x.Message.Contains("newer")); 560 570 } 561 571 } -
trunk/sources/HeuristicLab.sln
r1778 r1795 200 200 EndProject 201 201 Global 202 GlobalSection(TestCaseManagementSettings) = postSolution 203 CategoryFile = HeuristicLab.vsmdi 204 EndGlobalSection 202 205 GlobalSection(SolutionConfigurationPlatforms) = preSolution 203 206 CEDMA Debug|Any CPU = CEDMA Debug|Any CPU
Note: See TracChangeset
for help on using the changeset viewer.