1
0
Fork 0
mirror of git://git.psyc.eu/libpsyc synced 2024-08-15 03:19:02 +00:00

partial parsing possible with PsycParser and PsycListParser

This commit is contained in:
lurchi 2016-09-03 22:38:47 +02:00
parent 6330086b77
commit dd8cc059c5
6 changed files with 640 additions and 249 deletions

View file

@ -64,17 +64,16 @@ pub struct PsycParser {
state: PsycParseState
}
//pub struct PsycListParser<'a> {
// state: PsycParseListState,
// parsed_list: Vec<Vec<u8>>,
// 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<PsycParserResult<'a>, PsycParserError> {
pub fn parse(&mut self) -> Result<PsycParserResult<'a>, 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<PsycDictParserResult<'a>, 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<PsycListParserResult<'a>, 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<PsycDictParserResult<'a>, 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 {

View file

@ -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.

View file

@ -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]);
//}

View file

@ -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]);
}

View file

@ -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();

View file

@ -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;
}