Reputation:
I have a mixed binary (i.e. image) and some human readable data (i.e. HTTP header) stored in the "std::vector<char>
" container.
(Data is separated by "CRLFCRLF (\r\n\r\n)" indicator)
Can anyone suggest a way on how to find a start position of "\r\n\r\n" in the "std::vector<char>
" container?
Is it possible to do something like "std::size_t pos = data.find("\r\n\r\n");
(where data is a "std::vector<char>
")" using STL library?
Thanks.
Upvotes: 6
Views: 6648
Reputation: 3304
// As mentioned, you can use a basic C-style string.
// But, for convenience, an array works just as well
// Using an array allows for us to use std::begin() and std::end()
static constexpr const char DOUBLE_CLRF[]{'\r','\n','\r','\n'};
/**
<summary> Finds the first occurrence of "\r\n\r\n". </summary>
<param name="v"> Contains the char data you want to process. </param>
<returns> The position of the first "\r\n\r\n". </returns>
*/
ptrdiff_t findFirstDoubleClrf(const std::vector<char>& v) {
const auto it = std::search(v.begin(), v.end(), std::begin(DOUBLE_CLRF), std::end(DOUBLE_CLRF));
return std::distance(v.begin(), it);
}
/**
<summary> Finds the last occurrence of "\r\n\r\n". </summary>
<param name="v"> Contains the char data you want to process. </param>
<returns> The position of the last "\r\n\r\n". </returns>
*/
ptrdiff_t findLastDoubleClrf(const std::vector<char>& v) {
const auto it = std::find_end(v.begin(), v.end(), std::begin(DOUBLE_CLRF), std::end(DOUBLE_CLRF));
return std::distance(v.begin(), it);
}
Now suppose your binary data with human readable text is in your (as mentioned) std::vector<char>
named data
.
// To get the *first* match
auto pos = findFirstDoubleClrf(data);
// To get the *last* match
auto lastPos = findLastDoubleClrf(data);
// Note: std::distance returns a signed value rather than unsigned (e.g. size_t)
// You can, of course, static_cast<size_t>(pos) if desired.
But if you miss the find()
method std::string
offers, and you have C++17 available, std::string_view
can be worked in without copying the entire std::vector<char>
to offer similar functionality.
std::string_view sv(&data[0], data.size());
auto pos = sv.find("\r\n\r\n");
auto lastPos = sv.rfind("\r\n\r\n");
Upvotes: 1
Reputation: 16690
You don't need to put the pattern you're looking for into a container. A C string is enough.
std::vector<char> v = ....;
const char *crlf2 = "\r\n\r\n";
auto it = std::search(v.begin(), v.end(), crlf2, crlf2 + strlen(crlf2));
Anyway, after this, it
will contain an iterator into the vector v
where that pattern begins (or v.end()
if the pattern is not found).
You can convert that into an index with std::distance(v.begin(), it)
or just it - v.begin()
Upvotes: 9
Reputation: 227538
You can use std::search
to search for the first occurrence of the character sequence of interest. You would have to place that sequence in an array or container.
std::vector<char> v = ....;
std::vector<char> start{'\r', '\n', '\r', '\n'};
auto it = std::search(v.begin(), v.end(), start.begin(), start.end());
Upvotes: 5