2011-11-02 95 views
7

我想知道Boost.Format是否支持使用固定宽度/预分配的缓冲区作为输出,而不是由lib本身管理的动态缓冲区?是否可以使用预分配缓冲区的Boost.Format?

也就是说,正常情况下你会怎么做:

boost::format myfmt("arg1: %1%/arg2: %2%"); 
// e.g.: 
cout << (myfmt % 3.14 % 42); 
// or 
string s = boost::str(myfmt % "hey!" % "there!"); 

所以升压:格式LIB将自动完成分配足够的空间和管理“输出缓冲区”为你的。

我想知道是否有任何方式使用与Boost.Format库一个预定义的非动态缓冲区,也就是这样的:

const size_t buf_sz = 512; 
char big_enough[buf_sz]; 
boost::format myfmt("arg1: %1%/arg2: %2%"); 
myfmt.attach_buffer(big_enough, buf_sz); 
myfmt % "hey!" % "there!" 
// big_enough buffer now contains the result string 

我知道我可以通过例子只是筛选,该文档和来源,但除了缺乏时间atm。 (以及错过某些东西的可能性)知道以下内容会很有趣: 如果不可能,如果有人能解释为什么(如果存在/具体的是什么) - 这是故意的吗?它不符合API吗? ...?

声明:这个问题是不是关于性能!

+0

你要什么,当你运行的空间会发生什么?对于一个固定的buff,我会使用snprintf,但这就是我:) – nhed

+0

@nhed如果它不合适,库可以/可以抛出一个异常或只是停止填充缓冲区(类似于[选项](http:///www.boost.org/doc/libs/1_47_0/libs/format/doc/format.html#exceptions)已提供) –

+0

我不确定那些例外情况适用于目标缓冲区 – nhed

回答

4

初步设想

望着source看来你可以用你自己的分配器,然后使用的boost::format内部流(internal_streambuf_t)。这对你的情况足够好吗?

例如,你可以使用类似的libstdC++ array_allocator

不幸的是boost::format还使用了几个std::vector不使用它可以在你的情况下,问题的自定义分配器?

如何boost::format工作

我看着的boost::format的来源,这是它如何工作(以下描述为str()<<电话要么str()或使用标准std::ostream东西):

  • 格式类有时使用自定义分配器,有时使用默认分配器
  • 当所有参数和格式字符串分开时,将str()称为它cr eates新std::string并使其使用自定义分配器
  • 它,然后附加在格式字符串的所有参数和静态串件结果字符串
  • 最后却由值返回结果字符串足够大的结果

因此,最终的结果字符串并不存储在format类中,而是在需要时创建。

所以,即使您在使用自定义分配器时可以找到结果字符串的位置,它也只能在调用str()之后/期间使用。 这应该解释为什么它是不可能的:格式化结果永远不会存储在类的“输出缓冲区”中。

它为什么会这样工作

他们为什么这样做,我不知道。我认为这是因为只有在知道所有参数后才能创建结果,这会浪费空间来存储结果,并且对于给定的格式/参数组合,您可能只需要一次结果。因此,在需要时创建它并不会导致额外的工作,因为通常只会调用str()一次。

解决方案

  • 创建围绕str()<<一些包装和结果复制到您的固定缓冲
  • 使用stream_buffer为“流”串入缓冲区(见下面的例子)
  • 继承该类并添加您自己的str()函数,该函数将结果存储在固定缓冲区中。

使用可能的解决方法boost::iostreams(测试):

#include <iostream> 
#include <boost/format.hpp> 
#include <boost/iostreams/stream.hpp> 

int main() 
{ 
    char buffer[100]; 

    boost::iostreams::stream<boost::iostreams::array_sink> 
     stream(buffer, sizeof(buffer)); 

    stream << (boost::format("arg1 = %1%") % 12.5); 
    stream << '\0'; // make sure buffer contains 0-terminated string 

    std::cout << buffer << std::endl;  
} 
+0

有用的信息。我认为分配器的一个小问题是,他们只能通过bad_alloc报告失败,对吗? –

+0

@Martin:我认为你是对的。另外,我研究了格式的来源,我认为使用分配器很难做到。我用我发现的东西更新了我的答案。 – rve

+0

干得好!我是否正确理解你:每次调用'.str()'时都会重新构建输出字符串? –

相关问题