From dd8cc059c5511101be803253cfc15a5513eb7660 Mon Sep 17 00:00:00 2001 From: lurchi Date: Sat, 3 Sep 2016 22:38:47 +0200 Subject: [PATCH] partial parsing possible with PsycParser and PsycListParser --- rust/src/parser.rs | 411 +++++++++++++++++++++++---------- rust/src/parser_types.rs | 5 +- rust/tests/test_dict_parser.rs | 90 ++++++++ rust/tests/test_list_parser.rs | 90 ++++++++ rust/tests/test_parser.rs | 37 +++ src/parse.c | 256 ++++++++++---------- 6 files changed, 640 insertions(+), 249 deletions(-) create mode 100644 rust/tests/test_dict_parser.rs create mode 100644 rust/tests/test_list_parser.rs diff --git a/rust/src/parser.rs b/rust/src/parser.rs index 54644c6..0257564 100644 --- a/rust/src/parser.rs +++ b/rust/src/parser.rs @@ -64,17 +64,16 @@ pub struct PsycParser { state: PsycParseState } -//pub struct PsycListParser<'a> { -// state: PsycParseListState, -// parsed_list: Vec>, -// buffer: &'a [u8] -//} -// -//pub struct PsycDictParser<'a> { -// state: PsycParseDictState, -// parsed_key: Option<&'a [u8]>, -// cursor: usize -//} +pub struct PsycListParser { + state: PsycParseListState +} + +pub struct PsycDictParser<'a> { + state: PsycParseDictState, + parsed_key: Option<&'a [u8]>, + buffer: Option<&'a [u8]>, + cursor: usize +} // //// TODO: What data structures does the index parser need? //pub struct PsycIndexParser { @@ -129,24 +128,24 @@ pub enum PsycParserResult<'a> { } } -//#[derive(Debug, PartialEq)] -//pub enum PsycListParserResult { -// Complete, -// InsufficientData, -// ListElement { -// value: &[u8] -// }, -// ListElementStart { -// value_part: &[u8] -// }, -// ListElementCont { -// value_part: &[u8] -// }, -// ListElementEnd { -// value_part: &[u8] -// } -//} -// +#[derive(Debug, PartialEq)] +pub enum PsycListParserResult<'a> { + Complete, + InsufficientData, + ListElement { + value: &'a [u8] + }, + ListElementStart { + value_part: &'a [u8] + }, + ListElementCont { + value_part: &'a [u8] + }, + ListElementEnd { + value_part: &'a [u8] + } +} + #[derive(Debug, PartialEq)] pub enum PsycDictParserResult<'a> { Complete, @@ -205,9 +204,10 @@ pub enum PsycDictParserError { InvalidKeyStart = PsycParseDictRC::PSYC_PARSE_DICT_ERROR_KEY_START as _, InvalidKeyType = PsycParseDictRC::PSYC_PARSE_DICT_ERROR_TYPE as _, GenericError = PsycParseDictRC::PSYC_PARSE_DICT_ERROR as _, + NoBuffer } -impl PsycParser { +impl<'a> PsycParser { /// Create a PsycParser pub fn new() -> Self { let mut state: PsycParseState; @@ -217,14 +217,13 @@ impl PsycParser { psyc_parse_state_init(state_ptr, PsycParseFlag::PSYC_PARSE_ALL as u8) } PsycParser { - state: state, + state: state } } /// Parse the buffer previously set by set_buffer. Call repeatedly until the /// result is PsycParserResult::Complete or a PsycParserError. - pub fn parse<'a>(&mut self) - -> Result, PsycParserError> { + pub fn parse(&mut self) -> Result, PsycParserError> { let state_ptr = &mut self.state as *mut PsycParseState; let mut operator = '\0'; let mut name: PsycString; @@ -325,8 +324,8 @@ impl PsycParser { } } -impl Parser for PsycParser { - fn set_buffer(&mut self, buffer: &[u8]) { +impl<'a> Parser<'a> for PsycParser { + fn set_buffer(&mut self, buffer: &'a [u8]) { let state_ptr = &mut self.state as *mut PsycParseState; let buffer_ptr = buffer.as_ptr() as *const c_char; unsafe { @@ -347,100 +346,266 @@ impl Parser for PsycParser { } } -//impl<'a> PsycDictParser<'a> { -// /// Create a PsycDictParser -// pub fn new() -> Self { -// let mut state: PsycParseDictState; -// unsafe { -// state = mem::uninitialized(); -// let state_ptr = &mut state as *mut PsycParseDictState; -// psyc_parse_dict_state_init(state_ptr) -// } -// PsycDictParser { -// state: state, -// parsed_key: None, -// parsed_dict: vec![], -// buffer: None, -// cursor: 0 -// } -// } -// -// /// Set a buffer of raw bytes for parsing -// pub fn set_buffer(&mut self, buffer: &'a [u8]) { -// self.buffer = Some(buffer); -// let state_ptr = &mut self.state as *mut PsycParseDictState; -// let buffer_ptr = &buffer[self.cursor] as *const u8 as *const c_char; -// unsafe { -// psyc_parse_dict_buffer_set(state_ptr, buffer_ptr, buffer.len()) -// } -// } -// -// /// Parse the buffer previously set by set_buffer. Call repeatedly until the -// /// result is PsycDictParserResult::Complete or a PsycDictParserError -// pub fn parse(&mut self) -// -> Result, PsycDictParserError> { -// let state_ptr = &mut self.state as *mut PsycParseDictState; -// let mut list_type: PsycString; -// let mut element: PsycString; -// unsafe { -// list_type = mem::uninitialized(); -// element = mem::uninitialized(); -// let list_type_ptr = &mut list_type as *mut PsycString; -// let element_ptr = &mut element as *mut PsycString; -// loop { -// let parse_result = psyc_parse_dict(state_ptr, list_type_ptr, element_ptr); -// self.cursor = self.cursor + self.state.cursor; -// println!("parse_result: {:?}", parse_result); -// match parse_result { -// PsycParseDictRC::PSYC_PARSE_DICT_KEY_END | -// PsycParseDictRC::PSYC_PARSE_DICT_KEY => { -// let key = util::cstring_to_slice(element.data, element.length); -// self.parsed_key = Some(key) -// }, -// -// PsycParseDictRC::PSYC_PARSE_DICT_VALUE_END | -// PsycParseDictRC::PSYC_PARSE_DICT_VALUE => { -// let value = util::cstring_to_slice(element.data, element.length); -// self.parsed_dict.push((self.parsed_key.unwrap(), value)) -// }, -// -// PsycParseDictRC::PSYC_PARSE_DICT_VALUE_LAST => { -// let value = util::cstring_to_slice(element.data, element.length); -// self.parsed_dict.push((self.parsed_key.unwrap(), value)); -// let complete = PsycDictParserResult::Complete { -// dict: self.parsed_dict.clone() -// }; -// return Ok(complete); -// }, -// -// PsycParseDictRC::PSYC_PARSE_DICT_INSUFFICIENT | -// PsycParseDictRC::PSYC_PARSE_DICT_KEY_START | -// PsycParseDictRC::PSYC_PARSE_DICT_KEY_CONT | -// PsycParseDictRC::PSYC_PARSE_DICT_VALUE_START | -// PsycParseDictRC::PSYC_PARSE_DICT_VALUE_CONT | -// PsycParseDictRC::PSYC_PARSE_DICT_END /* FIXME: correct? */=> { -// return Ok(PsycDictParserResult::InsufficientData); -// }, -// -// PsycParseDictRC::PSYC_PARSE_DICT_TYPE => (), -// -// _error => { -// return Err(mem::transmute(_error)); -// }, -// } -// } -// } -// } -//} +impl PsycListParser { + pub fn new() -> Self { + let mut state: PsycParseListState; + unsafe { + state = mem::uninitialized(); + let state_ptr = &mut state as *mut PsycParseListState; + psyc_parse_list_state_init(state_ptr) + } + PsycListParser { + state: state + } + } -pub trait Parser { + pub fn parse<'a>(&mut self) -> Result, PsycListParserError> { + let state_ptr = &mut self.state as *mut PsycParseListState; + let mut list_type: PsycString; + let mut element: PsycString; + unsafe { + list_type = mem::uninitialized(); + element = mem::uninitialized(); + let list_type_ptr = &mut list_type as *mut PsycString; + let element_ptr = &mut element as *mut PsycString; + loop { + let parse_result = psyc_parse_list(state_ptr, list_type_ptr, element_ptr); + println!("parse_result: {:?}", parse_result); + println!("cursor: {}", self.state.cursor); + match parse_result { + PsycParseListRC::PSYC_PARSE_LIST_END => + return Ok(PsycListParserResult::Complete), + + PsycParseListRC::PSYC_PARSE_LIST_INSUFFICIENT => + return Ok(PsycListParserResult::InsufficientData), + + PsycParseListRC::PSYC_PARSE_LIST_ELEM_LAST | + PsycParseListRC::PSYC_PARSE_LIST_ELEM => { + let result = PsycListParserResult::ListElement { + value: util::cstring_to_slice(element.data, element.length) + }; + return Ok(result) + }, + + PsycParseListRC::PSYC_PARSE_LIST_ELEM_START => { + let result = PsycListParserResult::ListElementStart { + value_part: util::cstring_to_slice(element.data, element.length) + }; + return Ok(result) + }, + + PsycParseListRC::PSYC_PARSE_LIST_ELEM_CONT => { + let result = PsycListParserResult::ListElementCont { + value_part: util::cstring_to_slice(element.data, element.length) + }; + return Ok(result) + }, + + PsycParseListRC::PSYC_PARSE_LIST_ELEM_END => { + let result = PsycListParserResult::ListElementEnd { + value_part: util::cstring_to_slice(element.data, element.length) + }; + return Ok(result) + }, + + //PsycParseListRC::PSYC_PARSE_LIST_ELEM_LAST => { + // let result: PsycListParserResult; + // if ! self.finished { + // result = PsycListParserResult::ListElement { + // value: util::cstring_to_slice(element.data, element.length) + // }; + // self.finished = true + // } else { + // result = PsycListParserResult::Complete + // } + // return Ok(result) + //}, + + PsycParseListRC::PSYC_PARSE_LIST_TYPE => (), + + _error => { + return Err(mem::transmute(_error)) + }, + } + } + } + } +} + +impl<'a> Parser<'a> for PsycListParser { + fn set_buffer(&mut self, buffer: &'a [u8]) { + let state_ptr = &mut self.state as *mut PsycParseListState; + let buffer_ptr = buffer.as_ptr() as *const c_char; + unsafe { + psyc_parse_list_buffer_set(state_ptr, buffer_ptr, buffer.len()) + } + } + + fn unparsed_position(&self) -> usize { + self.state.cursor + } + + fn unparsed_length(&self) -> usize { + self.state.buffer.length - self.state.cursor + } +} + +impl<'a> PsycDictParser<'a> { + /// Create a PsycDictParser + pub fn new() -> Self { + let mut state: PsycParseDictState; + unsafe { + state = mem::uninitialized(); + let state_ptr = &mut state as *mut PsycParseDictState; + psyc_parse_dict_state_init(state_ptr) + } + PsycDictParser { + state: state, + parsed_key: None, + buffer: None, + cursor: 0 + } + } + + /// Parse the buffer previously set by set_buffer. Call repeatedly until the + /// result is PsycDictParserResult::Complete or a PsycDictParserError + pub fn parse(&mut self) + -> Result, PsycDictParserError> { + if self.buffer == None { + return Err(PsycDictParserError::NoBuffer) + } + if self.buffer.unwrap().is_empty() { + return Ok(PsycDictParserResult::Complete); + } + let state_ptr = &mut self.state as *mut PsycParseDictState; + let mut list_type: PsycString; + let mut element: PsycString; + unsafe { + list_type = mem::uninitialized(); + element = mem::uninitialized(); + let list_type_ptr = &mut list_type as *mut PsycString; + let element_ptr = &mut element as *mut PsycString; + loop { + let parse_result = psyc_parse_dict(state_ptr, list_type_ptr, element_ptr); + println!("parse_result: {:?}", parse_result); + println!("cursor: {}", self.state.cursor); + self.cursor = self.state.cursor; + match parse_result { + PsycParseDictRC::PSYC_PARSE_DICT_END => + return Ok(PsycDictParserResult::Complete), + + PsycParseDictRC::PSYC_PARSE_DICT_INSUFFICIENT => + return Ok(PsycDictParserResult::InsufficientData), + + PsycParseDictRC::PSYC_PARSE_DICT_KEY => { + let key = util::cstring_to_slice(element.data, element.length); + self.parsed_key = Some(key) + }, + + PsycParseDictRC::PSYC_PARSE_DICT_KEY_START => { + self.cursor = element.data as usize - + self.buffer.unwrap().as_ptr() as usize; + return Ok(PsycDictParserResult::InsufficientData) + }, + + PsycParseDictRC::PSYC_PARSE_DICT_KEY_CONT => { + return Ok(PsycDictParserResult::InsufficientData) + }, + + PsycParseDictRC::PSYC_PARSE_DICT_KEY_END => { + let end_index = self.cursor + element.length; + let key = &self.buffer.unwrap()[self.cursor .. end_index]; + self.parsed_key = Some(key) + }, + + //PsycParseDictRC::PSYC_PARSE_DICT_VALUE => { + // let result = PsycDictParserResult::DictEntry { + // key: self.parsed_key.unwrap(), + // value: util::cstring_to_slice(element.data, element.length) + // }; + // return Ok(result) + //}, + + PsycParseDictRC::PSYC_PARSE_DICT_VALUE | + PsycParseDictRC::PSYC_PARSE_DICT_VALUE_LAST => { + //let result: PsycDictParserResult; + //// FIXME: workaround + //if ! self.finished { + // result = PsycDictParserResult::DictEntry { + // key: self.parsed_key.unwrap(), + // value: util::cstring_to_slice(element.data, element.length) + // }; + // self.finished = true + //} else { + // result = PsycDictParserResult::Complete; + //} + let result = PsycDictParserResult::DictEntry { + key: self.parsed_key.unwrap(), + value: util::cstring_to_slice(element.data, element.length) + }; + return Ok(result) + }, + + PsycParseDictRC::PSYC_PARSE_DICT_VALUE_START => { + let result = PsycDictParserResult::DictEntryStart { + key: self.parsed_key.unwrap(), + value_part: util::cstring_to_slice(element.data, element.length) + }; + return Ok(result) + }, + + PsycParseDictRC::PSYC_PARSE_DICT_VALUE_CONT => { + let result = PsycDictParserResult::DictEntryCont { + value_part: util::cstring_to_slice(element.data, element.length) + }; + return Ok(result) + }, + + PsycParseDictRC::PSYC_PARSE_DICT_VALUE_END => { + let result = PsycDictParserResult::DictEntryEnd { + value_part: util::cstring_to_slice(element.data, element.length) + }; + return Ok(result) + }, + + PsycParseDictRC::PSYC_PARSE_DICT_TYPE => (), + + _error => { + return Err(mem::transmute(_error)) + }, + } + } + } + } +} + +impl<'a> Parser<'a> for PsycDictParser<'a> { + fn set_buffer(&mut self, buffer: &'a [u8]) { + self.buffer = Some(buffer); + let state_ptr = &mut self.state as *mut PsycParseDictState; + let buffer_ptr = buffer.as_ptr() as *const c_char; + unsafe { + psyc_parse_dict_buffer_set(state_ptr, buffer_ptr, buffer.len()); + } + } + + fn unparsed_position(&self) -> usize { + self.cursor + } + + fn unparsed_length(&self) -> usize { + self.state.buffer.length - self.cursor + } +} + +pub trait Parser<'a> { /// Set a buffer of raw bytes for parsing - fn set_buffer(&mut self, buffer: &[u8]); + fn set_buffer(&mut self, buffer: &'a [u8]); /// copies the remaining unparsed bytes to the beginning of the given buffer. /// Returns the number of copied bytes. Must be called when parse() returned /// InsufficientData as Result. - fn copy_unparsed_into_buffer(&self, buffer: &mut [u8]) -> usize { + fn copy_unparsed_into_buffer(&self, buffer: &'a mut [u8]) -> usize { let unparsed_pos = self.unparsed_position(); let unparsed_len = self.unparsed_length(); if unparsed_pos != 0 { diff --git a/rust/src/parser_types.rs b/rust/src/parser_types.rs index 7b75a64..751f2d1 100644 --- a/rust/src/parser_types.rs +++ b/rust/src/parser_types.rs @@ -25,7 +25,7 @@ pub struct PsycParseState { #[repr(C)] pub struct PsycParseListState { - buffer: PsycString, + pub buffer: PsycString, pub cursor: usize, startc: usize, list_type: PsycString, @@ -37,7 +37,7 @@ pub struct PsycParseListState { #[repr(C)] pub struct PsycParseDictState { - buffer: PsycString, + pub buffer: PsycString, pub cursor: usize, startc: usize, elemlen: usize, @@ -151,6 +151,7 @@ pub enum PsycParseRC { PSYC_PARSE_COMPLETE = 13, } +#[derive(Debug)] #[repr(C)] pub enum PsycParseListRC { /// Error, no length is set for an element which is longer than PSYC_ELEM_SIZE_THRESHOLD. diff --git a/rust/tests/test_dict_parser.rs b/rust/tests/test_dict_parser.rs new file mode 100644 index 0000000..2d27b77 --- /dev/null +++ b/rust/tests/test_dict_parser.rs @@ -0,0 +1,90 @@ +extern crate psyc; +use psyc::parser::*; + +#[test] +fn test_parse() { + let test_data = "{foo1} bar1{foo2} bar2".to_string().into_bytes(); + + let expected1 = PsycDictParserResult::DictEntry{ + key: b"foo1", + value: b"bar1" + }; + + let expected2 = PsycDictParserResult::DictEntry{ + key: b"foo2", + value: b"bar2" + }; + + let expected3 = PsycDictParserResult::Complete; + + let mut parser = PsycDictParser::new(); + + parser.set_buffer(&test_data); + + assert_eq!(parser.parse().unwrap(), expected1); + assert_eq!(parser.parse().unwrap(), expected2); + assert_eq!(parser.parse().unwrap(), expected3); +} + +#[test] +fn test_empty() { + let test_data = "".to_string().into_bytes(); + + let mut parser = PsycDictParser::new(); + + parser.set_buffer(&test_data); + + assert_eq!(parser.parse().unwrap(), PsycDictParserResult::Complete); +} + +#[test] +fn test_incomplete() { + let test_data1 = "{foo1}4 bar".to_string().into_bytes(); + let test_data2 = "1{foo2} bar2".to_string().into_bytes(); + + let expected = vec![PsycDictParserResult::DictEntryStart { + key: b"foo1", + value_part: b"bar" + }, + PsycDictParserResult::DictEntryEnd { + value_part: b"1" + }, + PsycDictParserResult::DictEntry { + key: b"foo2", + value: b"bar2" + }]; + + let mut parser = PsycDictParser::new(); + + parser.set_buffer(&test_data1); + assert_eq!(parser.parse().unwrap(), expected[0]); + + parser.set_buffer(&test_data2); + assert_eq!(parser.parse().unwrap(), expected[1]); + + assert_eq!(parser.parse().unwrap(), expected[2]); +} + +//#[test] +//fn test_insufficient() { +// let mut test_data1 = "{4 foo".to_string().into_bytes(); +// let mut test_data2 = "1} bar1".to_string().into_bytes(); +// let mut test_data3 = "{4 foo1} bar1".to_string().into_bytes(); +// +// let expected = vec![PsycDictParserResult::InsufficientData, +// PsycDictParserResult::DictEntry { +// key: b"foo1", +// value: b"bar1" +// }]; +// +// let mut parser = PsycDictParser::new(); +// +// parser.set_buffer(&test_data1); +// assert_eq!(parser.parse().unwrap(), expected[0]); +// +// //let unparsed_length = parser.copy_unparsed_into_buffer(&mut test_data1); +// //test_data1.resize(unparsed_length, 0); +// //test_data1.append(&mut test_data2); +// parser.set_buffer(&test_data3); +// assert_eq!(parser.parse().unwrap(), expected[1]); +//} diff --git a/rust/tests/test_list_parser.rs b/rust/tests/test_list_parser.rs new file mode 100644 index 0000000..953e86b --- /dev/null +++ b/rust/tests/test_list_parser.rs @@ -0,0 +1,90 @@ +extern crate psyc; +use psyc::parser::*; + +#[test] +fn test_parse() { + let test_data = "| element1| element2| element3".to_string().into_bytes(); + + let expected1 = PsycListParserResult::ListElement { + value: b"element1" + }; + + let expected2 = PsycListParserResult::ListElement { + value: b"element2" + }; + + let expected3 = PsycListParserResult::ListElement { + value: b"element3" + }; + + let expected4 = PsycListParserResult::Complete; + + let mut parser = PsycListParser::new(); + + parser.set_buffer(&test_data); + + assert_eq!(parser.parse().unwrap(), expected1); + assert_eq!(parser.parse().unwrap(), expected2); + assert_eq!(parser.parse().unwrap(), expected3); + assert_eq!(parser.parse().unwrap(), expected4); +} + +#[test] +fn test_empty() { + let test_data = "".to_string().into_bytes(); + + let mut parser = PsycListParser::new(); + + parser.set_buffer(&test_data); + + assert_eq!(parser.parse().unwrap(), PsycListParserResult::Complete); +} + +#[test] +fn test_incomplete() { + let test_data1 = "|8 element".to_string().into_bytes(); + let test_data2 = "1| element2|".to_string().into_bytes(); + + let expected = vec![PsycListParserResult::ListElementStart { + value_part: b"element" + }, + PsycListParserResult::ListElementEnd { + value_part: b"1" + }, + PsycListParserResult::ListElement { + value: b"element2" + }]; + + let mut parser = PsycListParser::new(); + + parser.set_buffer(&test_data1); + assert_eq!(parser.parse().unwrap(), expected[0]); + + parser.set_buffer(&test_data2); + assert_eq!(parser.parse().unwrap(), expected[1]); + + assert_eq!(parser.parse().unwrap(), expected[2]); +} + +#[test] +fn test_insufficient() { + let mut test_data1 = "|4".to_string().into_bytes(); + let mut test_data2 = " foo1".to_string().into_bytes(); + + let expected = vec![PsycListParserResult::InsufficientData, + PsycListParserResult::ListElement { + value: b"foo1" + }]; + + let mut parser = PsycListParser::new(); + + parser.set_buffer(&test_data1); + + assert_eq!(parser.parse().unwrap(), expected[0]); + + let unparsed_length = parser.copy_unparsed_into_buffer(&mut test_data1); + test_data1.resize(unparsed_length, 0); + test_data1.append(&mut test_data2); + parser.set_buffer(&test_data1); + assert_eq!(parser.parse().unwrap(), expected[1]); +} diff --git a/rust/tests/test_parser.rs b/rust/tests/test_parser.rs index 2e2cb8f..5f73031 100644 --- a/rust/tests/test_parser.rs +++ b/rust/tests/test_parser.rs @@ -21,6 +21,43 @@ fn test_parse() { assert_eq!(parser.parse().unwrap(), expected[1]); } +#[test] +fn test_empty() { + let test_data = "".to_string().into_bytes(); + + let mut parser = PsycParser::new(); + + parser.set_buffer(&test_data); + + // FIXME: InsufficientData or Complete? + assert_eq!(parser.parse().unwrap(), PsycParserResult::InsufficientData); +} + +#[test] +fn test_incomplete() { + let test_data1 = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_nick 6\t".to_string().into_bytes(); + + let test_data2 = "lurchi".to_string().into_bytes(); + + let expected = vec![PsycParserResult::EntityModifierStart { + operator: ':', + name: b"_nick", + value_part: b"" + }, + PsycParserResult::EntityModifierEnd { + value_part: b"lurchi" + }]; + + let mut parser = PsycParser::new(); + + parser.set_buffer(&test_data1); + let _ = parser.parse(); + assert_eq!(parser.parse().unwrap(), expected[0]); + + parser.set_buffer(&test_data2); + assert_eq!(parser.parse().unwrap(), expected[1]); +} + #[test] fn test_insufficient() { let mut test_data1 = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_nick".to_string().into_bytes(); diff --git a/src/parse.c b/src/parse.c index 0f89051..bd2a40a 100644 --- a/src/parse.c +++ b/src/parse.c @@ -573,145 +573,150 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem) { ParseRC ret; - if (state->cursor >= state->buffer.length) - return PSYC_PARSE_LIST_END; + if (state->cursor >= state->buffer.length) { + return PSYC_PARSE_LIST_END; + } state->startc = state->cursor; switch (state->part) { - case PSYC_LIST_PART_START: - type->length = elem->length = 0; - type->data = elem->data = NULL; + case PSYC_LIST_PART_START: + type->length = elem->length = 0; + type->data = elem->data = NULL; - state->part = PSYC_LIST_PART_TYPE; - // fall thru + state->part = PSYC_LIST_PART_TYPE; + // fall thru - case PSYC_LIST_PART_TYPE: - switch (parse_keyword((ParseState*)state, type)) { - case PARSE_SUCCESS: // end of keyword - state->part = PSYC_LIST_PART_ELEM_START; - return PSYC_PARSE_LIST_TYPE; - case PARSE_INSUFFICIENT: // end of buffer - return PSYC_PARSE_LIST_END; - case PARSE_ERROR: // no keyword - state->part = PSYC_LIST_PART_ELEM_START; - break; - default: // should not be reached - return PSYC_PARSE_LIST_ERROR; - } - // fall thru + case PSYC_LIST_PART_TYPE: + switch (parse_keyword((ParseState*)state, type)) { + case PARSE_SUCCESS: // end of keyword + state->part = PSYC_LIST_PART_ELEM_START; + return PSYC_PARSE_LIST_TYPE; + case PARSE_INSUFFICIENT: // end of buffer + return PSYC_PARSE_LIST_END; + case PARSE_ERROR: // no keyword + state->part = PSYC_LIST_PART_ELEM_START; + break; + default: // should not be reached + return PSYC_PARSE_LIST_ERROR; + } + // fall thru - case PSYC_LIST_PART_ELEM_START: - if (state->buffer.data[state->cursor] != '|') - return PSYC_PARSE_LIST_ERROR_ELEM_START; + case PSYC_LIST_PART_ELEM_START: + if (state->buffer.data[state->cursor] != '|') + return PSYC_PARSE_LIST_ERROR_ELEM_START; - type->length = elem->length = 0; - type->data = elem->data = NULL; + type->length = elem->length = 0; + type->data = elem->data = NULL; - state->elem_parsed = 0; - state->elemlen_found = 0; + state->elem_parsed = 0; + state->elemlen_found = 0; - state->part = PSYC_LIST_PART_ELEM_LENGTH; - ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST); - // fall thru + state->part = PSYC_LIST_PART_ELEM_LENGTH; + ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST); + // fall thru - case PSYC_LIST_PART_ELEM_TYPE: - if (state->buffer.data[state->cursor] == '=') { - ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); + case PSYC_LIST_PART_ELEM_TYPE: + if (state->buffer.data[state->cursor] == '=') { + ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); - switch (parse_keyword((ParseState*)state, type)) { - case PARSE_SUCCESS: - switch (state->buffer.data[state->cursor]) { - case ':': - state->part = PSYC_LIST_PART_ELEM_LENGTH; - ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST); - break; - case ' ': - state->part = PSYC_LIST_PART_ELEM; - ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST); - goto PSYC_LIST_PART_ELEM; - case '|': - state->part = PSYC_LIST_PART_ELEM_START; - return PSYC_PARSE_LIST_ELEM; - break; - default: - return PSYC_PARSE_LIST_ERROR_ELEM_TYPE; - } - break; - case PARSE_INSUFFICIENT: // end of buffer - return PSYC_PARSE_LIST_ELEM_LAST; - case PARSE_ERROR: - return PSYC_PARSE_LIST_ERROR_ELEM_TYPE; - default: // should not be reached - return PSYC_PARSE_LIST_ERROR; - } - } - // fall thru + switch (parse_keyword((ParseState*)state, type)) { + case PARSE_SUCCESS: + switch (state->buffer.data[state->cursor]) { + case ':': + state->part = PSYC_LIST_PART_ELEM_LENGTH; + ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST); + break; + case ' ': + state->part = PSYC_LIST_PART_ELEM; + ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST); + goto PSYC_LIST_PART_ELEM; + case '|': + state->part = PSYC_LIST_PART_ELEM_START; + return PSYC_PARSE_LIST_ELEM; + break; + default: + return PSYC_PARSE_LIST_ERROR_ELEM_TYPE; + } + break; + case PARSE_INSUFFICIENT: // end of buffer + state->cursor = state->buffer.length; + return PSYC_PARSE_LIST_ELEM_LAST; + case PARSE_ERROR: + return PSYC_PARSE_LIST_ERROR_ELEM_TYPE; + default: // should not be reached + return PSYC_PARSE_LIST_ERROR; + } + } + // fall thru - case PSYC_LIST_PART_ELEM_LENGTH: - switch (parse_length((ParseState*)state, &state->elemlen)) { - case PARSE_SUCCESS: // length is complete - state->elemlen_found = 1; - state->elem_parsed = 0; - elem->length = state->elemlen; - elem->data = NULL; - break; - case PARSE_INSUFFICIENT: // length is incomplete - return PSYC_PARSE_LIST_INSUFFICIENT; - case PARSE_ERROR: // no length - break; - default: // should not be reached - return PSYC_PARSE_LIST_ERROR; - } + case PSYC_LIST_PART_ELEM_LENGTH: + switch (parse_length((ParseState*)state, &state->elemlen)) { + case PARSE_SUCCESS: // length is complete + state->elemlen_found = 1; + state->elem_parsed = 0; + elem->length = state->elemlen; + elem->data = NULL; + break; + case PARSE_INSUFFICIENT: // length is incomplete + return PSYC_PARSE_LIST_INSUFFICIENT; + case PARSE_ERROR: // no length + break; + default: // should not be reached + return PSYC_PARSE_LIST_ERROR; + } - switch (state->buffer.data[state->cursor]) { - case ' ': - state->part = PSYC_LIST_PART_ELEM; - ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST); - break; - case '|': - state->part = PSYC_LIST_PART_ELEM_START; - return PSYC_PARSE_LIST_ELEM; - default: - return PSYC_PARSE_LIST_ERROR_ELEM_LENGTH; - } - // fall thru + switch (state->buffer.data[state->cursor]) { + case ' ': + state->part = PSYC_LIST_PART_ELEM; + ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_LIST_ELEM_LAST); + break; + case '|': + state->part = PSYC_LIST_PART_ELEM_START; + return PSYC_PARSE_LIST_ELEM; + default: + return PSYC_PARSE_LIST_ERROR_ELEM_LENGTH; + } + // fall thru - case PSYC_LIST_PART_ELEM: - PSYC_LIST_PART_ELEM: - if (state->elemlen_found) { - switch (parse_binary((ParseState*)state, state->elemlen, elem, - &state->elem_parsed)) { - case PARSE_SUCCESS: - if (elem->length == state->elem_parsed) - ret = PSYC_PARSE_LIST_ELEM; - else - ret = PSYC_PARSE_LIST_ELEM_END; - break; - case PARSE_INCOMPLETE: - if (elem->length == state->elem_parsed) - ret = PSYC_PARSE_LIST_ELEM_START; - else - ret = PSYC_PARSE_LIST_ELEM_CONT; - break; - default: // should not be reached - return PSYC_PARSE_LIST_ERROR; - } - } else { - switch (parse_until((ParseState*)state, '|', elem)) { - case PARSE_SUCCESS: - ret = PSYC_PARSE_LIST_ELEM; - break; - case PARSE_INSUFFICIENT: - return PSYC_PARSE_LIST_ELEM_LAST; - default: // should not be reached - return PSYC_PARSE_LIST_ERROR; - } - } + case PSYC_LIST_PART_ELEM: + PSYC_LIST_PART_ELEM: + if (state->elemlen_found) { + switch (parse_binary((ParseState*)state, state->elemlen, elem, + &state->elem_parsed)) { + case PARSE_SUCCESS: + state->part = PSYC_LIST_PART_ELEM_START; + if (elem->length == state->elem_parsed) + ret = PSYC_PARSE_LIST_ELEM; + else + ret = PSYC_PARSE_LIST_ELEM_END; + break; + case PARSE_INCOMPLETE: + state->part = PSYC_LIST_PART_ELEM; + if (elem->length == state->elem_parsed) + ret = PSYC_PARSE_LIST_ELEM_START; + else + ret = PSYC_PARSE_LIST_ELEM_CONT; + break; + default: // should not be reached + return PSYC_PARSE_LIST_ERROR; + } + } else { + switch (parse_until((ParseState*)state, '|', elem)) { + case PARSE_SUCCESS: + state->part = PSYC_LIST_PART_ELEM_START; + ret = PSYC_PARSE_LIST_ELEM; + break; + case PARSE_INSUFFICIENT: + state->cursor = state->buffer.length; + return PSYC_PARSE_LIST_ELEM_LAST; + default: // should not be reached + return PSYC_PARSE_LIST_ERROR; + } + } - state->part = PSYC_LIST_PART_ELEM_START; - state->startc = state->cursor; - return ret; + state->startc = state->cursor; + return ret; } return PSYC_PARSE_LIST_ERROR; // should not be reached @@ -873,6 +878,7 @@ psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem) } break; case PARSE_INSUFFICIENT: // end of buffer + //state->cursor = state->buffer.length; return PSYC_PARSE_DICT_VALUE_LAST; case PARSE_ERROR: return PSYC_PARSE_DICT_ERROR_VALUE_TYPE; @@ -917,6 +923,7 @@ psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem) switch (parse_binary((ParseState*)state, state->elemlen, elem, &state->elem_parsed)) { case PARSE_SUCCESS: + state->part = PSYC_DICT_PART_KEY_START; if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_VALUE; else @@ -934,16 +941,17 @@ psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem) } else { switch (parse_until((ParseState*)state, '{', elem)) { case PARSE_SUCCESS: + state->part = PSYC_DICT_PART_KEY_START; ret = PSYC_PARSE_DICT_VALUE; break; case PARSE_INSUFFICIENT: + state->cursor = state->buffer.length; return PSYC_PARSE_DICT_VALUE_LAST; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } - state->part = PSYC_DICT_PART_KEY_START; return ret; }