use std::iter::Peekable;
use std::str::Chars;
use crate::{internal_error_map, error::*};
pub(crate) struct ConfTokenizer<'token>
{
srcmsg: &'token str,
chars: Peekable<Chars<'token>>,
pos: usize,
curchar: Option<char>,
}
impl<'token> ConfTokenizer<'token>
{
pub fn from_str(text_buf: &'token str) -> CDnsResult<Self>
{
let mut chars: Peekable<Chars> = text_buf.chars().peekable();
let cur: Option<char> =
Some(chars.next().ok_or_else(|| internal_error_map!(CDnsErrorType::InternalError, "unexpected EOF"))?);
return Ok(
Self
{
srcmsg: text_buf,
chars: chars,
pos: 0,
curchar: cur,
}
);
}
#[inline]
fn move_next(&mut self)
{
self.pos += 1;
self.curchar = self.chars.next();
}
#[inline]
fn get_cur_char(&self) -> Option<char>
{
return self.curchar;
}
#[inline]
fn foresee_char(&mut self) -> Option<char>
{
return match self.chars.peek()
{
Some(c) => Some(*c),
None => None
};
}
#[inline]
fn is_eof(&mut self) -> bool
{
return self.curchar.is_none();
}
pub fn skip_upto_eol(&mut self)
{
while let Some(c) = self.get_cur_char()
{
if c == '\n'
{
self.move_next();
break; }
self.move_next();
}
}
pub
fn read_upto_eol(&mut self) -> CDnsResult<Vec<String>>
{
let mut params: Vec<String> = Vec::new();
while let Some(c) = self.get_cur_char()
{
if c == '\n'
{
self.move_next();
break; }
else if c.is_whitespace() == true
{
self.move_next();
continue;
}
let initpos = self.pos;
loop
{
match self.get_cur_char()
{
None => break,
Some(ref c) if c.is_whitespace() == true =>
{
break;
},
Some(ref c) if c.is_control() == true =>
{
self.move_next();
break;
},
Some(_c) =>
{
self.move_next();
}
}
}
params.push(self.srcmsg[initpos..self.pos].to_string());
}
return Ok(params);
}
pub
fn read_next(&mut self) -> CDnsResult<Option<&str>>
{
loop
{
while self.is_eof() == false && self.get_cur_char().unwrap().is_whitespace() == true
{
self.move_next();
}
if self.is_eof() == true
{
return Ok(None);
}
if self.get_cur_char().unwrap() == '#'
{
self.move_next();
while let Some(c) = self.get_cur_char()
{
if c == '\n'
{
self.move_next();
break; }
self.move_next();
}
}
else
{
break;
}
}
let initpos = self.pos;
loop
{
match self.get_cur_char()
{
None => break,
Some(ref c) if c.is_whitespace() == true =>
{
break;
},
Some(ref c) if c.is_control() == true =>
{
self.move_next();
break;
},
Some(_c) =>
{
self.move_next();
}
}
}
let ret = &self.srcmsg[initpos..self.pos];
return Ok(Some(ret));
}
}