tags:

views:

199

answers:

2

Hi all, I'm attempting to use boost::format, where my formatting string is the HTML below. I intend to insert 3x std::strings at locations specified by %s placeholders.

In other words - I'm opening the below *.html file for reading, read it's contents into a single std::string and use it as the formatter. Next I'm attempting to do the following :

std::string output = (boost::format(formatter) % str1 % str2 % str3).str();

Where str1-3 are strings containing text which I'm attempting to insert - obviously. The format attempt throws an exception saying that the format string is ill-formed. I've been trying to analyze it for the better part of the last 2 hrs but I've failed and I need some help.

What is wrong with the below HTML - why can't it become the proper formatter string? What are the limitations I should be aware of ?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>KP&D</title>
    <style type="text/css"> 
        html, body 
        {
            height: 100%;
            margin: 0;
            padding: 0;
        }
        img#bg 
        {
            position:fixed;
            top:0;
            left:0;
            width:100%;
            height:100%;
        }
        #content 
        {
            position:relative;
            z-index:1;
        }       
    </style>
</head>
<body>
<img src="Images/PageBackground.png" alt="background image" id="bg" />
<div id="content">
<br/>&nbsp;
<img src="Images/MyLogoReflected.png" alt="logo image"/>
<br />&nbsp;
<img src="Images/PDC_StatusPage.png" alt="remote status page image" />
<br />&nbsp;
<img src="Images/PDC_RemoteConfiguration.png" alt="remote config image" />
<br />&nbsp;
%s
<br />&nbsp;
<img src="Images/PDC_RemoteSubsystemStatus.png" alt="remote status image" />
<br />&nbsp;
%s
<br />&nbsp;
<img src="Images/PDC_RemoteConnectivityStatus.png" alt="remote status image" />
<br />&nbsp;
%s
<br />&nbsp;
</div>
</body>
</html>

Here's the code snippet responsible for loading the forementioned file :

#include <string>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>

int main()
{
    std::ifstream ifs("welcome.html"); // the html is in that file

    if(!ifs.good())
      return 1;

    std::string buffer = "";

    while(!ifs.eof())
    {
      char buf[256];
      ifs.getline(buf, 256);
      buffer += buf;
    }

    buffer = boost::trim_right_copy(buffer);

    const std::string str1 = "aaa";
    const std::string str2 = "bbb";
    const std::string str3 = "ccc";
    std::string Out = "";

    try{
    Out = (boost::format(buffer)
          % str1
          % str2
          % str3
          ).str();
   } catch(std::exception &e)
   { 
      err = e.what(); 
      return 1; 
   }

    return 0;
}
+4  A: 

boost::format uses % to delimit format specifications; so the % characters in your CSS are confusing it; it is trying to evaluate them as format specifications. You'll need to replace those with %% to get just a literal % character in the output.

If that doesn't help, then I would recommend trying to edit your template down into smaller pieces, until you find a piece as small as possible that demonstrates the problem. Once you do that, you may discover the problem yourself, but if not, edit your post to include that smaller snippet that still demonstrates the problem (preferably 1 or 2 lines of less than 80 characters each), as well as the exact error that you are getting from Boost. Likewise, it would help if you posted a snippet of the code you are using to read in the file, and invoke boost::format; a complete program with just a few lines of code for reading the template in, and printing the output of boost::format, would allow us to see if there's anything in your code that might be causing problems (and again, that may help you isolate the problem yourself).

The code you posted (edited a bit so it actually works; you left out declarations of buffer and err), works just fine with the template you posted, if all of the % signs in the CSS are replaced by %%, as I originally suggested. Here's the edited code (including output to check that it works):

#include <string>
#include <fstream>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <iostream>

int main()
{
    std::ifstream ifs("template.html"); // the html is in that file
    std::string buffer, err;

    if(!ifs.good())
      return 1;

    while(!ifs.eof())
    {
      char buf[256];
      ifs.getline(buf, 256);
      buffer += buf;
    }

    buffer = boost::trim_right_copy(buffer);

    const std::string str1 = "aaa";
    const std::string str2 = "bbb";
    const std::string str3 = "ccc";
    std::string Out = "";

    try{
    Out = (boost::format(buffer)
          % str1
          % str2
          % str3
          ).str();
   } catch(std::exception &e)
   { 
      err = e.what(); 
      std::cout << err << std::endl;
      return 1;
   }

    std::cout << Out;

    return 0;
}

And here's the edited template:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>KP&D</title>
    <style type="text/css"> 
        html, body 
        {
            height: 100%%;
            margin: 0;
            padding: 0;
        }
        img#bg 
        {
            position:fixed;
            top:0;
            left:0;
            width:100%%;
            height:100%%;
        }
        #content 
        {
            position:relative;
            z-index:1;
        }       
    </style>
</head>
<body>
<img src="Images/PageBackground.png" alt="background image" id="bg" />
<div id="content">
<br/>&nbsp;
<img src="Images/MyLogoReflected.png" alt="logo image"/>
<br />&nbsp;
<img src="Images/PDC_StatusPage.png" alt="remote status page image" />
<br />&nbsp;
<img src="Images/PDC_RemoteConfiguration.png" alt="remote config image" />
<br />&nbsp;
%s
<br />&nbsp;
<img src="Images/PDC_RemoteSubsystemStatus.png" alt="remote status image" />
<br />&nbsp;
%s
<br />&nbsp;
<img src="Images/PDC_RemoteConnectivityStatus.png" alt="remote status image" />
<br />&nbsp;
%s
<br />&nbsp;
</div>
</body>
</html>
Brian Campbell
I've done as you recommended. It didn't help - the string is still ill-formed. PS. VS now says that 100%% is not a valid value for height etc. Is that to be expected?
Maciek
Yes, because 100%% isn't a valid value. When it goes through Boost.Format, however, it will become valid as it replaces the double %.
coppro
I've added some notes on how to reduce the problem down, to help us isolate what's going on. The actual error message, and possibly a snippet of code demonstrating how you're reading in the file and invoking `boost::format`, would help too.
Brian Campbell
working on it, it will be up in a couple minutes
Maciek
ok it's up, I'm trying to isolate it but no luck so far
Maciek
ty Brian for all the help and your time.
Maciek
A: 

I've managed to locate the issue.

after optimizing the file reading & fixing the % characters it worked fine. Thank you all very very much.

Here's a cool snippet I've found on how to read whole file to string at once :)

buffer = std::string((std::istreambuf_iterator<char>(ifs)),
                          std::istreambuf_iterator<char>());
Maciek