0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-01 03:18:54 +01:00
construct/include/ircd/parse.h

152 lines
3.9 KiB
C
Raw Normal View History

2018-02-04 03:22:01 +01:00
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
2016-11-29 16:23:38 +01:00
#pragma once
#define HAVE_IRCD_PARSE_H
namespace ircd
{
struct parse;
}
2016-11-29 16:23:38 +01:00
/// NOTE: This interface will likely be removed. It predates the entire
/// NOTE: ircd::buffer system and only has very few unique qualities left
/// NOTE: which have not been replicated within ircd::buffer yet.
///
struct ircd::parse
2016-11-29 16:23:38 +01:00
{
IRCD_EXCEPTION(ircd::error, error)
IRCD_EXCEPTION(error, grammar_error)
IRCD_EXCEPTION(error, syntax_error)
IRCD_EXCEPTION(error, buffer_error)
2016-11-29 16:23:38 +01:00
using read_closure = std::function<void (char *&, char *)>;
using parse_closure = std::function<bool (const char *&, const char *)>;
2016-11-29 16:23:38 +01:00
struct grammar;
2017-03-13 23:24:42 +01:00
struct capstan;
2016-11-29 16:23:38 +01:00
struct buffer;
};
struct ircd::parse::buffer
2016-11-29 16:23:38 +01:00
{
char *base; // Lowest address of the buffer (const)
const char *parsed; // Data between [base, parsed] is completed
char *read; // Data between [parsed, read] is unparsed
char *stop; // Data between [read, stop] is unreceived (const)
size_t size() const { return stop - base; }
size_t completed() const { return parsed - base; }
size_t unparsed() const { return read - parsed; }
size_t remaining() const { return stop - read; }
void discard();
void remove();
buffer(const buffer &old, const mutable_buffer &mb)
:base{data(mb)}
,parsed{data(mb)}
,read{data(mb) + old.unparsed()}
,stop{data(mb) + ircd::size(mb)}
{
memmove(base, old.base, old.unparsed());
}
2016-11-29 16:23:38 +01:00
buffer(const mutable_buffer &mb)
:base{data(mb)}
,parsed{data(mb)}
,read{data(mb)}
,stop{data(mb) + ircd::size(mb)}
2016-11-29 16:23:38 +01:00
{}
buffer(const const_buffer &cb)
:base{const_cast<char *>(data(cb))}
,parsed{data(cb)}
,read{base + ircd::size(cb)}
,stop{read}
{}
template<size_t N> buffer(const buffer &old, char (&buf)[N])
:buffer{old, buf}
2016-11-29 16:23:38 +01:00
{}
};
struct ircd::parse::capstan
2016-11-29 16:23:38 +01:00
{
const char *&parsed;
char *&read;
char *stop;
size_t unparsed() const { return read - parsed; }
size_t remaining() const { return stop - read; }
2016-11-29 16:23:38 +01:00
read_closure reader;
void operator()(const parse_closure &);
2017-03-13 23:24:42 +01:00
capstan(const char *&parsed, char *&read, char *const &max, const decltype(reader) &reader = nullptr);
capstan(buffer &, const decltype(reader) &reader = nullptr);
2016-11-29 16:23:38 +01:00
};
inline
2017-03-13 23:24:42 +01:00
ircd::parse::capstan::capstan(buffer &buffer,
2016-11-29 16:23:38 +01:00
const decltype(reader) &reader)
:parsed{buffer.parsed}
,read{buffer.read}
,stop{buffer.stop}
,reader{reader}
{
}
inline
2017-03-13 23:24:42 +01:00
ircd::parse::capstan::capstan(const char *&parsed,
2016-11-29 16:23:38 +01:00
char *&read,
char *const &max,
const decltype(reader) &reader)
:parsed{parsed}
,read{read}
,stop{max}
,reader{reader}
{
}
inline void
2017-03-13 23:24:42 +01:00
ircd::parse::capstan::operator()(const parse_closure &pc)
try
2016-11-29 16:23:38 +01:00
{
while(!pc(parsed, const_cast<const char *>(read)) && read != stop)
2016-11-29 16:23:38 +01:00
reader(read, stop);
}
catch(const std::bad_function_call &e)
{
throw panic
{
"Invalid parse (parsed:%p read:%p stop:%p unparsed:%zu remaining: %zu)",
parsed,
read,
stop,
unparsed(),
remaining()
};
}
inline void
ircd::parse::buffer::remove()
{
memmove(base, parsed, unparsed());
read = base + unparsed();
parsed = base;
}
inline void
ircd::parse::buffer::discard()
{
read -= unparsed();
}