annotate DEPENDENCIES/generic/include/boost/asio/impl/read_until.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 //
Chris@16 2 // impl/read_until.hpp
Chris@16 3 // ~~~~~~~~~~~~~~~~~~~
Chris@16 4 //
Chris@101 5 // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Chris@16 6 //
Chris@16 7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 9 //
Chris@16 10
Chris@16 11 #ifndef BOOST_ASIO_IMPL_READ_UNTIL_HPP
Chris@16 12 #define BOOST_ASIO_IMPL_READ_UNTIL_HPP
Chris@16 13
Chris@16 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 15 # pragma once
Chris@16 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
Chris@16 17
Chris@16 18 #include <algorithm>
Chris@16 19 #include <string>
Chris@16 20 #include <vector>
Chris@16 21 #include <utility>
Chris@16 22 #include <boost/asio/buffer.hpp>
Chris@16 23 #include <boost/asio/buffers_iterator.hpp>
Chris@16 24 #include <boost/asio/detail/bind_handler.hpp>
Chris@16 25 #include <boost/asio/detail/handler_alloc_helpers.hpp>
Chris@16 26 #include <boost/asio/detail/handler_cont_helpers.hpp>
Chris@16 27 #include <boost/asio/detail/handler_invoke_helpers.hpp>
Chris@16 28 #include <boost/asio/detail/handler_type_requirements.hpp>
Chris@16 29 #include <boost/asio/detail/limits.hpp>
Chris@16 30 #include <boost/asio/detail/throw_error.hpp>
Chris@16 31
Chris@16 32 #include <boost/asio/detail/push_options.hpp>
Chris@16 33
Chris@16 34 namespace boost {
Chris@16 35 namespace asio {
Chris@16 36
Chris@16 37 template <typename SyncReadStream, typename Allocator>
Chris@16 38 inline std::size_t read_until(SyncReadStream& s,
Chris@16 39 boost::asio::basic_streambuf<Allocator>& b, char delim)
Chris@16 40 {
Chris@16 41 boost::system::error_code ec;
Chris@16 42 std::size_t bytes_transferred = read_until(s, b, delim, ec);
Chris@16 43 boost::asio::detail::throw_error(ec, "read_until");
Chris@16 44 return bytes_transferred;
Chris@16 45 }
Chris@16 46
Chris@16 47 template <typename SyncReadStream, typename Allocator>
Chris@16 48 std::size_t read_until(SyncReadStream& s,
Chris@16 49 boost::asio::basic_streambuf<Allocator>& b, char delim,
Chris@16 50 boost::system::error_code& ec)
Chris@16 51 {
Chris@16 52 std::size_t search_position = 0;
Chris@16 53 for (;;)
Chris@16 54 {
Chris@16 55 // Determine the range of the data to be searched.
Chris@16 56 typedef typename boost::asio::basic_streambuf<
Chris@16 57 Allocator>::const_buffers_type const_buffers_type;
Chris@16 58 typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
Chris@16 59 const_buffers_type buffers = b.data();
Chris@16 60 iterator begin = iterator::begin(buffers);
Chris@16 61 iterator start_pos = begin + search_position;
Chris@16 62 iterator end = iterator::end(buffers);
Chris@16 63
Chris@16 64 // Look for a match.
Chris@16 65 iterator iter = std::find(start_pos, end, delim);
Chris@16 66 if (iter != end)
Chris@16 67 {
Chris@16 68 // Found a match. We're done.
Chris@16 69 ec = boost::system::error_code();
Chris@16 70 return iter - begin + 1;
Chris@16 71 }
Chris@16 72 else
Chris@16 73 {
Chris@16 74 // No match. Next search can start with the new data.
Chris@16 75 search_position = end - begin;
Chris@16 76 }
Chris@16 77
Chris@16 78 // Check if buffer is full.
Chris@16 79 if (b.size() == b.max_size())
Chris@16 80 {
Chris@16 81 ec = error::not_found;
Chris@16 82 return 0;
Chris@16 83 }
Chris@16 84
Chris@16 85 // Need more data.
Chris@16 86 std::size_t bytes_to_read = read_size_helper(b, 65536);
Chris@16 87 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
Chris@16 88 if (ec)
Chris@16 89 return 0;
Chris@16 90 }
Chris@16 91 }
Chris@16 92
Chris@16 93 template <typename SyncReadStream, typename Allocator>
Chris@16 94 inline std::size_t read_until(SyncReadStream& s,
Chris@16 95 boost::asio::basic_streambuf<Allocator>& b, const std::string& delim)
Chris@16 96 {
Chris@16 97 boost::system::error_code ec;
Chris@16 98 std::size_t bytes_transferred = read_until(s, b, delim, ec);
Chris@16 99 boost::asio::detail::throw_error(ec, "read_until");
Chris@16 100 return bytes_transferred;
Chris@16 101 }
Chris@16 102
Chris@16 103 namespace detail
Chris@16 104 {
Chris@16 105 // Algorithm that finds a subsequence of equal values in a sequence. Returns
Chris@16 106 // (iterator,true) if a full match was found, in which case the iterator
Chris@16 107 // points to the beginning of the match. Returns (iterator,false) if a
Chris@16 108 // partial match was found at the end of the first sequence, in which case
Chris@16 109 // the iterator points to the beginning of the partial match. Returns
Chris@16 110 // (last1,false) if no full or partial match was found.
Chris@16 111 template <typename Iterator1, typename Iterator2>
Chris@16 112 std::pair<Iterator1, bool> partial_search(
Chris@16 113 Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
Chris@16 114 {
Chris@16 115 for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
Chris@16 116 {
Chris@16 117 Iterator1 test_iter1 = iter1;
Chris@16 118 Iterator2 test_iter2 = first2;
Chris@16 119 for (;; ++test_iter1, ++test_iter2)
Chris@16 120 {
Chris@16 121 if (test_iter2 == last2)
Chris@16 122 return std::make_pair(iter1, true);
Chris@16 123 if (test_iter1 == last1)
Chris@16 124 {
Chris@16 125 if (test_iter2 != first2)
Chris@16 126 return std::make_pair(iter1, false);
Chris@16 127 else
Chris@16 128 break;
Chris@16 129 }
Chris@16 130 if (*test_iter1 != *test_iter2)
Chris@16 131 break;
Chris@16 132 }
Chris@16 133 }
Chris@16 134 return std::make_pair(last1, false);
Chris@16 135 }
Chris@16 136 } // namespace detail
Chris@16 137
Chris@16 138 template <typename SyncReadStream, typename Allocator>
Chris@16 139 std::size_t read_until(SyncReadStream& s,
Chris@16 140 boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
Chris@16 141 boost::system::error_code& ec)
Chris@16 142 {
Chris@16 143 std::size_t search_position = 0;
Chris@16 144 for (;;)
Chris@16 145 {
Chris@16 146 // Determine the range of the data to be searched.
Chris@16 147 typedef typename boost::asio::basic_streambuf<
Chris@16 148 Allocator>::const_buffers_type const_buffers_type;
Chris@16 149 typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
Chris@16 150 const_buffers_type buffers = b.data();
Chris@16 151 iterator begin = iterator::begin(buffers);
Chris@16 152 iterator start_pos = begin + search_position;
Chris@16 153 iterator end = iterator::end(buffers);
Chris@16 154
Chris@16 155 // Look for a match.
Chris@16 156 std::pair<iterator, bool> result = detail::partial_search(
Chris@16 157 start_pos, end, delim.begin(), delim.end());
Chris@16 158 if (result.first != end)
Chris@16 159 {
Chris@16 160 if (result.second)
Chris@16 161 {
Chris@16 162 // Full match. We're done.
Chris@16 163 ec = boost::system::error_code();
Chris@16 164 return result.first - begin + delim.length();
Chris@16 165 }
Chris@16 166 else
Chris@16 167 {
Chris@16 168 // Partial match. Next search needs to start from beginning of match.
Chris@16 169 search_position = result.first - begin;
Chris@16 170 }
Chris@16 171 }
Chris@16 172 else
Chris@16 173 {
Chris@16 174 // No match. Next search can start with the new data.
Chris@16 175 search_position = end - begin;
Chris@16 176 }
Chris@16 177
Chris@16 178 // Check if buffer is full.
Chris@16 179 if (b.size() == b.max_size())
Chris@16 180 {
Chris@16 181 ec = error::not_found;
Chris@16 182 return 0;
Chris@16 183 }
Chris@16 184
Chris@16 185 // Need more data.
Chris@16 186 std::size_t bytes_to_read = read_size_helper(b, 65536);
Chris@16 187 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
Chris@16 188 if (ec)
Chris@16 189 return 0;
Chris@16 190 }
Chris@16 191 }
Chris@16 192
Chris@16 193 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
Chris@16 194
Chris@16 195 template <typename SyncReadStream, typename Allocator>
Chris@16 196 inline std::size_t read_until(SyncReadStream& s,
Chris@16 197 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
Chris@16 198 {
Chris@16 199 boost::system::error_code ec;
Chris@16 200 std::size_t bytes_transferred = read_until(s, b, expr, ec);
Chris@16 201 boost::asio::detail::throw_error(ec, "read_until");
Chris@16 202 return bytes_transferred;
Chris@16 203 }
Chris@16 204
Chris@16 205 template <typename SyncReadStream, typename Allocator>
Chris@16 206 std::size_t read_until(SyncReadStream& s,
Chris@16 207 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
Chris@16 208 boost::system::error_code& ec)
Chris@16 209 {
Chris@16 210 std::size_t search_position = 0;
Chris@16 211 for (;;)
Chris@16 212 {
Chris@16 213 // Determine the range of the data to be searched.
Chris@16 214 typedef typename boost::asio::basic_streambuf<
Chris@16 215 Allocator>::const_buffers_type const_buffers_type;
Chris@16 216 typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
Chris@16 217 const_buffers_type buffers = b.data();
Chris@16 218 iterator begin = iterator::begin(buffers);
Chris@16 219 iterator start_pos = begin + search_position;
Chris@16 220 iterator end = iterator::end(buffers);
Chris@16 221
Chris@16 222 // Look for a match.
Chris@16 223 boost::match_results<iterator,
Chris@16 224 typename std::vector<boost::sub_match<iterator> >::allocator_type>
Chris@16 225 match_results;
Chris@16 226 if (regex_search(start_pos, end, match_results, expr,
Chris@16 227 boost::match_default | boost::match_partial))
Chris@16 228 {
Chris@16 229 if (match_results[0].matched)
Chris@16 230 {
Chris@16 231 // Full match. We're done.
Chris@16 232 ec = boost::system::error_code();
Chris@16 233 return match_results[0].second - begin;
Chris@16 234 }
Chris@16 235 else
Chris@16 236 {
Chris@16 237 // Partial match. Next search needs to start from beginning of match.
Chris@16 238 search_position = match_results[0].first - begin;
Chris@16 239 }
Chris@16 240 }
Chris@16 241 else
Chris@16 242 {
Chris@16 243 // No match. Next search can start with the new data.
Chris@16 244 search_position = end - begin;
Chris@16 245 }
Chris@16 246
Chris@16 247 // Check if buffer is full.
Chris@16 248 if (b.size() == b.max_size())
Chris@16 249 {
Chris@16 250 ec = error::not_found;
Chris@16 251 return 0;
Chris@16 252 }
Chris@16 253
Chris@16 254 // Need more data.
Chris@16 255 std::size_t bytes_to_read = read_size_helper(b, 65536);
Chris@16 256 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
Chris@16 257 if (ec)
Chris@16 258 return 0;
Chris@16 259 }
Chris@16 260 }
Chris@16 261
Chris@16 262 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
Chris@16 263
Chris@16 264 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
Chris@16 265 std::size_t read_until(SyncReadStream& s,
Chris@16 266 boost::asio::basic_streambuf<Allocator>& b,
Chris@16 267 MatchCondition match_condition, boost::system::error_code& ec,
Chris@16 268 typename enable_if<is_match_condition<MatchCondition>::value>::type*)
Chris@16 269 {
Chris@16 270 std::size_t search_position = 0;
Chris@16 271 for (;;)
Chris@16 272 {
Chris@16 273 // Determine the range of the data to be searched.
Chris@16 274 typedef typename boost::asio::basic_streambuf<
Chris@16 275 Allocator>::const_buffers_type const_buffers_type;
Chris@16 276 typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
Chris@16 277 const_buffers_type buffers = b.data();
Chris@16 278 iterator begin = iterator::begin(buffers);
Chris@16 279 iterator start_pos = begin + search_position;
Chris@16 280 iterator end = iterator::end(buffers);
Chris@16 281
Chris@16 282 // Look for a match.
Chris@16 283 std::pair<iterator, bool> result = match_condition(start_pos, end);
Chris@16 284 if (result.second)
Chris@16 285 {
Chris@16 286 // Full match. We're done.
Chris@16 287 ec = boost::system::error_code();
Chris@16 288 return result.first - begin;
Chris@16 289 }
Chris@16 290 else if (result.first != end)
Chris@16 291 {
Chris@16 292 // Partial match. Next search needs to start from beginning of match.
Chris@16 293 search_position = result.first - begin;
Chris@16 294 }
Chris@16 295 else
Chris@16 296 {
Chris@16 297 // No match. Next search can start with the new data.
Chris@16 298 search_position = end - begin;
Chris@16 299 }
Chris@16 300
Chris@16 301 // Check if buffer is full.
Chris@16 302 if (b.size() == b.max_size())
Chris@16 303 {
Chris@16 304 ec = error::not_found;
Chris@16 305 return 0;
Chris@16 306 }
Chris@16 307
Chris@16 308 // Need more data.
Chris@16 309 std::size_t bytes_to_read = read_size_helper(b, 65536);
Chris@16 310 b.commit(s.read_some(b.prepare(bytes_to_read), ec));
Chris@16 311 if (ec)
Chris@16 312 return 0;
Chris@16 313 }
Chris@16 314 }
Chris@16 315
Chris@16 316 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
Chris@16 317 inline std::size_t read_until(SyncReadStream& s,
Chris@16 318 boost::asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
Chris@16 319 typename enable_if<is_match_condition<MatchCondition>::value>::type*)
Chris@16 320 {
Chris@16 321 boost::system::error_code ec;
Chris@16 322 std::size_t bytes_transferred = read_until(s, b, match_condition, ec);
Chris@16 323 boost::asio::detail::throw_error(ec, "read_until");
Chris@16 324 return bytes_transferred;
Chris@16 325 }
Chris@16 326
Chris@16 327 namespace detail
Chris@16 328 {
Chris@16 329 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 330 class read_until_delim_op
Chris@16 331 {
Chris@16 332 public:
Chris@16 333 read_until_delim_op(AsyncReadStream& stream,
Chris@16 334 boost::asio::basic_streambuf<Allocator>& streambuf,
Chris@16 335 char delim, ReadHandler& handler)
Chris@16 336 : stream_(stream),
Chris@16 337 streambuf_(streambuf),
Chris@16 338 delim_(delim),
Chris@16 339 start_(0),
Chris@16 340 search_position_(0),
Chris@16 341 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
Chris@16 342 {
Chris@16 343 }
Chris@16 344
Chris@16 345 #if defined(BOOST_ASIO_HAS_MOVE)
Chris@16 346 read_until_delim_op(const read_until_delim_op& other)
Chris@16 347 : stream_(other.stream_),
Chris@16 348 streambuf_(other.streambuf_),
Chris@16 349 delim_(other.delim_),
Chris@16 350 start_(other.start_),
Chris@16 351 search_position_(other.search_position_),
Chris@16 352 handler_(other.handler_)
Chris@16 353 {
Chris@16 354 }
Chris@16 355
Chris@16 356 read_until_delim_op(read_until_delim_op&& other)
Chris@16 357 : stream_(other.stream_),
Chris@16 358 streambuf_(other.streambuf_),
Chris@16 359 delim_(other.delim_),
Chris@16 360 start_(other.start_),
Chris@16 361 search_position_(other.search_position_),
Chris@16 362 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
Chris@16 363 {
Chris@16 364 }
Chris@16 365 #endif // defined(BOOST_ASIO_HAS_MOVE)
Chris@16 366
Chris@16 367 void operator()(const boost::system::error_code& ec,
Chris@16 368 std::size_t bytes_transferred, int start = 0)
Chris@16 369 {
Chris@16 370 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
Chris@16 371 std::size_t bytes_to_read;
Chris@16 372 switch (start_ = start)
Chris@16 373 {
Chris@16 374 case 1:
Chris@16 375 for (;;)
Chris@16 376 {
Chris@16 377 {
Chris@16 378 // Determine the range of the data to be searched.
Chris@16 379 typedef typename boost::asio::basic_streambuf<
Chris@16 380 Allocator>::const_buffers_type const_buffers_type;
Chris@16 381 typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
Chris@16 382 const_buffers_type buffers = streambuf_.data();
Chris@16 383 iterator begin = iterator::begin(buffers);
Chris@16 384 iterator start_pos = begin + search_position_;
Chris@16 385 iterator end = iterator::end(buffers);
Chris@16 386
Chris@16 387 // Look for a match.
Chris@16 388 iterator iter = std::find(start_pos, end, delim_);
Chris@16 389 if (iter != end)
Chris@16 390 {
Chris@16 391 // Found a match. We're done.
Chris@16 392 search_position_ = iter - begin + 1;
Chris@16 393 bytes_to_read = 0;
Chris@16 394 }
Chris@16 395
Chris@16 396 // No match yet. Check if buffer is full.
Chris@16 397 else if (streambuf_.size() == streambuf_.max_size())
Chris@16 398 {
Chris@16 399 search_position_ = not_found;
Chris@16 400 bytes_to_read = 0;
Chris@16 401 }
Chris@16 402
Chris@16 403 // Need to read some more data.
Chris@16 404 else
Chris@16 405 {
Chris@16 406 // Next search can start with the new data.
Chris@16 407 search_position_ = end - begin;
Chris@16 408 bytes_to_read = read_size_helper(streambuf_, 65536);
Chris@16 409 }
Chris@16 410 }
Chris@16 411
Chris@16 412 // Check if we're done.
Chris@16 413 if (!start && bytes_to_read == 0)
Chris@16 414 break;
Chris@16 415
Chris@16 416 // Start a new asynchronous read operation to obtain more data.
Chris@16 417 stream_.async_read_some(streambuf_.prepare(bytes_to_read),
Chris@16 418 BOOST_ASIO_MOVE_CAST(read_until_delim_op)(*this));
Chris@16 419 return; default:
Chris@16 420 streambuf_.commit(bytes_transferred);
Chris@16 421 if (ec || bytes_transferred == 0)
Chris@16 422 break;
Chris@16 423 }
Chris@16 424
Chris@16 425 const boost::system::error_code result_ec =
Chris@16 426 (search_position_ == not_found)
Chris@16 427 ? error::not_found : ec;
Chris@16 428
Chris@16 429 const std::size_t result_n =
Chris@16 430 (ec || search_position_ == not_found)
Chris@16 431 ? 0 : search_position_;
Chris@16 432
Chris@16 433 handler_(result_ec, result_n);
Chris@16 434 }
Chris@16 435 }
Chris@16 436
Chris@16 437 //private:
Chris@16 438 AsyncReadStream& stream_;
Chris@16 439 boost::asio::basic_streambuf<Allocator>& streambuf_;
Chris@16 440 char delim_;
Chris@16 441 int start_;
Chris@16 442 std::size_t search_position_;
Chris@16 443 ReadHandler handler_;
Chris@16 444 };
Chris@16 445
Chris@16 446 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 447 inline void* asio_handler_allocate(std::size_t size,
Chris@16 448 read_until_delim_op<AsyncReadStream,
Chris@16 449 Allocator, ReadHandler>* this_handler)
Chris@16 450 {
Chris@16 451 return boost_asio_handler_alloc_helpers::allocate(
Chris@16 452 size, this_handler->handler_);
Chris@16 453 }
Chris@16 454
Chris@16 455 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 456 inline void asio_handler_deallocate(void* pointer, std::size_t size,
Chris@16 457 read_until_delim_op<AsyncReadStream,
Chris@16 458 Allocator, ReadHandler>* this_handler)
Chris@16 459 {
Chris@16 460 boost_asio_handler_alloc_helpers::deallocate(
Chris@16 461 pointer, size, this_handler->handler_);
Chris@16 462 }
Chris@16 463
Chris@16 464 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 465 inline bool asio_handler_is_continuation(
Chris@16 466 read_until_delim_op<AsyncReadStream,
Chris@16 467 Allocator, ReadHandler>* this_handler)
Chris@16 468 {
Chris@16 469 return this_handler->start_ == 0 ? true
Chris@16 470 : boost_asio_handler_cont_helpers::is_continuation(
Chris@16 471 this_handler->handler_);
Chris@16 472 }
Chris@16 473
Chris@16 474 template <typename Function, typename AsyncReadStream, typename Allocator,
Chris@16 475 typename ReadHandler>
Chris@16 476 inline void asio_handler_invoke(Function& function,
Chris@16 477 read_until_delim_op<AsyncReadStream,
Chris@16 478 Allocator, ReadHandler>* this_handler)
Chris@16 479 {
Chris@16 480 boost_asio_handler_invoke_helpers::invoke(
Chris@16 481 function, this_handler->handler_);
Chris@16 482 }
Chris@16 483
Chris@16 484 template <typename Function, typename AsyncReadStream, typename Allocator,
Chris@16 485 typename ReadHandler>
Chris@16 486 inline void asio_handler_invoke(const Function& function,
Chris@16 487 read_until_delim_op<AsyncReadStream,
Chris@16 488 Allocator, ReadHandler>* this_handler)
Chris@16 489 {
Chris@16 490 boost_asio_handler_invoke_helpers::invoke(
Chris@16 491 function, this_handler->handler_);
Chris@16 492 }
Chris@16 493 } // namespace detail
Chris@16 494
Chris@16 495 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 496 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
Chris@16 497 void (boost::system::error_code, std::size_t))
Chris@16 498 async_read_until(AsyncReadStream& s,
Chris@16 499 boost::asio::basic_streambuf<Allocator>& b, char delim,
Chris@16 500 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
Chris@16 501 {
Chris@16 502 // If you get an error on the following line it means that your handler does
Chris@16 503 // not meet the documented type requirements for a ReadHandler.
Chris@16 504 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
Chris@16 505
Chris@16 506 detail::async_result_init<
Chris@16 507 ReadHandler, void (boost::system::error_code, std::size_t)> init(
Chris@16 508 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
Chris@16 509
Chris@16 510 detail::read_until_delim_op<AsyncReadStream,
Chris@16 511 Allocator, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
Chris@16 512 void (boost::system::error_code, std::size_t))>(
Chris@16 513 s, b, delim, init.handler)(
Chris@16 514 boost::system::error_code(), 0, 1);
Chris@16 515
Chris@16 516 return init.result.get();
Chris@16 517 }
Chris@16 518
Chris@16 519 namespace detail
Chris@16 520 {
Chris@16 521 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 522 class read_until_delim_string_op
Chris@16 523 {
Chris@16 524 public:
Chris@16 525 read_until_delim_string_op(AsyncReadStream& stream,
Chris@16 526 boost::asio::basic_streambuf<Allocator>& streambuf,
Chris@16 527 const std::string& delim, ReadHandler& handler)
Chris@16 528 : stream_(stream),
Chris@16 529 streambuf_(streambuf),
Chris@16 530 delim_(delim),
Chris@16 531 start_(0),
Chris@16 532 search_position_(0),
Chris@16 533 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
Chris@16 534 {
Chris@16 535 }
Chris@16 536
Chris@16 537 #if defined(BOOST_ASIO_HAS_MOVE)
Chris@16 538 read_until_delim_string_op(const read_until_delim_string_op& other)
Chris@16 539 : stream_(other.stream_),
Chris@16 540 streambuf_(other.streambuf_),
Chris@16 541 delim_(other.delim_),
Chris@16 542 start_(other.start_),
Chris@16 543 search_position_(other.search_position_),
Chris@16 544 handler_(other.handler_)
Chris@16 545 {
Chris@16 546 }
Chris@16 547
Chris@16 548 read_until_delim_string_op(read_until_delim_string_op&& other)
Chris@16 549 : stream_(other.stream_),
Chris@16 550 streambuf_(other.streambuf_),
Chris@16 551 delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
Chris@16 552 start_(other.start_),
Chris@16 553 search_position_(other.search_position_),
Chris@16 554 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
Chris@16 555 {
Chris@16 556 }
Chris@16 557 #endif // defined(BOOST_ASIO_HAS_MOVE)
Chris@16 558
Chris@16 559 void operator()(const boost::system::error_code& ec,
Chris@16 560 std::size_t bytes_transferred, int start = 0)
Chris@16 561 {
Chris@16 562 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
Chris@16 563 std::size_t bytes_to_read;
Chris@16 564 switch (start_ = start)
Chris@16 565 {
Chris@16 566 case 1:
Chris@16 567 for (;;)
Chris@16 568 {
Chris@16 569 {
Chris@16 570 // Determine the range of the data to be searched.
Chris@16 571 typedef typename boost::asio::basic_streambuf<
Chris@16 572 Allocator>::const_buffers_type const_buffers_type;
Chris@16 573 typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
Chris@16 574 const_buffers_type buffers = streambuf_.data();
Chris@16 575 iterator begin = iterator::begin(buffers);
Chris@16 576 iterator start_pos = begin + search_position_;
Chris@16 577 iterator end = iterator::end(buffers);
Chris@16 578
Chris@16 579 // Look for a match.
Chris@16 580 std::pair<iterator, bool> result = detail::partial_search(
Chris@16 581 start_pos, end, delim_.begin(), delim_.end());
Chris@16 582 if (result.first != end && result.second)
Chris@16 583 {
Chris@16 584 // Full match. We're done.
Chris@16 585 search_position_ = result.first - begin + delim_.length();
Chris@16 586 bytes_to_read = 0;
Chris@16 587 }
Chris@16 588
Chris@16 589 // No match yet. Check if buffer is full.
Chris@16 590 else if (streambuf_.size() == streambuf_.max_size())
Chris@16 591 {
Chris@16 592 search_position_ = not_found;
Chris@16 593 bytes_to_read = 0;
Chris@16 594 }
Chris@16 595
Chris@16 596 // Need to read some more data.
Chris@16 597 else
Chris@16 598 {
Chris@16 599 if (result.first != end)
Chris@16 600 {
Chris@16 601 // Partial match. Next search needs to start from beginning of
Chris@16 602 // match.
Chris@16 603 search_position_ = result.first - begin;
Chris@16 604 }
Chris@16 605 else
Chris@16 606 {
Chris@16 607 // Next search can start with the new data.
Chris@16 608 search_position_ = end - begin;
Chris@16 609 }
Chris@16 610
Chris@16 611 bytes_to_read = read_size_helper(streambuf_, 65536);
Chris@16 612 }
Chris@16 613 }
Chris@16 614
Chris@16 615 // Check if we're done.
Chris@16 616 if (!start && bytes_to_read == 0)
Chris@16 617 break;
Chris@16 618
Chris@16 619 // Start a new asynchronous read operation to obtain more data.
Chris@16 620 stream_.async_read_some(streambuf_.prepare(bytes_to_read),
Chris@16 621 BOOST_ASIO_MOVE_CAST(read_until_delim_string_op)(*this));
Chris@16 622 return; default:
Chris@16 623 streambuf_.commit(bytes_transferred);
Chris@16 624 if (ec || bytes_transferred == 0)
Chris@16 625 break;
Chris@16 626 }
Chris@16 627
Chris@16 628 const boost::system::error_code result_ec =
Chris@16 629 (search_position_ == not_found)
Chris@16 630 ? error::not_found : ec;
Chris@16 631
Chris@16 632 const std::size_t result_n =
Chris@16 633 (ec || search_position_ == not_found)
Chris@16 634 ? 0 : search_position_;
Chris@16 635
Chris@16 636 handler_(result_ec, result_n);
Chris@16 637 }
Chris@16 638 }
Chris@16 639
Chris@16 640 //private:
Chris@16 641 AsyncReadStream& stream_;
Chris@16 642 boost::asio::basic_streambuf<Allocator>& streambuf_;
Chris@16 643 std::string delim_;
Chris@16 644 int start_;
Chris@16 645 std::size_t search_position_;
Chris@16 646 ReadHandler handler_;
Chris@16 647 };
Chris@16 648
Chris@16 649 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 650 inline void* asio_handler_allocate(std::size_t size,
Chris@16 651 read_until_delim_string_op<AsyncReadStream,
Chris@16 652 Allocator, ReadHandler>* this_handler)
Chris@16 653 {
Chris@16 654 return boost_asio_handler_alloc_helpers::allocate(
Chris@16 655 size, this_handler->handler_);
Chris@16 656 }
Chris@16 657
Chris@16 658 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 659 inline void asio_handler_deallocate(void* pointer, std::size_t size,
Chris@16 660 read_until_delim_string_op<AsyncReadStream,
Chris@16 661 Allocator, ReadHandler>* this_handler)
Chris@16 662 {
Chris@16 663 boost_asio_handler_alloc_helpers::deallocate(
Chris@16 664 pointer, size, this_handler->handler_);
Chris@16 665 }
Chris@16 666
Chris@16 667 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 668 inline bool asio_handler_is_continuation(
Chris@16 669 read_until_delim_string_op<AsyncReadStream,
Chris@16 670 Allocator, ReadHandler>* this_handler)
Chris@16 671 {
Chris@16 672 return this_handler->start_ == 0 ? true
Chris@16 673 : boost_asio_handler_cont_helpers::is_continuation(
Chris@16 674 this_handler->handler_);
Chris@16 675 }
Chris@16 676
Chris@16 677 template <typename Function, typename AsyncReadStream,
Chris@16 678 typename Allocator, typename ReadHandler>
Chris@16 679 inline void asio_handler_invoke(Function& function,
Chris@16 680 read_until_delim_string_op<AsyncReadStream,
Chris@16 681 Allocator, ReadHandler>* this_handler)
Chris@16 682 {
Chris@16 683 boost_asio_handler_invoke_helpers::invoke(
Chris@16 684 function, this_handler->handler_);
Chris@16 685 }
Chris@16 686
Chris@16 687 template <typename Function, typename AsyncReadStream,
Chris@16 688 typename Allocator, typename ReadHandler>
Chris@16 689 inline void asio_handler_invoke(const Function& function,
Chris@16 690 read_until_delim_string_op<AsyncReadStream,
Chris@16 691 Allocator, ReadHandler>* this_handler)
Chris@16 692 {
Chris@16 693 boost_asio_handler_invoke_helpers::invoke(
Chris@16 694 function, this_handler->handler_);
Chris@16 695 }
Chris@16 696 } // namespace detail
Chris@16 697
Chris@16 698 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 699 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
Chris@16 700 void (boost::system::error_code, std::size_t))
Chris@16 701 async_read_until(AsyncReadStream& s,
Chris@16 702 boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
Chris@16 703 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
Chris@16 704 {
Chris@16 705 // If you get an error on the following line it means that your handler does
Chris@16 706 // not meet the documented type requirements for a ReadHandler.
Chris@16 707 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
Chris@16 708
Chris@16 709 detail::async_result_init<
Chris@16 710 ReadHandler, void (boost::system::error_code, std::size_t)> init(
Chris@16 711 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
Chris@16 712
Chris@16 713 detail::read_until_delim_string_op<AsyncReadStream,
Chris@16 714 Allocator, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
Chris@16 715 void (boost::system::error_code, std::size_t))>(
Chris@16 716 s, b, delim, init.handler)(
Chris@16 717 boost::system::error_code(), 0, 1);
Chris@16 718
Chris@16 719 return init.result.get();
Chris@16 720 }
Chris@16 721
Chris@16 722 #if defined(BOOST_ASIO_HAS_BOOST_REGEX)
Chris@16 723
Chris@16 724 namespace detail
Chris@16 725 {
Chris@16 726 template <typename AsyncReadStream, typename Allocator,
Chris@16 727 typename RegEx, typename ReadHandler>
Chris@16 728 class read_until_expr_op
Chris@16 729 {
Chris@16 730 public:
Chris@16 731 read_until_expr_op(AsyncReadStream& stream,
Chris@16 732 boost::asio::basic_streambuf<Allocator>& streambuf,
Chris@16 733 const boost::regex& expr, ReadHandler& handler)
Chris@16 734 : stream_(stream),
Chris@16 735 streambuf_(streambuf),
Chris@16 736 expr_(expr),
Chris@16 737 start_(0),
Chris@16 738 search_position_(0),
Chris@16 739 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
Chris@16 740 {
Chris@16 741 }
Chris@16 742
Chris@16 743 #if defined(BOOST_ASIO_HAS_MOVE)
Chris@16 744 read_until_expr_op(const read_until_expr_op& other)
Chris@16 745 : stream_(other.stream_),
Chris@16 746 streambuf_(other.streambuf_),
Chris@16 747 expr_(other.expr_),
Chris@16 748 start_(other.start_),
Chris@16 749 search_position_(other.search_position_),
Chris@16 750 handler_(other.handler_)
Chris@16 751 {
Chris@16 752 }
Chris@16 753
Chris@16 754 read_until_expr_op(read_until_expr_op&& other)
Chris@16 755 : stream_(other.stream_),
Chris@16 756 streambuf_(other.streambuf_),
Chris@16 757 expr_(other.expr_),
Chris@16 758 start_(other.start_),
Chris@16 759 search_position_(other.search_position_),
Chris@16 760 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
Chris@16 761 {
Chris@16 762 }
Chris@16 763 #endif // defined(BOOST_ASIO_HAS_MOVE)
Chris@16 764
Chris@16 765 void operator()(const boost::system::error_code& ec,
Chris@16 766 std::size_t bytes_transferred, int start = 0)
Chris@16 767 {
Chris@16 768 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
Chris@16 769 std::size_t bytes_to_read;
Chris@16 770 switch (start_ = start)
Chris@16 771 {
Chris@16 772 case 1:
Chris@16 773 for (;;)
Chris@16 774 {
Chris@16 775 {
Chris@16 776 // Determine the range of the data to be searched.
Chris@16 777 typedef typename boost::asio::basic_streambuf<
Chris@16 778 Allocator>::const_buffers_type const_buffers_type;
Chris@16 779 typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
Chris@16 780 const_buffers_type buffers = streambuf_.data();
Chris@16 781 iterator begin = iterator::begin(buffers);
Chris@16 782 iterator start_pos = begin + search_position_;
Chris@16 783 iterator end = iterator::end(buffers);
Chris@16 784
Chris@16 785 // Look for a match.
Chris@16 786 boost::match_results<iterator,
Chris@16 787 typename std::vector<boost::sub_match<iterator> >::allocator_type>
Chris@16 788 match_results;
Chris@16 789 bool match = regex_search(start_pos, end, match_results, expr_,
Chris@16 790 boost::match_default | boost::match_partial);
Chris@16 791 if (match && match_results[0].matched)
Chris@16 792 {
Chris@16 793 // Full match. We're done.
Chris@16 794 search_position_ = match_results[0].second - begin;
Chris@16 795 bytes_to_read = 0;
Chris@16 796 }
Chris@16 797
Chris@16 798 // No match yet. Check if buffer is full.
Chris@16 799 else if (streambuf_.size() == streambuf_.max_size())
Chris@16 800 {
Chris@16 801 search_position_ = not_found;
Chris@16 802 bytes_to_read = 0;
Chris@16 803 }
Chris@16 804
Chris@16 805 // Need to read some more data.
Chris@16 806 else
Chris@16 807 {
Chris@16 808 if (match)
Chris@16 809 {
Chris@16 810 // Partial match. Next search needs to start from beginning of
Chris@16 811 // match.
Chris@16 812 search_position_ = match_results[0].first - begin;
Chris@16 813 }
Chris@16 814 else
Chris@16 815 {
Chris@16 816 // Next search can start with the new data.
Chris@16 817 search_position_ = end - begin;
Chris@16 818 }
Chris@16 819
Chris@16 820 bytes_to_read = read_size_helper(streambuf_, 65536);
Chris@16 821 }
Chris@16 822 }
Chris@16 823
Chris@16 824 // Check if we're done.
Chris@16 825 if (!start && bytes_to_read == 0)
Chris@16 826 break;
Chris@16 827
Chris@16 828 // Start a new asynchronous read operation to obtain more data.
Chris@16 829 stream_.async_read_some(streambuf_.prepare(bytes_to_read),
Chris@16 830 BOOST_ASIO_MOVE_CAST(read_until_expr_op)(*this));
Chris@16 831 return; default:
Chris@16 832 streambuf_.commit(bytes_transferred);
Chris@16 833 if (ec || bytes_transferred == 0)
Chris@16 834 break;
Chris@16 835 }
Chris@16 836
Chris@16 837 const boost::system::error_code result_ec =
Chris@16 838 (search_position_ == not_found)
Chris@16 839 ? error::not_found : ec;
Chris@16 840
Chris@16 841 const std::size_t result_n =
Chris@16 842 (ec || search_position_ == not_found)
Chris@16 843 ? 0 : search_position_;
Chris@16 844
Chris@16 845 handler_(result_ec, result_n);
Chris@16 846 }
Chris@16 847 }
Chris@16 848
Chris@16 849 //private:
Chris@16 850 AsyncReadStream& stream_;
Chris@16 851 boost::asio::basic_streambuf<Allocator>& streambuf_;
Chris@16 852 RegEx expr_;
Chris@16 853 int start_;
Chris@16 854 std::size_t search_position_;
Chris@16 855 ReadHandler handler_;
Chris@16 856 };
Chris@16 857
Chris@16 858 template <typename AsyncReadStream, typename Allocator,
Chris@16 859 typename RegEx, typename ReadHandler>
Chris@16 860 inline void* asio_handler_allocate(std::size_t size,
Chris@16 861 read_until_expr_op<AsyncReadStream,
Chris@16 862 Allocator, RegEx, ReadHandler>* this_handler)
Chris@16 863 {
Chris@16 864 return boost_asio_handler_alloc_helpers::allocate(
Chris@16 865 size, this_handler->handler_);
Chris@16 866 }
Chris@16 867
Chris@16 868 template <typename AsyncReadStream, typename Allocator,
Chris@16 869 typename RegEx, typename ReadHandler>
Chris@16 870 inline void asio_handler_deallocate(void* pointer, std::size_t size,
Chris@16 871 read_until_expr_op<AsyncReadStream,
Chris@16 872 Allocator, RegEx, ReadHandler>* this_handler)
Chris@16 873 {
Chris@16 874 boost_asio_handler_alloc_helpers::deallocate(
Chris@16 875 pointer, size, this_handler->handler_);
Chris@16 876 }
Chris@16 877
Chris@16 878 template <typename AsyncReadStream, typename Allocator,
Chris@16 879 typename RegEx, typename ReadHandler>
Chris@16 880 inline bool asio_handler_is_continuation(
Chris@16 881 read_until_expr_op<AsyncReadStream,
Chris@16 882 Allocator, RegEx, ReadHandler>* this_handler)
Chris@16 883 {
Chris@16 884 return this_handler->start_ == 0 ? true
Chris@16 885 : boost_asio_handler_cont_helpers::is_continuation(
Chris@16 886 this_handler->handler_);
Chris@16 887 }
Chris@16 888
Chris@16 889 template <typename Function, typename AsyncReadStream, typename Allocator,
Chris@16 890 typename RegEx, typename ReadHandler>
Chris@16 891 inline void asio_handler_invoke(Function& function,
Chris@16 892 read_until_expr_op<AsyncReadStream,
Chris@16 893 Allocator, RegEx, ReadHandler>* this_handler)
Chris@16 894 {
Chris@16 895 boost_asio_handler_invoke_helpers::invoke(
Chris@16 896 function, this_handler->handler_);
Chris@16 897 }
Chris@16 898
Chris@16 899 template <typename Function, typename AsyncReadStream, typename Allocator,
Chris@16 900 typename RegEx, typename ReadHandler>
Chris@16 901 inline void asio_handler_invoke(const Function& function,
Chris@16 902 read_until_expr_op<AsyncReadStream,
Chris@16 903 Allocator, RegEx, ReadHandler>* this_handler)
Chris@16 904 {
Chris@16 905 boost_asio_handler_invoke_helpers::invoke(
Chris@16 906 function, this_handler->handler_);
Chris@16 907 }
Chris@16 908 } // namespace detail
Chris@16 909
Chris@16 910 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
Chris@16 911 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
Chris@16 912 void (boost::system::error_code, std::size_t))
Chris@16 913 async_read_until(AsyncReadStream& s,
Chris@16 914 boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
Chris@16 915 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
Chris@16 916 {
Chris@16 917 // If you get an error on the following line it means that your handler does
Chris@16 918 // not meet the documented type requirements for a ReadHandler.
Chris@16 919 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
Chris@16 920
Chris@16 921 detail::async_result_init<
Chris@16 922 ReadHandler, void (boost::system::error_code, std::size_t)> init(
Chris@16 923 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
Chris@16 924
Chris@16 925 detail::read_until_expr_op<AsyncReadStream, Allocator,
Chris@16 926 boost::regex, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
Chris@16 927 void (boost::system::error_code, std::size_t))>(
Chris@16 928 s, b, expr, init.handler)(
Chris@16 929 boost::system::error_code(), 0, 1);
Chris@16 930
Chris@16 931 return init.result.get();
Chris@16 932 }
Chris@16 933
Chris@16 934 #endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
Chris@16 935
Chris@16 936 namespace detail
Chris@16 937 {
Chris@16 938 template <typename AsyncReadStream, typename Allocator,
Chris@16 939 typename MatchCondition, typename ReadHandler>
Chris@16 940 class read_until_match_op
Chris@16 941 {
Chris@16 942 public:
Chris@16 943 read_until_match_op(AsyncReadStream& stream,
Chris@16 944 boost::asio::basic_streambuf<Allocator>& streambuf,
Chris@16 945 MatchCondition match_condition, ReadHandler& handler)
Chris@16 946 : stream_(stream),
Chris@16 947 streambuf_(streambuf),
Chris@16 948 match_condition_(match_condition),
Chris@16 949 start_(0),
Chris@16 950 search_position_(0),
Chris@16 951 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
Chris@16 952 {
Chris@16 953 }
Chris@16 954
Chris@16 955 #if defined(BOOST_ASIO_HAS_MOVE)
Chris@16 956 read_until_match_op(const read_until_match_op& other)
Chris@16 957 : stream_(other.stream_),
Chris@16 958 streambuf_(other.streambuf_),
Chris@16 959 match_condition_(other.match_condition_),
Chris@16 960 start_(other.start_),
Chris@16 961 search_position_(other.search_position_),
Chris@16 962 handler_(other.handler_)
Chris@16 963 {
Chris@16 964 }
Chris@16 965
Chris@16 966 read_until_match_op(read_until_match_op&& other)
Chris@16 967 : stream_(other.stream_),
Chris@16 968 streambuf_(other.streambuf_),
Chris@16 969 match_condition_(other.match_condition_),
Chris@16 970 start_(other.start_),
Chris@16 971 search_position_(other.search_position_),
Chris@16 972 handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
Chris@16 973 {
Chris@16 974 }
Chris@16 975 #endif // defined(BOOST_ASIO_HAS_MOVE)
Chris@16 976
Chris@16 977 void operator()(const boost::system::error_code& ec,
Chris@16 978 std::size_t bytes_transferred, int start = 0)
Chris@16 979 {
Chris@16 980 const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();
Chris@16 981 std::size_t bytes_to_read;
Chris@16 982 switch (start_ = start)
Chris@16 983 {
Chris@16 984 case 1:
Chris@16 985 for (;;)
Chris@16 986 {
Chris@16 987 {
Chris@16 988 // Determine the range of the data to be searched.
Chris@16 989 typedef typename boost::asio::basic_streambuf<
Chris@16 990 Allocator>::const_buffers_type const_buffers_type;
Chris@16 991 typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
Chris@16 992 const_buffers_type buffers = streambuf_.data();
Chris@16 993 iterator begin = iterator::begin(buffers);
Chris@16 994 iterator start_pos = begin + search_position_;
Chris@16 995 iterator end = iterator::end(buffers);
Chris@16 996
Chris@16 997 // Look for a match.
Chris@16 998 std::pair<iterator, bool> result = match_condition_(start_pos, end);
Chris@16 999 if (result.second)
Chris@16 1000 {
Chris@16 1001 // Full match. We're done.
Chris@16 1002 search_position_ = result.first - begin;
Chris@16 1003 bytes_to_read = 0;
Chris@16 1004 }
Chris@16 1005
Chris@16 1006 // No match yet. Check if buffer is full.
Chris@16 1007 else if (streambuf_.size() == streambuf_.max_size())
Chris@16 1008 {
Chris@16 1009 search_position_ = not_found;
Chris@16 1010 bytes_to_read = 0;
Chris@16 1011 }
Chris@16 1012
Chris@16 1013 // Need to read some more data.
Chris@16 1014 else
Chris@16 1015 {
Chris@16 1016 if (result.first != end)
Chris@16 1017 {
Chris@16 1018 // Partial match. Next search needs to start from beginning of
Chris@16 1019 // match.
Chris@16 1020 search_position_ = result.first - begin;
Chris@16 1021 }
Chris@16 1022 else
Chris@16 1023 {
Chris@16 1024 // Next search can start with the new data.
Chris@16 1025 search_position_ = end - begin;
Chris@16 1026 }
Chris@16 1027
Chris@16 1028 bytes_to_read = read_size_helper(streambuf_, 65536);
Chris@16 1029 }
Chris@16 1030 }
Chris@16 1031
Chris@16 1032 // Check if we're done.
Chris@16 1033 if (!start && bytes_to_read == 0)
Chris@16 1034 break;
Chris@16 1035
Chris@16 1036 // Start a new asynchronous read operation to obtain more data.
Chris@16 1037 stream_.async_read_some(streambuf_.prepare(bytes_to_read),
Chris@16 1038 BOOST_ASIO_MOVE_CAST(read_until_match_op)(*this));
Chris@16 1039 return; default:
Chris@16 1040 streambuf_.commit(bytes_transferred);
Chris@16 1041 if (ec || bytes_transferred == 0)
Chris@16 1042 break;
Chris@16 1043 }
Chris@16 1044
Chris@16 1045 const boost::system::error_code result_ec =
Chris@16 1046 (search_position_ == not_found)
Chris@16 1047 ? error::not_found : ec;
Chris@16 1048
Chris@16 1049 const std::size_t result_n =
Chris@16 1050 (ec || search_position_ == not_found)
Chris@16 1051 ? 0 : search_position_;
Chris@16 1052
Chris@16 1053 handler_(result_ec, result_n);
Chris@16 1054 }
Chris@16 1055 }
Chris@16 1056
Chris@16 1057 //private:
Chris@16 1058 AsyncReadStream& stream_;
Chris@16 1059 boost::asio::basic_streambuf<Allocator>& streambuf_;
Chris@16 1060 MatchCondition match_condition_;
Chris@16 1061 int start_;
Chris@16 1062 std::size_t search_position_;
Chris@16 1063 ReadHandler handler_;
Chris@16 1064 };
Chris@16 1065
Chris@16 1066 template <typename AsyncReadStream, typename Allocator,
Chris@16 1067 typename MatchCondition, typename ReadHandler>
Chris@16 1068 inline void* asio_handler_allocate(std::size_t size,
Chris@16 1069 read_until_match_op<AsyncReadStream,
Chris@16 1070 Allocator, MatchCondition, ReadHandler>* this_handler)
Chris@16 1071 {
Chris@16 1072 return boost_asio_handler_alloc_helpers::allocate(
Chris@16 1073 size, this_handler->handler_);
Chris@16 1074 }
Chris@16 1075
Chris@16 1076 template <typename AsyncReadStream, typename Allocator,
Chris@16 1077 typename MatchCondition, typename ReadHandler>
Chris@16 1078 inline void asio_handler_deallocate(void* pointer, std::size_t size,
Chris@16 1079 read_until_match_op<AsyncReadStream,
Chris@16 1080 Allocator, MatchCondition, ReadHandler>* this_handler)
Chris@16 1081 {
Chris@16 1082 boost_asio_handler_alloc_helpers::deallocate(
Chris@16 1083 pointer, size, this_handler->handler_);
Chris@16 1084 }
Chris@16 1085
Chris@16 1086 template <typename AsyncReadStream, typename Allocator,
Chris@16 1087 typename MatchCondition, typename ReadHandler>
Chris@16 1088 inline bool asio_handler_is_continuation(
Chris@16 1089 read_until_match_op<AsyncReadStream,
Chris@16 1090 Allocator, MatchCondition, ReadHandler>* this_handler)
Chris@16 1091 {
Chris@16 1092 return this_handler->start_ == 0 ? true
Chris@16 1093 : boost_asio_handler_cont_helpers::is_continuation(
Chris@16 1094 this_handler->handler_);
Chris@16 1095 }
Chris@16 1096
Chris@16 1097 template <typename Function, typename AsyncReadStream, typename Allocator,
Chris@16 1098 typename MatchCondition, typename ReadHandler>
Chris@16 1099 inline void asio_handler_invoke(Function& function,
Chris@16 1100 read_until_match_op<AsyncReadStream,
Chris@16 1101 Allocator, MatchCondition, ReadHandler>* this_handler)
Chris@16 1102 {
Chris@16 1103 boost_asio_handler_invoke_helpers::invoke(
Chris@16 1104 function, this_handler->handler_);
Chris@16 1105 }
Chris@16 1106
Chris@16 1107 template <typename Function, typename AsyncReadStream, typename Allocator,
Chris@16 1108 typename MatchCondition, typename ReadHandler>
Chris@16 1109 inline void asio_handler_invoke(const Function& function,
Chris@16 1110 read_until_match_op<AsyncReadStream,
Chris@16 1111 Allocator, MatchCondition, ReadHandler>* this_handler)
Chris@16 1112 {
Chris@16 1113 boost_asio_handler_invoke_helpers::invoke(
Chris@16 1114 function, this_handler->handler_);
Chris@16 1115 }
Chris@16 1116 } // namespace detail
Chris@16 1117
Chris@16 1118 template <typename AsyncReadStream, typename Allocator,
Chris@16 1119 typename MatchCondition, typename ReadHandler>
Chris@16 1120 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
Chris@16 1121 void (boost::system::error_code, std::size_t))
Chris@16 1122 async_read_until(AsyncReadStream& s,
Chris@16 1123 boost::asio::basic_streambuf<Allocator>& b,
Chris@16 1124 MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
Chris@16 1125 typename enable_if<is_match_condition<MatchCondition>::value>::type*)
Chris@16 1126 {
Chris@16 1127 // If you get an error on the following line it means that your handler does
Chris@16 1128 // not meet the documented type requirements for a ReadHandler.
Chris@16 1129 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
Chris@16 1130
Chris@16 1131 detail::async_result_init<
Chris@16 1132 ReadHandler, void (boost::system::error_code, std::size_t)> init(
Chris@16 1133 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
Chris@16 1134
Chris@16 1135 detail::read_until_match_op<AsyncReadStream, Allocator,
Chris@16 1136 MatchCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
Chris@16 1137 void (boost::system::error_code, std::size_t))>(
Chris@16 1138 s, b, match_condition, init.handler)(
Chris@16 1139 boost::system::error_code(), 0, 1);
Chris@16 1140
Chris@16 1141 return init.result.get();
Chris@16 1142 }
Chris@16 1143
Chris@16 1144 } // namespace asio
Chris@16 1145 } // namespace boost
Chris@16 1146
Chris@16 1147 #include <boost/asio/detail/pop_options.hpp>
Chris@16 1148
Chris@16 1149 #endif // BOOST_ASIO_IMPL_READ_UNTIL_HPP