34 return (
'0' <= c && c <=
'9');
39 static const char alpha[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
40 return (std::strchr(alpha, c) !=
nullptr);
50 return std::isspace(
static_cast<unsigned char>(c)) != 0;
69class BBNode :
public std::enable_shared_from_this<BBNode>
71 template<
typename NewTypePtrT>
74 if (node ==
nullptr && !bThrowOnFail)
78 else if (node ==
nullptr)
80 throw std::invalid_argument(
"Cannot downcast BBNode, object is null");
83 NewTypePtrT newobj = std::dynamic_pointer_cast<typename NewTypePtrT::element_type, BBNode>(node);
85 if (newobj ==
nullptr && bThrowOnFail)
87 throw std::invalid_argument(
"Cannot downcast, object is not correct type");
93 template<
typename NewTypePtrT>
96 if (node ==
nullptr && !bThrowOnFail)
100 else if (node ==
nullptr)
102 throw std::invalid_argument(
"Cannot downcast, BBNode object is null");
105 NewTypePtrT newobj = std::dynamic_pointer_cast<typename NewTypePtrT::element_type, BBNode>(node);
107 if (newobj ==
nullptr && bThrowOnFail)
109 throw std::invalid_argument(
"Cannot downcast, object is not correct type");
136 node->_parent = shared_from_this();
139 template<
typename NewTypePtrT>
142 return cast<NewTypePtrT>(shared_from_this(), bThrowOnFail);
145 template<
typename NewTypePtrT>
146 NewTypePtrT
downCast(
bool bThrowOnFail =
true)
const
148 return cast<NewTypePtrT>(shared_from_this(), bThrowOnFail);
146 NewTypePtrT
downCast(
bool bThrowOnFail =
true)
const {
…}
69class BBNode :
public std::enable_shared_from_this<BBNode> {
…};
203 void setOrAddParameter(
const std::string& key,
const std::string& value,
bool addIfNotExists =
true)
203 void setOrAddParameter(
const std::string& key,
const std::string& value,
bool addIfNotExists =
true) {
…}
236 template <
typename citerator>
239 auto endingChar = begin;
241 for (
auto it = begin; it != end; it++)
250 if (endingChar == begin)
255 newText(std::string(begin, endingChar));
260 template <
typename citerator>
264 std::stringstream str;
266 for (
auto it = start; it != end; it++)
269 const char c = (char)*it;
276 buf.assign(str.str());
284 template <
typename citerator>
304 int internal_openbracket_stack = 0;
307 bool quote_mode_known =
false;
308 bool is_value_quoted =
false;
310 std::stringstream temp;
312 for (
auto it = start; it != end; it++)
320 if (!quote_mode_known)
323 quote_mode_known =
true;
324 is_value_quoted =
true;
327 else if (is_value_quoted)
331 value.assign(temp.str());
342 internal_openbracket_stack++;
344 if (!quote_mode_known)
346 quote_mode_known =
true;
347 is_value_quoted =
false;
352 if (internal_openbracket_stack == 0)
354 value.assign(temp.str());
359 internal_openbracket_stack--;
366 if (!quote_mode_known)
368 quote_mode_known =
true;
369 is_value_quoted =
false;
379 template <
typename citerator>
380 citerator
parseKey(citerator begin, citerator end, std::string& keyname)
396 std::stringstream temp;
400 for (
auto it = start; it != end; it++)
408 keyname.assign(temp.str());
380 citerator
parseKey(citerator begin, citerator end, std::string& keyname) {
…}
424 template <
typename citerator>
427 auto current = begin;
431 while (current != end)
433 current =
parseKey(current, end, tempKey);
446 current = std::next(current);
449 if (tempKey.empty() || tempVal.empty())
455 pairs.insert(std::make_pair(tempKey, tempVal));
467 template <
typename citerator>
470 bool closingTag =
false;
473 auto nameStart = std::next(begin);
475 std::string elementName;
478 if (*nameStart ==
'/')
481 nameStart = std::next(nameStart);
487 if (elementName.empty())
492 else if (nameEnd == end)
494 newText(std::string(begin,end));
502 else if (*nameEnd ==
'=')
509 if (pairs.size() == 0)
511 newText(std::string(begin, kvEnd));
518 return std::next(kvEnd);
521 else if (*nameEnd ==
' ')
527 if (pairs.size() == 0)
529 newText(std::string(begin, kvEnd));
536 return std::next(kvEnd);
543 newText(std::string(begin,nameEnd));
556 return std::next(nameEnd);
566 void load(
const std::string& bbcode)
568 load(bbcode.begin(), bbcode.end());
566 void load(
const std::string& bbcode) {
…}
571 template<
class Iterator>
572 void load(Iterator begin, Iterator end)
575 auto bUnknownNodeType =
true;
576 auto current = begin;
581 while (current != end)
583 if (bUnknownNodeType)
588 bUnknownNodeType =
false;
593 bUnknownNodeType =
false;
597 if (!bUnknownNodeType)
602 throw std::runtime_error(
"Unknown node type in BBDocument::load()");
608 bUnknownNodeType =
true;
619 bUnknownNodeType =
false;
624 bUnknownNodeType =
true;
572 void load(Iterator begin, Iterator end) {
…}
645std::ostream& operator<<(std::ostream& os,
const ParameterMap& params)
649 for (
auto& p : params)
651 os << (first ?
"" :
", ") <<
"{" << p.first <<
"=" << p.second <<
"}";
BBElement & newClosingElement(const std::string &name)
citerator parseElement(citerator begin, citerator end)
void load(const std::string &bbcode)
BBElement & newKeyValueElement(const std::string &name, const ParameterMap &pairs)
BBElement & newElement(const std::string &name)
citerator parseKey(citerator begin, citerator end, std::string &keyname)
citerator parseKeyValuePairs(citerator begin, citerator end, ParameterMap &pairs)
BBText & newText(const std::string &text=std::string())
citerator parseText(citerator begin, citerator end)
void load(Iterator begin, Iterator end)
citerator parseAttributeValue(citerator begin, citerator end, std::string &value)
static BBDocumentPtr create()
citerator parseElementName(citerator begin, citerator end, std::string &buf)
const ParameterMap & getParameters() const
std::string findParameter(const std::string &key)
void setOrAddParameter(const std::string &key, const std::string &value, bool addIfNotExists=true)
BBElement(const std::string &name, ElementType et=BBElement::SIMPLE)
virtual ~BBElement()=default
const ElementType getElementType() const
NewTypePtrT cast(BBNodePtr node, bool bThrowOnFail)
BBNodePtr getParent() const
NodeType getNodeType() const
virtual void appendChild(BBNodePtr node)
const std::string & getNodeName() const
virtual ~BBNode()=default
const BBNodeList & getChildren() const
NewTypePtrT cast(BBNodePtr node, bool bThrowOnFail) const
NewTypePtrT downCast(bool bThrowOnFail=true)
NewTypePtrT downCast(bool bThrowOnFail=true) const
virtual const std::string getText() const
void append(const std::string &text)
BBText(const std::string &value)
virtual ~BBText()=default
std::stack< BBNodePtr > BBNodeStack
std::shared_ptr< BBDocument > BBDocumentPtr
std::shared_ptr< BBElement > BBElementPtr
std::weak_ptr< BBNode > BBNodeWeakPtr
std::shared_ptr< BBNode > BBNodePtr
std::map< std::string, std::string > ParameterMap
std::shared_ptr< BBText > BBTextPtr
std::vector< BBNodePtr > BBNodeList