6

Is it possible to somehow adapt a c-style string/buffer (char* or wchar_t*) to work with the Boost String Algorithms Library?

That is, for example, it's trimalgorithm has the following declaration:

template<typename SequenceT> 
void trim(SequenceT &, const std::locale & = std::locale());

and the implementation (look for trim_left_if) requires that the sequence type has a member function erase.

How could I use that with a raw character pointer / c string buffer?

char* pStr = getSomeCString(); // example, could also be something like wchar_t buf[256];
...
boost::trim(pStr); // HOW?

Ideally, the algorithms would work directly on the supplied buffer. (As far as possible. it obviously can't work if an algorithm needs to allocate additional space in the "string".)


@Vitaly asks: why can't you create a std::string from char buffer and then use it in algorithms?

The reason I have char* at all is that I'd like to use a few algorthims on our existing codebase. Refactoring all the char buffers to string would be more work than it's worth, and when changing or adapting something it would be nice to just be able to apply a given algorithm to any c-style string that happens to live in the current code.

Using a string would mean to (a) copy char* to string, (b) apply algorithm to string and (c) copy string back into char buffer.

Community
  • 1
  • 1
Martin Ba
  • 37,187
  • 33
  • 183
  • 337
  • 1
    why can't you create a std::string from char buffer and then use it in algorithms? – Vitaly Dyatlov Nov 04 '11 at 10:38
  • 2
    Do you really want to use the boost string algorithms? Why don't you use a c string library? (like one on this page: http://www.and.org/vstr/comparison) – rve Nov 04 '11 at 15:38
  • 1
    @rve: boost would handily already be there in our codebase. (Also: I can not find a `trim` like function in the vstr library you link to.) – Martin Ba Nov 07 '11 at 07:28
  • @Martin: I linked to that page because it also lists a lot of other string libraries. I think you want the ones where "Model = C-style strings" – rve Nov 07 '11 at 07:32

3 Answers3

5

For the SequenceT-type operations, you probably have to use std::string. If you wanted to implement that by yourself, you'd have to fulfill many more requirements for creation, destruction, value semantics etc. You'd basically end up with your implementation of std::string.

The RangeT-type operations might be, however, usable on char*s using the iterator_range from Boost.Range library. I didn't try it, though.

jpalecek
  • 47,058
  • 7
  • 102
  • 144
  • Thanks for highlighting the `SequenceT` and `RangeT` thing -- hadn't seen that there are different concepts used. – Martin Ba Nov 04 '11 at 11:01
  • `iterator_range` will work with `trim_copy` but not with `trim`. `trim` calls `erase` which `iterator_range` does not provide. – rve Nov 07 '11 at 18:40
  • @rve: that's the distinction between `RangeT` and `SequenceT`. Actually, as documented, `iterator_range` would work only with `trim_copy_if`, although it would probably work with `trim_copy` too. – jpalecek Nov 07 '11 at 18:48
1

There exist some code which implements a std::string like string with a fixed buffer. With some tinkering you can modify this code to create a string type which uses an external buffer:

char buffer[100];
strcpy(buffer, "   HELLO   ");

xstr::xstring<xstr::fixed_char_buf<char> >
    str(buffer, strlen(buffer), sizeof(buffer));

boost::algorithm::trim(str);
buffer[str.size()] = 0;

std::cout << buffer << std::endl;   // prints "HELLO"

For this I added an constructor to xstr::xstring and xstr::fixed_char_buf to take the buffer, the size of the buffer which is in use and the maximum size of the buffer. Further I replaced the SIZE template argument with a member variable and changed the internal char array into a char pointer.

The xstr code is a bit old and will not compile without trouble on newer compilers but it needs some minor changes. Further I only added the things needed in this case. If you want to use this for real, you need to make some more changes to make sure it can not use uninitialized memory.

Anyway, it might be a good start for writing you own string adapter.

rve
  • 5,897
  • 3
  • 40
  • 64
  • This does indeed look quite useful! I'll have to remember this for next time I'm able to pull a few additional library tools inside our project. – Martin Ba Nov 08 '11 at 06:37
0

I don't know what platform you're targeting, but on most modern computers (including mobile ones like ARM) memory copy is so fast you shouldn't even waste your time optimizing memory copies. I say - wrap char* in std::string and check whether the performance suits your needs. Don't waste time on premature optimization.

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • 2
    It's not about performance. It's about two additional logical steps (copy to, copy from) and another handcrafted additional wrapper function that would do this. Granted, it may be the best option. Also note: If this *Were* about performance, it's not only the memory *copy*, it is also the required dynamic allocation for std::string, and in a heavily multithreaded Windows application, heap access (`new`) *can* slow down things. (Note again: This question is not about performance.) – Martin Ba Nov 04 '11 at 11:39