private bool ParseDollar(Stream stream, object context, ref string output) { if (stream.Current == '$') { var identifier = stream.PeekWord(1); object value; if (TryGetIdentifier(identifier, context, out value)) { stream.Advance(identifier.Length); var collection = value as IEnumerable <Item>; if (collection != null) { var filter = ParseBlock(stream, '(', ')'); var block = ParseBlock(stream, '[', ']'); var separator = ParseBlock(stream, '[', ']'); if (filter == null && block == null && separator == null) { var stringValue = value.ToString(); if (stringValue != value.GetType().FullName) { output += stringValue; } else { output += "$" + identifier; } } else { IEnumerable <Item> items; if (filter != null && filter.StartsWith("$")) { var predicate = filter.Remove(0, 1); if (extensions != null) { // Lambda filters are always defined in the first extension type var c = extensions.FirstOrDefault()?.GetMethod(predicate); if (c != null) { items = collection.Where(x => (bool)c.Invoke(null, new object[] { x })).ToList(); matchFound = matchFound || items.Any(); } else { items = new Item[0]; } } else { items = new Item[0]; } } else { items = ItemFilter.Apply(collection, filter, ref matchFound); } output += string.Join(ParseTemplate(separator, context), items.Select(item => ParseTemplate(block, item))); } } else if (value is bool) { var trueBlock = ParseBlock(stream, '[', ']'); var falseBlock = ParseBlock(stream, '[', ']'); output += ParseTemplate((bool)value ? trueBlock : falseBlock, context); } else { var block = ParseBlock(stream, '[', ']'); if (value != null) { if (block != null) { output += ParseTemplate(block, value); } else { output += value.ToString(); } } } return(true); } } return(false); }
public static SerializableDocument ReadBuffer(this SerializableDocument doc, Stream stream, string name, long numBytes) { Debug.WriteLine($"Reading buffer {name} of size {Util.BytesToString(numBytes)}"); switch (name) { case BufferNames.Header: var bytes = stream.ReadArray <byte>((int)numBytes); doc.Header = SerializableHeader.Parse(Encoding.UTF8.GetString(bytes)); return(doc); case BufferNames.Assets: if (doc.Options?.SkipAssets == true) { Debug.WriteLine("Skipping assets"); stream.Advance(numBytes); return(doc); } doc.Assets = stream.ReadBFast().ToArray(); return(doc); case BufferNames.Strings: var stringBytes = stream.ReadArray <byte>((int)numBytes); var joinedStringTable = Encoding.UTF8.GetString(stringBytes); doc.StringTable = joinedStringTable.Split('\0'); return(doc); case BufferNames.Geometry: if (doc.Options?.SkipGeometry == true) { Debug.WriteLine("Skipping geometry"); stream.Advance(numBytes); return(doc); } doc.Geometry = G3D.Read(stream); return(doc); case BufferNames.Nodes: if (doc.Options?.SkipGeometry == true) { Debug.WriteLine("Skipping nodes"); stream.Advance(numBytes); return(doc); } var cnt = (int)(numBytes / SerializableSceneNode.Size); Debug.Assert(numBytes % SerializableSceneNode.Size == 0, $"Number of bytes is not divisible by {SerializableSceneNode.Size}"); if (cnt < 0) { throw new Exception($"More than {int.MaxValue} items in array"); } doc.Nodes = stream.ReadArray <SerializableSceneNode>(cnt); return(doc); case BufferNames.Entities: doc.EntityTables = ReadEntityTables(stream); return(doc); } // NOTE: unrecognized buffers are not an error. Debug.WriteLine($"Unrecognized buffer {name}"); stream.ReadArray <byte>((int)numBytes); return(doc); }
private bool ParseDollar(/* ProjectItem projectItem, */ string sourcePath, Stream stream, object context, ref string output) { if (stream.Current == '$') { var identifier = stream.PeekWord(1); object value; if (TryGetIdentifier(/*projectItem,*/ sourcePath, identifier, context, out value)) { stream.Advance(identifier.Length); var collection = value as IEnumerable <Item>; if (collection != null) { var filter = ParseBlock(stream, '(', ')'); var block = ParseBlock(stream, '[', ']'); var separator = ParseBlock(stream, '[', ']'); if (filter == null && block == null && separator == null) { var stringValue = value.ToString(); if (stringValue != value.GetType().FullName) { output += stringValue; } else { output += "$" + identifier; } } else { IList <Item> items; if (filter != null && filter.StartsWith("$")) { var predicate = filter.Remove(0, 1); if (_extensions != null) { // Lambda filters are always defined in the first extension type var c = _extensions.FirstOrDefault()?.GetMethod(predicate); if (c != null) { try { items = collection.Where(x => (bool)c.Invoke(null, new object[] { x })).ToList(); _matchFound = _matchFound || items.Any(); } catch (Exception e) { items = new Item[0]; _hasError = true; var message = $"Error rendering template. Cannot apply filter to identifier '{identifier}'."; LogException(e, message, /* projectItem,*/ sourcePath); } } else { items = new Item[0]; } } else { items = new Item[0]; } } else { items = ItemFilter.Apply(collection, filter, ref _matchFound).ToList(); } output += string.Join(ParseTemplate(/*projectItem,*/ sourcePath, separator, context), items.Select(item => ParseTemplate(/*projectItem, */ sourcePath, block, item))); } } else if (value is bool) { var trueBlock = ParseBlock(stream, '[', ']'); var falseBlock = ParseBlock(stream, '[', ']'); output += ParseTemplate(/*projectItem,*/ sourcePath, (bool)value ? trueBlock : falseBlock, context); } else { var block = ParseBlock(stream, '[', ']'); if (value != null) { if (block != null) { output += ParseTemplate(/*projectItem,*/ sourcePath, block, value); } else { output += value.ToString(); } } } return(true); } } return(false); }