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
|
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
namespace ircd
|
|
|
|
{
|
|
|
|
struct parse;
|
|
|
|
}
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2018-05-30 18:09:48 +02: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.
|
|
|
|
///
|
2017-08-28 23:51:22 +02:00
|
|
|
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)
|
2017-09-08 10:55:18 +02:00
|
|
|
IRCD_EXCEPTION(error, buffer_error)
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-03-13 20:05:13 +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;
|
|
|
|
};
|
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
struct ircd::parse::buffer
|
2016-11-29 16:23:38 +01:00
|
|
|
{
|
2017-03-13 20:05:13 +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();
|
|
|
|
|
2017-10-03 14:05:15 +02:00
|
|
|
buffer(const buffer &old, const mutable_buffer &mb)
|
|
|
|
:base{data(mb)}
|
|
|
|
,parsed{data(mb)}
|
|
|
|
,read{data(mb) + old.unparsed()}
|
2018-12-31 21:27:00 +01:00
|
|
|
,stop{data(mb) + ircd::size(mb)}
|
2017-03-13 20:05:13 +01:00
|
|
|
{
|
|
|
|
memmove(base, old.base, old.unparsed());
|
|
|
|
}
|
2016-11-29 16:23:38 +01:00
|
|
|
|
2017-10-03 14:05:15 +02: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
|
|
|
{}
|
|
|
|
|
2018-12-31 19:59:07 +01:00
|
|
|
buffer(const const_buffer &cb)
|
|
|
|
:base{const_cast<char *>(data(cb))}
|
|
|
|
,parsed{data(cb)}
|
|
|
|
,read{base + ircd::size(cb)}
|
|
|
|
,stop{read}
|
|
|
|
{}
|
|
|
|
|
2017-03-13 20:05:13 +01:00
|
|
|
template<size_t N> buffer(const buffer &old, char (&buf)[N])
|
2017-10-03 14:05:15 +02:00
|
|
|
:buffer{old, buf}
|
2016-11-29 16:23:38 +01:00
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
2017-08-28 23:51:22 +02:00
|
|
|
struct ircd::parse::capstan
|
2016-11-29 16:23:38 +01:00
|
|
|
{
|
|
|
|
const char *&parsed;
|
|
|
|
char *&read;
|
|
|
|
char *stop;
|
|
|
|
|
2017-03-13 20:05:13 +01:00
|
|
|
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)
|
2018-02-20 01:01:42 +01:00
|
|
|
try
|
2016-11-29 16:23:38 +01:00
|
|
|
{
|
2018-12-31 21:27:00 +01:00
|
|
|
while(!pc(parsed, const_cast<const char *>(read)) && read != stop)
|
2016-11-29 16:23:38 +01:00
|
|
|
reader(read, stop);
|
|
|
|
}
|
2018-02-20 01:01:42 +01:00
|
|
|
catch(const std::bad_function_call &e)
|
|
|
|
{
|
2019-01-14 00:50:04 +01:00
|
|
|
throw panic
|
2018-02-20 01:01:42 +01:00
|
|
|
{
|
|
|
|
"Invalid parse (parsed:%p read:%p stop:%p unparsed:%zu remaining: %zu)",
|
|
|
|
parsed,
|
|
|
|
read,
|
|
|
|
stop,
|
|
|
|
unparsed(),
|
|
|
|
remaining()
|
|
|
|
};
|
|
|
|
}
|
2017-03-13 20:05:13 +01:00
|
|
|
|
|
|
|
inline void
|
|
|
|
ircd::parse::buffer::remove()
|
|
|
|
{
|
|
|
|
memmove(base, parsed, unparsed());
|
|
|
|
read = base + unparsed();
|
|
|
|
parsed = base;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
ircd::parse::buffer::discard()
|
|
|
|
{
|
|
|
|
read -= unparsed();
|
|
|
|
}
|