{"id":626,"date":"2009-11-27T10:31:58","date_gmt":"2009-11-27T18:31:58","guid":{"rendered":"http:\/\/boost-spirit.com\/home\/?page_id=626"},"modified":"2010-11-13T06:24:15","modified_gmt":"2010-11-13T14:24:15","slug":"generate-escaped-string-output-using-spirit-karma","status":"publish","type":"page","link":"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/","title":{"rendered":"Generate Escaped String Output Using Spirit.Karma"},"content":{"rendered":"<p>This is another article in the series of \u201cHow To\u2019s\u201d providing you with shrink wrapped grammars directly usable in any project. I\u2019m going to describe a <em>Karma<\/em> grammar you can use to generate output for quoted strings, where all contained special characters are properly escaped.<\/p>\n<p>The previous installment of this series (see <a href=\"http:\/\/boost-spirit.com\/home\/?page_id=400\" target=\"_blank\">here<\/a>) is already giving a high level overview of <em>Karma<\/em>. This allows us to skip any related introductions and to start right away. The purpose of the <span style=\"font-family: Courier New;\">escaped_string<\/span> grammar is to generate output for any given character sequence while enclosing it in quotes (i.e. <span style=\"font-family: Courier New;\">\u2018\\\u201d\u2019<\/span> or <span style=\"font-family: Courier New;\">\u2018\\\u2019\u2019<\/span>) and making sure all relevant characters get escaped by pre-pending a backslash (i.e. <span style=\"font-family: Courier New;\">\u2018\\n\u2019<\/span> will be generated as <span style=\"font-family: Courier New;\">\u201c\\\\n\u201d<\/span><span style=\"font-family: Arial;\">, etc.). Let\u2019s start with the reverse Parsing Expression Grammar (PEG) for this:<\/span><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">esc_str \u2192 '&quot;' (esc_char \/ . \/ &quot;\\\\x&quot; hex)* '&quot;'\r\nesc_char \u2192 &amp;'\\a' &quot;\\\\a&quot; \/ &amp;'\\b' &quot;\\\\b&quot; \/ &amp;'\\f' &quot;\\\\f&quot; \/\r\n           &amp;'\\n' &quot;\\\\n&quot; \/ &amp;'\\r' &quot;\\\\r&quot; \/ &amp;'\\t' &quot;\\\\t&quot; \/\r\n           &amp;'\\v' &quot;\\\\v&quot; \/ &amp;'\\\\' &quot;\\\\\\\\&quot; \/\r\n           &amp;'\\'' &quot;\\\\\\'&quot; \/ &amp;'&quot;' &quot;\\\\\\&quot;&quot;\r\n<\/pre>\n<p>Any escaped string (<span style=\"font-family: Courier New;\">esc_str<\/span>) starts and ends with the quoting character (in this case <span style=\"font-family: Courier New;\">\u2018\u201d\u2019<\/span>) and all characters of the sequence are printed either as an escaped character (<span style=\"font-family: Courier New;\">esc_char<\/span>) or a printable character or a <span style=\"font-family: Courier New;\">\u201c\\\\x\u201d<\/span> followed by the hexadecimal representation of the corresponding character code. The esc_char will handle any of the listed character codes by generating a backslash followed by the corresponding C-style encoding. Each of the listed alternatives (such as <span style=\"font-family: Courier New;\">&amp;\u2018\\a\u2019 \u201c\\\\a\u201d<\/span>) reads as: if the character has the code <span style=\"font-family: Courier New;\">\u2018\\a\u2019<\/span> print it as <span style=\"font-family: Courier New;\">\u201c\\\\a\u201d<\/span> (a backslash followed by <span style=\"font-family: Courier New;\">\u2018a\u2019<\/span>).<\/p>\n<p>We have seen this before: converting the PEG into a Spirit grammar is a simple and formal step (we discussed that briefly <a href=\"http:\/\/boost-spirit.com\/home\/?page_id=371\" target=\"_blank\">here<\/a>):<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nesc_str = '&quot;' &lt;&lt; *(esc_char | karma::print | &quot;\\\\x&quot; &lt;&lt; karma::hex) &lt;&lt; '&quot;';\r\nesc_char.add('\\a', &quot;\\\\a&quot;)('\\b', &quot;\\\\b&quot;)('\\f', &quot;\\\\f&quot;)('\\n', &quot;\\\\n&quot;)\r\n            ('\\r', &quot;\\\\r&quot;)('\\t', &quot;\\\\t&quot;)('\\v', &quot;\\\\v&quot;)('\\\\', &quot;\\\\\\\\&quot;)\r\n            ('\\'', &quot;\\\\\\'&quot;)('&quot;', &quot;\\\\\\&quot;&quot;);\r\n<\/pre>\n<p>Note we use predefined <em>Karma<\/em> facilities here, replacing a straight reverse PEG translation. We could have defined the rule <span style=\"font-family: Courier New;\">esc_char<\/span> in a very similar way as done in the reverse PEG notation above, but decided to use a predefined <em>Karma<\/em> component, the <span style=\"font-family: Courier New;\"><a href=\"http:\/\/boost-spirit.com\/home\/spirit2\/libs\/spirit\/doc\/html\/spirit\/karma\/reference\/string\/symbols.html\" target=\"_blank\">karma::symbols&lt;&gt;<\/a><\/span>, instead. This gives us a nice way of mapping the special characters to their C-style representation. Conveniently, the symbols generator fails to generate anything if the supplied character is not contained in the symbols table. The <span style=\"font-family: Courier New; color: #404040;\"><a href=\"http:\/\/boost-spirit.com\/home\/spirit2\/libs\/spirit\/doc\/html\/spirit\/karma\/reference\/char\/char_class.html\" target=\"_blank\">karma::print<\/a><\/span> is a primitive generator which succeeds generating output for characters satisfying <a href=\"http:\/\/www.cppreference.com\/wiki\/c\/string\/isprint\" target=\"_blank\"><span style=\"font-family: Courier New;\">std::isprint()<\/span><\/a> while failing for all others. The <span style=\"font-family: cou; color: #404040;\"><a href=\"http:\/\/boost-spirit.com\/home\/spirit2\/libs\/spirit\/doc\/html\/spirit\/karma\/reference\/numeric\/unsigned_int.html\" target=\"_blank\">karma::hex<\/a> is a predefined numeric generator emitting its attribute in hexadecimal integer representation.\u00a0 <\/span><\/p>\n<p>Generally, <em>Karma<\/em> generators have the ability to fail generating if some of their preconditions are not met. This allows to use them in alternatives (as shown above), forcing to try the next alternative if the current generator doesn\u2019t handle the output. In the example above a specific character is first tried to be handled by the symbols generator. If the character is not in the list of those to be handled by the symbols generator, the next alternative (<span style=\"font-family: Courier New; color: #404040;\"><a href=\"http:\/\/boost-spirit.com\/home\/spirit2\/libs\/spirit\/doc\/html\/spirit\/karma\/reference\/char\/char_class.html\" target=\"_blank\">karma::print<\/a><\/span>) is tried. If the character does not satisfy <span style=\"font-family: Courier New; color: #404040;\"><a href=\"http:\/\/www.cppreference.com\/wiki\/c\/string\/isprint\" target=\"_blank\">std::isprint()<\/a><\/span> (resulting in the <span style=\"font-family: Courier New;\">karma::print<\/span> primitive to fail) we use the last alternative as a catch all fallback and emit the character\u2019s hexadecimal representation.<\/p>\n<p>The overall rule <span style=\"font-family: Courier New;\">esc_str<\/span> reads as: \u2018generate any supplied string embedded inside quotes (<span style=\"font-family: Courier New;\">\u2018\u201d\u2019<\/span>), convert all special characters into a sequence of a backslash and the corresponding C-style encoding and represent all non-printable characters in C-style hexadecimal character encoding\u2019.<\/p>\n<p>Now, as we have the grammar, the next step is to figure out the proper attribute types for the rules. As written <a href=\"http:\/\/boost-spirit.com\/home\/?page_id=400\" target=\"_blank\">before<\/a>, attributes in <em>Qi<\/em> are the types and values we get as the result of converting the input. Attributes in <em>Karma<\/em> are the types and values we want to generate output from. For our example the choice is straightforward and already implied by the goal. If we assume narrow character representation we get:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nkarma::rule&lt;OutputIterator, std::string()&gt; esc_str;\r\nkarma::symbol&lt;char, char const*&gt; esc_char;\r\n<\/pre>\n<p>We use <span style=\"font-family: Courier New; color: #404040;\"><a href=\"http:\/\/boost-spirit.com\/home\/spirit2\/libs\/spirit\/doc\/html\/spirit\/karma\/reference\/nonterminal\/rule.html\" target=\"_blank\">karma::rule&lt;&gt;<\/a><\/span> as the non-terminal for storing the output format for the <span style=\"font-family: Courier New;\">esc_str<\/span>. As this is the top level rule we assume <span style=\"font-family: Courier New;\">std::string<\/span> to be its attribute. As alluded to earlier, <span style=\"font-family: Courier New;\">esc_char<\/span> is a <span style=\"font-family: Courier New;\"><a href=\"http:\/\/boost-spirit.com\/home\/spirit2\/libs\/spirit\/doc\/html\/spirit\/karma\/reference\/string\/symbols.html\">karma::symbols&lt;&gt;<\/a><\/span> instance using one character in the string as the key while storing the C-style representation of that character as its value. Two of the generator alternatives inside the Kleene Star expose a single char as their attribute. The third alternative, the (<span style=\"font-family: Courier New;\">&#8220;\\\\x&#8221; &lt;&lt; karma::hex<\/span>) exposes an <span style=\"font-family: Courier New;\">int<\/span> as its attribute, but this is perfectly compatible with a single character. This allows the <span style=\"font-family: Courier New;\">std::string<\/span> to be naturally split into single characters, one at a time.<\/p>\n<p>Essentially we are done. That was not too hard, was it?<\/p>\n<p>But before we write the (reusable) grammar and demonstrate how it needs to be called I thought to make things a bit more interesting. So far our output format is bound to generate strings quoted using the double quote character (<span style=\"font-family: Courier New;\">\u2018\u201d\u2019<\/span>). Wouldn\u2019t it be nice to be able to customize the quoting character as well? This is interesting for instance if you need to generate Python style strings which come in 3 flavors: quoted with <span style=\"font-family: Courier New;\">\u2018\u201d\u2019<\/span>, <span style=\"font-family: Courier New;\">\u201c\u2019\u201d<\/span>, or <span style=\"font-family: Courier New;\">\u201c\u2019\u2019\u2019\u201d<\/span>. So I decided to introduce another features provided by <em>Spirit\u2019s<\/em> non-terminals: inherited attributes. Non-terminals in recursive descent parsers and generators can be seen as being very similar to functions. Parsers return a value, their <em>synthesized<\/em> attribute, while generators require a special <em>consumed<\/em> attribute. Both optionally may take arguments, their <em>inherited<\/em> attributes. <em>Spirit<\/em> uses the function declaration syntax in order to specify all attributes in a very compact form. So we make the grammar customizable by \u2018passing\u2019 the quoting character sequence as an inherited attribute. We modify the rule <span style=\"font-family: Courier New;\">esc_str<\/span> to expect a single inherited attribute (the quoting sequence) as a plain <span style=\"font-family: Courier New;\">char const*<\/span>, and change the rule definition to use this attribute:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nkarma::rule&lt;OutputIterator, std::string(char const*)&gt; esc_str =\r\n        karma::lit(karma::_r1)\r\n    &lt;&lt; *(esc_char | karma::print | &quot;\\\\x&quot; &lt;&lt; karma::hex)\r\n    &lt;&lt;  karma::lit(karma::_r1);\r\n<\/pre>\n<p>The predefined primitive <span style=\"font-family: Courier New;\">karma::lit<\/span> emits its argument as a literal and <span style=\"font-family: Courier New;\">karma::_r1<\/span> is a special predefined placeholder expression referring to the first inherited attribute of the rule on the left hand side of the expression.<\/p>\n<p>Now, as we have all the required pieces in place I\u2019ll show you how to wrap everything into a <span style=\"font-family: Courier New;\">karma::grammar<\/span> to make it reusable:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate &lt;typename OutputIterator&gt;\r\nstruct escaped_string\r\n  : karma::grammar&lt;OutputIterator, std::string(char const*)&gt;\r\n{\r\n    escaped_string()\r\n      : escaped_string::base_type(esc_str)\r\n    {\r\n        esc_char.add('\\a', &quot;\\\\a&quot;)('\\b', &quot;\\\\b&quot;)('\\f', &quot;\\\\f&quot;)('\\n', &quot;\\\\n&quot;)\r\n                    ('\\r', &quot;\\\\r&quot;)('\\t', &quot;\\\\t&quot;)('\\v', &quot;\\\\v&quot;)('\\\\', &quot;\\\\\\\\&quot;)\r\n                    ('\\'', &quot;\\\\\\'&quot;)('&quot;', &quot;\\\\\\&quot;&quot;)\r\n            ;\r\n        esc_str =   karma::lit(karma::_r1)\r\n                &lt;&lt; *(esc_char | karma::print | &quot;\\\\x&quot; &lt;&lt; karma::hex)\r\n                &lt;&lt;  karma::lit(karma::_r1)\r\n            ;\r\n    }\r\n    karma::rule&lt;OutputIterator, std::string(char const*)&gt; esc_str;\r\n    karma::symbols&lt;char, char const*&gt; esc_char;\r\n};\r\n<\/pre>\n<p>The derivation from <em>Karma\u2019s<\/em> grammar type converts the <span style=\"font-family: courier new;\">escaped_string<\/span> type into a generator. Its member rules define a grammar which makes it usable for emitting quoted strings using arbitrary quoting characters. The base class constructor gets passed the esc_str rule, which is the top most rule of the grammar to be executed when the grammar is invoked. The type <span style=\"font-family: courier new;\">escaped_string<\/span> has a template parameter allowing to utilize this grammar with arbitrary output iterator types.<\/p>\n<p>The last missing code piece shows how to invoke the newly created generator.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntypedef std::back_insert_iterator&lt;std::string&gt; sink_type;\r\n\r\nstd::string generated;\r\nsink_type sink(generated);\r\n\r\nstd::string str(&quot;string to escape: \\n\\r\\t\\&quot;'\\x19&quot;);\r\nchar const* quote = &quot;\u2019\u2019\u2019&quot;;\r\n\r\nclient::escaped_string&lt;sink_type&gt; g;\r\nkarma::generate(sink, g(quote), str);\r\n    \/\/ this will emit: \u2019\u2019\u2019string to escape: \\n\\r\\t\\&quot;\\'\\x19\u2019\u2019\u2019&lt;\/a&gt;\r\n<\/pre>\n<p>The function <span style=\"font-family: courier new;\">karma::generate()<\/span> is another of Spirit\u2019s main API functions. In the simplest case it takes an output iterator representing the output target to send the output to <span style=\"font-family: courier new;\">(sink)<\/span>, an instance of the generator to invoke <span style=\"font-family: courier new;\">(g)<\/span>, and the attribute instance holding the data <span style=\"font-family: courier new;\">(v)<\/span>. We pass the quoting character sequence (the <span style=\"font-family: Courier New;\">\u201c\\\u201d\u201d<\/span>) as a inherited attribute while invoking the grammar. This function executes the actual generator operation and returns <span style=\"font-family: courier new;\">true<\/span> if it was successful.<\/p>\n<p>If you want to try out this example for yourself, the complete source code is available from the <a href=\"http:\/\/www.boost.org\/\" target=\"_blank\">Boost<\/a> SVN <a href=\"http:\/\/svn.boost.org\/svn\/boost\/trunk\/libs\/spirit\/example\/karma\/escaped_string.cpp\" target=\"_blank\">here<\/a>. In the future this example will be distributed as part of the Spirit distribution, but for now it lives in the SVN only. Additionally, the <span style=\"font-family: Courier New;\"><a href=\"http:\/\/boost-spirit.com\/home\/spirit2\/libs\/spirit\/doc\/html\/spirit\/karma\/reference\/string\/symbols.html\" target=\"_blank\">karma::symbols&lt;&gt;<\/a><\/span> generator is not yet part of the latest released code (Spirit V2.1). You either need to checkout the current version of Spirit from the SVN or download the related file <a href=\"http:\/\/svn.boost.org\/svn\/boost\/trunk\/boost\/spirit\/home\/karma\/string\/symbols.hpp\">here<\/a>. In this case you need to explicitly include it into the example in order to be able to compile the code.<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Share this:<\/h3><div class=\"sd-content\"><ul><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>Share<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-626\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=facebook\" target=\"_blank\" title=\"Click to share on Facebook\" ><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-626\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=twitter\" target=\"_blank\" title=\"Click to share on Twitter\" ><span>Twitter<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-pinterest\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-pinterest-626\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=pinterest\" target=\"_blank\" title=\"Click to share on Pinterest\" ><span>Pinterest<\/span><\/a><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-626\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=linkedin\" target=\"_blank\" title=\"Click to share on LinkedIn\" ><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-reddit\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-reddit sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=reddit\" target=\"_blank\" title=\"Click to share on Reddit\" ><span>Reddit<\/span><\/a><\/li><li class=\"share-tumblr\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-tumblr sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=tumblr\" target=\"_blank\" title=\"Click to share on Tumblr\" ><span>Tumblr<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>This is another article in the series of \u201cHow To\u2019s\u201d providing you with shrink wrapped grammars directly usable in any project. I\u2019m going to describe a Karma grammar you can use to generate output for quoted strings, where all contained special characters are properly escaped. The previous installment of this series (see here) is already [&hellip;]<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Share this:<\/h3><div class=\"sd-content\"><ul><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>Share<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-626\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=facebook\" target=\"_blank\" title=\"Click to share on Facebook\" ><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-626\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=twitter\" target=\"_blank\" title=\"Click to share on Twitter\" ><span>Twitter<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-pinterest\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-pinterest-626\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=pinterest\" target=\"_blank\" title=\"Click to share on Pinterest\" ><span>Pinterest<\/span><\/a><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-626\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=linkedin\" target=\"_blank\" title=\"Click to share on LinkedIn\" ><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-reddit\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-reddit sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=reddit\" target=\"_blank\" title=\"Click to share on Reddit\" ><span>Reddit<\/span><\/a><\/li><li class=\"share-tumblr\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-tumblr sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/karma-examples\/generate-escaped-string-output-using-spirit-karma\/?share=tumblr\" target=\"_blank\" title=\"Click to share on Tumblr\" ><span>Tumblr<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"author":3,"featured_media":0,"parent":397,"menu_order":2,"comment_status":"open","ping_status":"open","template":"article-page.php","meta":{"_s2mail":"yes","spay_email":""},"jetpack_shortlink":"https:\/\/wp.me\/PIHdZ-a6","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/626"}],"collection":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/comments?post=626"}],"version-history":[{"count":25,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/626\/revisions"}],"predecessor-version":[{"id":640,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/626\/revisions\/640"}],"up":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/397"}],"wp:attachment":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/media?parent=626"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}