private bool FetchNodes() { if (done) { return(false); } if (rows == null) { rows = EnumerateRows(textReader).GetEnumerator(); if (Settings.HasHeaders) { var hasMoreRows = rows.MoveNext(); if (!hasMoreRows) { done = true; EmitRowCollectionEnd(); return(true); } var colNames = EnumerateCols(rows.Current).ToArray(); this.colNamesAlgorithm = colNames; } EmitRowCollectionStart(); return(true); } if (cols == null) { var hasMoreRows = rows.MoveNext(); if (!hasMoreRows) { done = true; EmitRowCollectionEnd(); return(true); } cols = EnumerateCols(rows.Current).GetEnumerator(); colNames = this.colNamesAlgorithm.GetEnumerator(); EmitRowStart(); return(true); } var hasMoreCols = cols.MoveNext(); if (!hasMoreCols) { cols = null; EmitRowEnd(); return(true); } var colValue = ValueConventions.CreateValue(cols.Current, Settings); EmitCol(colValue); return(true); }
private IEnumerable <Node> EnumerateNodes() { var tokenEnumerator = EnumerateTokens().GetEnumerator(); var stack = new Stack <NodeType>(); string suggestedName = null; var ready = tokenEnumerator.MoveNext(); while (ready) { var token = tokenEnumerator.Current; switch (token) { case ",": { var type = stack.FirstOrDefault(); if (type == NodeType.Property) { stack.Pop(); yield return(new Node { Type = NodeType.PropertyEnd }); } ready = tokenEnumerator.MoveNext(); break; } case "{": { var depth = stack.Count; var isDocument = (!Settings.IsFragment && depth == 0); if (isDocument) { stack.Push(NodeType.Document); var name = ValueConventions.CreateName("document", Settings, TextCase.CamelCase); yield return(new Node { Type = NodeType.DocumentStart, Value = name }); // // a proxima propriedade deve ser tratada como o nome do objeto ou coleção // exemplo: // { // "tipo": { ... } // } // // nome da propriedade ready = tokenEnumerator.MoveNext(); if (!ready) { throw new SerializationException("Fim inesperado de arquivo."); } var propertyName = tokenEnumerator.Current; // dois pontos ready = tokenEnumerator.MoveNext(); if (!ready) { throw new SerializationException("Fim inesperado de arquivo."); } var delimiter = tokenEnumerator.Current; if (delimiter != ":") { throw new SerializationException("Token não esperado: " + delimiter); } suggestedName = propertyName; } else { stack.Push(NodeType.Object); var name = ValueConventions.CreateName(suggestedName ?? "object", Settings, TextCase.CamelCase); yield return(new Node { Type = NodeType.ObjectStart, Value = name }); suggestedName = null; } ready = tokenEnumerator.MoveNext(); break; } case "[": { stack.Push(NodeType.Collection); var name = ValueConventions.CreateName(suggestedName ?? "collection", Settings, TextCase.CamelCase); yield return(new Node { Type = NodeType.CollectionStart, Value = name }); ready = tokenEnumerator.MoveNext(); suggestedName = null; break; } case "]": case "}": { NodeType type; type = stack.FirstOrDefault(); if (type == NodeType.Property) { stack.Pop(); yield return(new Node { Type = NodeType.PropertyEnd }); } type = stack.Pop(); yield return(new Node { Type = type | NodeType.End }); type = stack.FirstOrDefault(); if (type == NodeType.Property) { stack.Pop(); yield return(new Node { Type = NodeType.PropertyEnd }); } ready = tokenEnumerator.MoveNext(); break; } default: { ready = tokenEnumerator.MoveNext(); if (!ready) { throw new SerializationException("Fim inesperado de arquivo."); } var nextToken = tokenEnumerator.Current; if (nextToken == ":") { stack.Push(NodeType.Property); var name = ValueConventions.CreateName(token, Settings, TextCase.CamelCase); yield return(new Node { Type = NodeType.PropertyStart, Value = name }); ready = tokenEnumerator.MoveNext(); } else { if (token.StartsWith("'")) { token = token.Substring(1, token.Length - 2); } var value = ValueConventions.CreateValue(token, Settings, Toolset.Json.Unescape); yield return(new Node { Type = NodeType.Value, Value = value }); } break; } } } }
private IEnumerable <Node> EmitNodes(XmlReader reader) { // Propriedade sem EndElement é considerada nula: <tag/> // Propriedade com EndElement e sem conteúdo é considerada vazia: <tag></tag> // Tag nula é identificada por IsEmptyElement. // Tag vazia é identificada por esta variável, que estoca o último tipo de nodo encontrdo. // Se este último nodo foi um abre propriedade e estamos fechando esta propriedade então // não vimos valor algum. Node emitted = null; while (reader.Read()) { var nodeType = reader.NodeType; var nodeName = reader.Name; var nodeValue = reader.Value; var isEmptyElement = reader.IsEmptyElement; switch (nodeType) { case XmlNodeType.Element: { var isCollection = IsCollection(); var parentKind = stack.FirstOrDefault(); var parentIsProperty = (parentKind == NodeType.Property); if (parentIsProperty) { var name = "Object"; var conventionName = ValueConventions.CreateName(name, Settings, TextCase.KeepOriginal); stack.Push(NodeType.Object); yield return(emitted = new Node { Type = NodeType.ObjectStart, Value = conventionName }); parentKind = stack.FirstOrDefault(); } var isProperty = (parentKind == NodeType.Object); if (isProperty) { var name = nodeName ?? "Property"; var conventionName = ValueConventions.CreateName(name, Settings, TextCase.KeepOriginal); yield return(emitted = new Node { Type = NodeType.PropertyStart, Value = conventionName }); if (reader.IsEmptyElement) { // tags vazias não tem um EndElement correspondente, como em: <tag/> // por isto vamos emitir um aqui e com um valor padrao. if (isCollection) { yield return(emitted = new Node { Type = NodeType.CollectionStart, Value = "Collection" }); yield return(emitted = new Node { Type = NodeType.CollectionEnd }); // Como estamos fechando a coleção para forçar uma coleção vazia como // valor padrão vamos também abortar a interpretação da coleção na continuidade. // A propriedade foi detectada em uma tag vazia como <Xml IsArray="true"/> e // portanto não há realmente coleção para interpretar isCollection = false; } else { yield return(emitted = new Node { Type = NodeType.Value, Value = null }); } yield return(emitted = new Node { Type = NodeType.PropertyEnd }); } else { stack.Push(NodeType.Property); } } if (isCollection) { var name = nodeName ?? "Collection"; var conventionName = ValueConventions.CreateName(name, Settings, TextCase.KeepOriginal); stack.Push(NodeType.Collection); yield return(emitted = new Node { Type = NodeType.CollectionStart, Value = conventionName }); if (reader.IsEmptyElement) { yield return(emitted = new Node { Type = NodeType.CollectionEnd }); } } else if (!isProperty && !isCollection) { var name = nodeName ?? "Object"; var conventionName = ValueConventions.CreateName(name, Settings, TextCase.KeepOriginal); stack.Push(NodeType.Object); yield return(emitted = new Node { Type = NodeType.ObjectStart, Value = conventionName }); if (reader.IsEmptyElement) { yield return(emitted = new Node { Type = NodeType.ObjectEnd }); } } break; } case XmlNodeType.EndElement: { var kind = stack.Pop(); var parentKind = stack.FirstOrDefault(); if (kind == NodeType.Property) { // se o nodo emitido anteriormente tiver sido abre propriedade então não vimos // um valor e devemos tratar a propriedade como vazia if (emitted.Type == NodeType.PropertyStart) { yield return emitted = new Node { Type = NodeType.Value, Value = string.Empty } } ; } yield return(emitted = new Node { Type = kind | NodeType.End }); if (kind == NodeType.Collection) { var isProperty = (parentKind == NodeType.Property); if (isProperty) { kind = stack.Pop(); yield return(emitted = new Node { Type = kind | NodeType.End }); } } else if (parentKind == NodeType.Property) { kind = stack.Pop(); yield return(emitted = new Node { Type = kind | NodeType.End }); } break; } case XmlNodeType.CDATA: case XmlNodeType.Text: { var value = ValueConventions.CreateValue(nodeValue, Settings); yield return(emitted = new Node { Type = NodeType.Value, Value = value }); break; } } } // while (reader.Read()) }