mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-05 22:48:02 +00:00
auto merge of #7704 : glinscott/rust/json_iter, r=erickt
This is much faster for strings, and eventually when there is a buffered reader of some sort, will be much faster for files. Reading example.json 100 times before was around 1.18s. After: - reading from string 0.68s - reading from file 1.08s (extra time is all in io::Reader) Also: - fixes #7611 - error when parsing strings and we hit EOF - updates definition of whitespace in json should only be the 4 ascii whitespace chars
This commit is contained in:
commit
06accaf22b
@ -16,11 +16,10 @@
|
|||||||
|
|
||||||
//! json serialization
|
//! json serialization
|
||||||
|
|
||||||
|
use std::iterator;
|
||||||
use std::char;
|
|
||||||
use std::float;
|
use std::float;
|
||||||
use std::hashmap::HashMap;
|
use std::hashmap::HashMap;
|
||||||
use std::io::{WriterUtil, ReaderUtil};
|
use std::io::WriterUtil;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::to_str;
|
use std::to_str;
|
||||||
@ -481,24 +480,17 @@ pub fn to_pretty_str(json: &Json) -> ~str {
|
|||||||
io::with_str_writer(|wr| to_pretty_writer(wr, json))
|
io::with_str_writer(|wr| to_pretty_writer(wr, json))
|
||||||
}
|
}
|
||||||
|
|
||||||
static BUF_SIZE : uint = 64000;
|
pub struct Parser<T> {
|
||||||
|
priv rdr: ~T,
|
||||||
#[allow(missing_doc)]
|
|
||||||
pub struct Parser {
|
|
||||||
priv rdr: @io::Reader,
|
|
||||||
priv buf: ~[char],
|
|
||||||
priv buf_idx: uint,
|
|
||||||
priv ch: char,
|
priv ch: char,
|
||||||
priv line: uint,
|
priv line: uint,
|
||||||
priv col: uint,
|
priv col: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decode a json value from an io::reader
|
/// Decode a json value from an Iterator<char>
|
||||||
pub fn Parser(rdr: @io::Reader) -> Parser {
|
pub fn Parser<T : iterator::Iterator<char>>(rdr: ~T) -> Parser<T> {
|
||||||
let mut p = Parser {
|
let mut p = Parser {
|
||||||
rdr: rdr,
|
rdr: rdr,
|
||||||
buf: rdr.read_chars(BUF_SIZE),
|
|
||||||
buf_idx: 0,
|
|
||||||
ch: 0 as char,
|
ch: 0 as char,
|
||||||
line: 1,
|
line: 1,
|
||||||
col: 0,
|
col: 0,
|
||||||
@ -507,7 +499,7 @@ pub fn Parser(rdr: @io::Reader) -> Parser {
|
|||||||
p
|
p
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl<T: iterator::Iterator<char>> Parser<T> {
|
||||||
pub fn parse(&mut self) -> Result<Json, Error> {
|
pub fn parse(&mut self) -> Result<Json, Error> {
|
||||||
match self.parse_value() {
|
match self.parse_value() {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
@ -525,30 +517,20 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser {
|
impl<T : iterator::Iterator<char>> Parser<T> {
|
||||||
fn eof(&self) -> bool { self.ch == -1 as char }
|
fn eof(&self) -> bool { self.ch == -1 as char }
|
||||||
|
|
||||||
fn bump(&mut self) {
|
fn bump(&mut self) {
|
||||||
if self.eof() {
|
match self.rdr.next() {
|
||||||
return;
|
Some(ch) => self.ch = ch,
|
||||||
|
None() => self.ch = -1 as char,
|
||||||
}
|
}
|
||||||
|
|
||||||
self.col += 1u;
|
|
||||||
|
|
||||||
if self.buf_idx >= self.buf.len() {
|
|
||||||
self.buf = self.rdr.read_chars(BUF_SIZE);
|
|
||||||
if self.buf.len() == 0 {
|
|
||||||
self.ch = -1 as char;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.buf_idx = 0;
|
|
||||||
}
|
|
||||||
self.ch = self.buf[self.buf_idx];
|
|
||||||
self.buf_idx += 1;
|
|
||||||
|
|
||||||
if self.ch == '\n' {
|
if self.ch == '\n' {
|
||||||
self.line += 1u;
|
self.line += 1u;
|
||||||
self.col = 1u;
|
self.col = 1u;
|
||||||
|
} else {
|
||||||
|
self.col += 1u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +565,10 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_whitespace(&mut self) {
|
fn parse_whitespace(&mut self) {
|
||||||
while char::is_whitespace(self.ch) { self.bump(); }
|
while self.ch == ' ' ||
|
||||||
|
self.ch == '\n' ||
|
||||||
|
self.ch == '\t' ||
|
||||||
|
self.ch == '\r' { self.bump(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
|
fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
|
||||||
@ -727,8 +712,11 @@ impl Parser {
|
|||||||
let mut escape = false;
|
let mut escape = false;
|
||||||
let mut res = ~"";
|
let mut res = ~"";
|
||||||
|
|
||||||
while !self.eof() {
|
loop {
|
||||||
self.bump();
|
self.bump();
|
||||||
|
if self.eof() {
|
||||||
|
return self.error(~"EOF while parsing string");
|
||||||
|
}
|
||||||
|
|
||||||
if (escape) {
|
if (escape) {
|
||||||
match self.ch {
|
match self.ch {
|
||||||
@ -783,8 +771,6 @@ impl Parser {
|
|||||||
res.push_char(self.ch);
|
res.push_char(self.ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.error(~"EOF while parsing string")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_list(&mut self) -> Result<Json, Error> {
|
fn parse_list(&mut self) -> Result<Json, Error> {
|
||||||
@ -870,15 +856,15 @@ impl Parser {
|
|||||||
|
|
||||||
/// Decodes a json value from an @io::Reader
|
/// Decodes a json value from an @io::Reader
|
||||||
pub fn from_reader(rdr: @io::Reader) -> Result<Json, Error> {
|
pub fn from_reader(rdr: @io::Reader) -> Result<Json, Error> {
|
||||||
let mut parser = Parser(rdr);
|
let s = str::from_bytes(rdr.read_whole_stream());
|
||||||
|
let mut parser = Parser(~s.iter());
|
||||||
parser.parse()
|
parser.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decodes a json value from a string
|
/// Decodes a json value from a string
|
||||||
pub fn from_str(s: &str) -> Result<Json, Error> {
|
pub fn from_str(s: &str) -> Result<Json, Error> {
|
||||||
do io::with_str_reader(s) |rdr| {
|
let mut parser = Parser(~s.iter());
|
||||||
from_reader(rdr)
|
parser.parse()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A structure to decode JSON to values in rust.
|
/// A structure to decode JSON to values in rust.
|
||||||
@ -1744,7 +1730,7 @@ mod tests {
|
|||||||
assert_eq!(v, 0.4e-01f);
|
assert_eq!(v, 0.4e-01f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: #7611: xfailed for now
|
#[test]
|
||||||
fn test_read_str() {
|
fn test_read_str() {
|
||||||
assert_eq!(from_str("\""),
|
assert_eq!(from_str("\""),
|
||||||
Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string"
|
Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string"
|
||||||
|
Loading…
Reference in New Issue
Block a user