00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef ASIO_READ_UNTIL_IPP
00012 #define ASIO_READ_UNTIL_IPP
00013
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
00015 # pragma once
00016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
00017
00018 #include "asio/detail/push_options.hpp"
00019
00020 #include "asio/detail/push_options.hpp"
00021 #include <algorithm>
00022 #include <limits>
00023 #include <string>
00024 #include <utility>
00025 #include "asio/detail/pop_options.hpp"
00026
00027 #include "asio/buffer.hpp"
00028 #include "asio/detail/bind_handler.hpp"
00029 #include "asio/detail/const_buffers_iterator.hpp"
00030 #include "asio/detail/handler_alloc_helpers.hpp"
00031 #include "asio/detail/handler_invoke_helpers.hpp"
00032 #include "asio/detail/throw_error.hpp"
00033
00034 namespace asio {
00035
00036 template <typename SyncReadStream, typename Allocator>
00037 inline std::size_t read_until(SyncReadStream& s,
00038 asio::basic_streambuf<Allocator>& b, char delim)
00039 {
00040 asio::error_code ec;
00041 std::size_t bytes_transferred = read_until(s, b, delim, ec);
00042 asio::detail::throw_error(ec);
00043 return bytes_transferred;
00044 }
00045
00046 template <typename SyncReadStream, typename Allocator>
00047 std::size_t read_until(SyncReadStream& s,
00048 asio::basic_streambuf<Allocator>& b, char delim,
00049 asio::error_code& ec)
00050 {
00051 std::size_t next_search_start = 0;
00052 for (;;)
00053 {
00054
00055 typedef typename asio::basic_streambuf<
00056 Allocator>::const_buffers_type const_buffers_type;
00057 typedef asio::detail::const_buffers_iterator<
00058 const_buffers_type> iterator;
00059 const_buffers_type buffers = b.data();
00060 iterator begin(buffers, next_search_start);
00061 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00062
00063
00064 iterator iter = std::find(begin, end, delim);
00065 if (iter != end)
00066 {
00067
00068 ec = asio::error_code();
00069 return iter.position() + 1;
00070 }
00071 else
00072 {
00073
00074 next_search_start = end.position();
00075 }
00076
00077
00078 if (b.size() == b.max_size())
00079 {
00080 ec = error::not_found;
00081 return 0;
00082 }
00083
00084
00085 std::size_t bytes_available =
00086 std::min<std::size_t>(512, b.max_size() - b.size());
00087 b.commit(s.read_some(b.prepare(bytes_available), ec));
00088 if (ec)
00089 return 0;
00090 }
00091 }
00092
00093 template <typename SyncReadStream, typename Allocator>
00094 inline std::size_t read_until(SyncReadStream& s,
00095 asio::basic_streambuf<Allocator>& b, const std::string& delim)
00096 {
00097 asio::error_code ec;
00098 std::size_t bytes_transferred = read_until(s, b, delim, ec);
00099 asio::detail::throw_error(ec);
00100 return bytes_transferred;
00101 }
00102
00103 namespace detail
00104 {
00105
00106
00107
00108
00109
00110
00111 template <typename Iterator1, typename Iterator2>
00112 std::pair<Iterator1, bool> partial_search(
00113 Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)
00114 {
00115 for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)
00116 {
00117 Iterator1 test_iter1 = iter1;
00118 Iterator2 test_iter2 = first2;
00119 for (;; ++test_iter1, ++test_iter2)
00120 {
00121 if (test_iter2 == last2)
00122 return std::make_pair(iter1, true);
00123 if (test_iter1 == last1)
00124 {
00125 if (test_iter2 != first2)
00126 return std::make_pair(iter1, false);
00127 else
00128 break;
00129 }
00130 if (*test_iter1 != *test_iter2)
00131 break;
00132 }
00133 }
00134 return std::make_pair(last1, false);
00135 }
00136 }
00137
00138 template <typename SyncReadStream, typename Allocator>
00139 std::size_t read_until(SyncReadStream& s,
00140 asio::basic_streambuf<Allocator>& b, const std::string& delim,
00141 asio::error_code& ec)
00142 {
00143 std::size_t next_search_start = 0;
00144 for (;;)
00145 {
00146
00147 typedef typename asio::basic_streambuf<
00148 Allocator>::const_buffers_type const_buffers_type;
00149 typedef asio::detail::const_buffers_iterator<
00150 const_buffers_type> iterator;
00151 const_buffers_type buffers = b.data();
00152 iterator begin(buffers, next_search_start);
00153 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00154
00155
00156 std::pair<iterator, bool> result = asio::detail::partial_search(
00157 begin, end, delim.begin(), delim.end());
00158 if (result.first != end)
00159 {
00160 if (result.second)
00161 {
00162
00163 ec = asio::error_code();
00164 return result.first.position() + delim.length();
00165 }
00166 else
00167 {
00168
00169 next_search_start = result.first.position();
00170 }
00171 }
00172 else
00173 {
00174
00175 next_search_start = end.position();
00176 }
00177
00178
00179 if (b.size() == b.max_size())
00180 {
00181 ec = error::not_found;
00182 return 0;
00183 }
00184
00185
00186 std::size_t bytes_available =
00187 std::min<std::size_t>(512, b.max_size() - b.size());
00188 b.commit(s.read_some(b.prepare(bytes_available), ec));
00189 if (ec)
00190 return 0;
00191 }
00192 }
00193
00194 template <typename SyncReadStream, typename Allocator>
00195 inline std::size_t read_until(SyncReadStream& s,
00196 asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
00197 {
00198 asio::error_code ec;
00199 std::size_t bytes_transferred = read_until(s, b, expr, ec);
00200 asio::detail::throw_error(ec);
00201 return bytes_transferred;
00202 }
00203
00204 template <typename SyncReadStream, typename Allocator>
00205 std::size_t read_until(SyncReadStream& s,
00206 asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
00207 asio::error_code& ec)
00208 {
00209 std::size_t next_search_start = 0;
00210 for (;;)
00211 {
00212
00213 typedef typename asio::basic_streambuf<
00214 Allocator>::const_buffers_type const_buffers_type;
00215 typedef asio::detail::const_buffers_iterator<
00216 const_buffers_type> iterator;
00217 const_buffers_type buffers = b.data();
00218 iterator begin(buffers, next_search_start);
00219 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00220
00221
00222 boost::match_results<iterator> match_results;
00223 if (boost::regex_search(begin, end, match_results, expr,
00224 boost::match_default | boost::match_partial))
00225 {
00226 if (match_results[0].matched)
00227 {
00228
00229 ec = asio::error_code();
00230 return match_results[0].second.position();
00231 }
00232 else
00233 {
00234
00235 next_search_start = match_results[0].first.position();
00236 }
00237 }
00238 else
00239 {
00240
00241 next_search_start = end.position();
00242 }
00243
00244
00245 if (b.size() == b.max_size())
00246 {
00247 ec = error::not_found;
00248 return 0;
00249 }
00250
00251
00252 std::size_t bytes_available =
00253 std::min<std::size_t>(512, b.max_size() - b.size());
00254 b.commit(s.read_some(b.prepare(bytes_available), ec));
00255 if (ec)
00256 return 0;
00257 }
00258 }
00259
00260 namespace detail
00261 {
00262 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00263 class read_until_delim_handler
00264 {
00265 public:
00266 read_until_delim_handler(AsyncReadStream& stream,
00267 asio::basic_streambuf<Allocator>& streambuf, char delim,
00268 std::size_t next_search_start, ReadHandler handler)
00269 : stream_(stream),
00270 streambuf_(streambuf),
00271 delim_(delim),
00272 next_search_start_(next_search_start),
00273 handler_(handler)
00274 {
00275 }
00276
00277 void operator()(const asio::error_code& ec,
00278 std::size_t bytes_transferred)
00279 {
00280
00281 if (ec)
00282 {
00283 std::size_t bytes = 0;
00284 handler_(ec, bytes);
00285 return;
00286 }
00287
00288
00289 streambuf_.commit(bytes_transferred);
00290
00291
00292 typedef typename asio::basic_streambuf<
00293 Allocator>::const_buffers_type const_buffers_type;
00294 typedef asio::detail::const_buffers_iterator<
00295 const_buffers_type> iterator;
00296 const_buffers_type buffers = streambuf_.data();
00297 iterator begin(buffers, next_search_start_);
00298 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00299
00300
00301 iterator iter = std::find(begin, end, delim_);
00302 if (iter != end)
00303 {
00304
00305 std::size_t bytes = iter.position() + 1;
00306 handler_(ec, bytes);
00307 return;
00308 }
00309
00310
00311 if (streambuf_.size() == streambuf_.max_size())
00312 {
00313 std::size_t bytes = 0;
00314 handler_(error::not_found, bytes);
00315 return;
00316 }
00317
00318
00319 next_search_start_ = end.position();
00320
00321
00322 std::size_t bytes_available =
00323 std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
00324 stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
00325 }
00326
00327
00328 AsyncReadStream& stream_;
00329 asio::basic_streambuf<Allocator>& streambuf_;
00330 char delim_;
00331 std::size_t next_search_start_;
00332 ReadHandler handler_;
00333 };
00334
00335 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00336 inline void* asio_handler_allocate(std::size_t size,
00337 read_until_delim_handler<AsyncReadStream,
00338 Allocator, ReadHandler>* this_handler)
00339 {
00340 return asio_handler_alloc_helpers::allocate(
00341 size, &this_handler->handler_);
00342 }
00343
00344 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00345 inline void asio_handler_deallocate(void* pointer, std::size_t size,
00346 read_until_delim_handler<AsyncReadStream,
00347 Allocator, ReadHandler>* this_handler)
00348 {
00349 asio_handler_alloc_helpers::deallocate(
00350 pointer, size, &this_handler->handler_);
00351 }
00352
00353 template <typename Function, typename AsyncReadStream, typename Allocator,
00354 typename ReadHandler>
00355 inline void asio_handler_invoke(const Function& function,
00356 read_until_delim_handler<AsyncReadStream,
00357 Allocator, ReadHandler>* this_handler)
00358 {
00359 asio_handler_invoke_helpers::invoke(
00360 function, &this_handler->handler_);
00361 }
00362 }
00363
00364 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00365 void async_read_until(AsyncReadStream& s,
00366 asio::basic_streambuf<Allocator>& b, char delim, ReadHandler handler)
00367 {
00368
00369 typedef typename asio::basic_streambuf<
00370 Allocator>::const_buffers_type const_buffers_type;
00371 typedef asio::detail::const_buffers_iterator<
00372 const_buffers_type> iterator;
00373 const_buffers_type buffers = b.data();
00374 iterator begin(buffers, 0);
00375 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00376
00377
00378 iterator iter = std::find(begin, end, delim);
00379 if (iter != end)
00380 {
00381
00382 asio::error_code ec;
00383 std::size_t bytes = iter.position() + 1;
00384 s.io_service().post(detail::bind_handler(handler, ec, bytes));
00385 return;
00386 }
00387
00388
00389 if (b.size() == b.max_size())
00390 {
00391 s.io_service().post(detail::bind_handler(handler, error::not_found, 0));
00392 return;
00393 }
00394
00395
00396 std::size_t bytes_available =
00397 std::min<std::size_t>(512, b.max_size() - b.size());
00398 s.async_read_some(b.prepare(bytes_available),
00399 detail::read_until_delim_handler<AsyncReadStream, Allocator, ReadHandler>(
00400 s, b, delim, end.position(), handler));
00401 }
00402
00403 namespace detail
00404 {
00405 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00406 class read_until_delim_string_handler
00407 {
00408 public:
00409 read_until_delim_string_handler(AsyncReadStream& stream,
00410 asio::basic_streambuf<Allocator>& streambuf,
00411 const std::string& delim, std::size_t next_search_start,
00412 ReadHandler handler)
00413 : stream_(stream),
00414 streambuf_(streambuf),
00415 delim_(delim),
00416 next_search_start_(next_search_start),
00417 handler_(handler)
00418 {
00419 }
00420
00421 void operator()(const asio::error_code& ec,
00422 std::size_t bytes_transferred)
00423 {
00424
00425 if (ec)
00426 {
00427 std::size_t bytes = 0;
00428 handler_(ec, bytes);
00429 return;
00430 }
00431
00432
00433 streambuf_.commit(bytes_transferred);
00434
00435
00436 typedef typename asio::basic_streambuf<
00437 Allocator>::const_buffers_type const_buffers_type;
00438 typedef asio::detail::const_buffers_iterator<
00439 const_buffers_type> iterator;
00440 const_buffers_type buffers = streambuf_.data();
00441 iterator begin(buffers, next_search_start_);
00442 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00443
00444
00445 std::pair<iterator, bool> result = asio::detail::partial_search(
00446 begin, end, delim_.begin(), delim_.end());
00447 if (result.first != end)
00448 {
00449 if (result.second)
00450 {
00451
00452 std::size_t bytes = result.first.position() + delim_.length();
00453 handler_(ec, bytes);
00454 return;
00455 }
00456 else
00457 {
00458
00459 next_search_start_ = result.first.position();
00460 }
00461 }
00462 else
00463 {
00464
00465 next_search_start_ = end.position();
00466 }
00467
00468
00469 if (streambuf_.size() == streambuf_.max_size())
00470 {
00471 std::size_t bytes = 0;
00472 handler_(error::not_found, bytes);
00473 return;
00474 }
00475
00476
00477 std::size_t bytes_available =
00478 std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
00479 stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
00480 }
00481
00482
00483 AsyncReadStream& stream_;
00484 asio::basic_streambuf<Allocator>& streambuf_;
00485 std::string delim_;
00486 std::size_t next_search_start_;
00487 ReadHandler handler_;
00488 };
00489
00490 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00491 inline void* asio_handler_allocate(std::size_t size,
00492 read_until_delim_string_handler<AsyncReadStream,
00493 Allocator, ReadHandler>* this_handler)
00494 {
00495 return asio_handler_alloc_helpers::allocate(
00496 size, &this_handler->handler_);
00497 }
00498
00499 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00500 inline void asio_handler_deallocate(void* pointer, std::size_t size,
00501 read_until_delim_string_handler<AsyncReadStream,
00502 Allocator, ReadHandler>* this_handler)
00503 {
00504 asio_handler_alloc_helpers::deallocate(
00505 pointer, size, &this_handler->handler_);
00506 }
00507
00508 template <typename Function, typename AsyncReadStream,
00509 typename Allocator, typename ReadHandler>
00510 inline void asio_handler_invoke(const Function& function,
00511 read_until_delim_string_handler<AsyncReadStream,
00512 Allocator, ReadHandler>* this_handler)
00513 {
00514 asio_handler_invoke_helpers::invoke(
00515 function, &this_handler->handler_);
00516 }
00517 }
00518
00519 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00520 void async_read_until(AsyncReadStream& s,
00521 asio::basic_streambuf<Allocator>& b, const std::string& delim,
00522 ReadHandler handler)
00523 {
00524
00525 typedef typename asio::basic_streambuf<
00526 Allocator>::const_buffers_type const_buffers_type;
00527 typedef asio::detail::const_buffers_iterator<
00528 const_buffers_type> iterator;
00529 const_buffers_type buffers = b.data();
00530 iterator begin(buffers, 0);
00531 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00532
00533
00534 std::size_t next_search_start;
00535 std::pair<iterator, bool> result = asio::detail::partial_search(
00536 begin, end, delim.begin(), delim.end());
00537 if (result.first != end)
00538 {
00539 if (result.second)
00540 {
00541
00542 asio::error_code ec;
00543 std::size_t bytes = result.first.position() + delim.length();
00544 s.io_service().post(detail::bind_handler(handler, ec, bytes));
00545 return;
00546 }
00547 else
00548 {
00549
00550 next_search_start = result.first.position();
00551 }
00552 }
00553 else
00554 {
00555
00556 next_search_start = end.position();
00557 }
00558
00559
00560 if (b.size() == b.max_size())
00561 {
00562 s.io_service().post(detail::bind_handler(handler, error::not_found, 0));
00563 return;
00564 }
00565
00566
00567 std::size_t bytes_available =
00568 std::min<std::size_t>(512, b.max_size() - b.size());
00569 s.async_read_some(b.prepare(bytes_available),
00570 detail::read_until_delim_string_handler<
00571 AsyncReadStream, Allocator, ReadHandler>(
00572 s, b, delim, next_search_start, handler));
00573 }
00574
00575 namespace detail
00576 {
00577 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00578 class read_until_expr_handler
00579 {
00580 public:
00581 read_until_expr_handler(AsyncReadStream& stream,
00582 asio::basic_streambuf<Allocator>& streambuf,
00583 const boost::regex& expr, std::size_t next_search_start,
00584 ReadHandler handler)
00585 : stream_(stream),
00586 streambuf_(streambuf),
00587 expr_(expr),
00588 next_search_start_(next_search_start),
00589 handler_(handler)
00590 {
00591 }
00592
00593 void operator()(const asio::error_code& ec,
00594 std::size_t bytes_transferred)
00595 {
00596
00597 if (ec)
00598 {
00599 std::size_t bytes = 0;
00600 handler_(ec, bytes);
00601 return;
00602 }
00603
00604
00605 streambuf_.commit(bytes_transferred);
00606
00607
00608 typedef typename asio::basic_streambuf<
00609 Allocator>::const_buffers_type const_buffers_type;
00610 typedef asio::detail::const_buffers_iterator<
00611 const_buffers_type> iterator;
00612 const_buffers_type buffers = streambuf_.data();
00613 iterator begin(buffers, next_search_start_);
00614 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00615
00616
00617 boost::match_results<iterator> match_results;
00618 if (boost::regex_search(begin, end, match_results, expr_,
00619 boost::match_default | boost::match_partial))
00620 {
00621 if (match_results[0].matched)
00622 {
00623
00624 std::size_t bytes = match_results[0].second.position();
00625 handler_(ec, bytes);
00626 return;
00627 }
00628 else
00629 {
00630
00631 next_search_start_ = match_results[0].first.position();
00632 }
00633 }
00634 else
00635 {
00636
00637 next_search_start_ = end.position();
00638 }
00639
00640
00641 if (streambuf_.size() == streambuf_.max_size())
00642 {
00643 std::size_t bytes = 0;
00644 handler_(error::not_found, bytes);
00645 return;
00646 }
00647
00648
00649 std::size_t bytes_available =
00650 std::min<std::size_t>(512, streambuf_.max_size() - streambuf_.size());
00651 stream_.async_read_some(streambuf_.prepare(bytes_available), *this);
00652 }
00653
00654
00655 AsyncReadStream& stream_;
00656 asio::basic_streambuf<Allocator>& streambuf_;
00657 boost::regex expr_;
00658 std::size_t next_search_start_;
00659 ReadHandler handler_;
00660 };
00661
00662 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00663 inline void* asio_handler_allocate(std::size_t size,
00664 read_until_expr_handler<AsyncReadStream,
00665 Allocator, ReadHandler>* this_handler)
00666 {
00667 return asio_handler_alloc_helpers::allocate(
00668 size, &this_handler->handler_);
00669 }
00670
00671 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00672 inline void asio_handler_deallocate(void* pointer, std::size_t size,
00673 read_until_expr_handler<AsyncReadStream,
00674 Allocator, ReadHandler>* this_handler)
00675 {
00676 asio_handler_alloc_helpers::deallocate(
00677 pointer, size, &this_handler->handler_);
00678 }
00679
00680 template <typename Function, typename AsyncReadStream, typename Allocator,
00681 typename ReadHandler>
00682 inline void asio_handler_invoke(const Function& function,
00683 read_until_expr_handler<AsyncReadStream,
00684 Allocator, ReadHandler>* this_handler)
00685 {
00686 asio_handler_invoke_helpers::invoke(
00687 function, &this_handler->handler_);
00688 }
00689 }
00690
00691 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
00692 void async_read_until(AsyncReadStream& s,
00693 asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
00694 ReadHandler handler)
00695 {
00696
00697 typedef typename asio::basic_streambuf<
00698 Allocator>::const_buffers_type const_buffers_type;
00699 typedef asio::detail::const_buffers_iterator<
00700 const_buffers_type> iterator;
00701 const_buffers_type buffers = b.data();
00702 iterator begin(buffers, 0);
00703 iterator end(buffers, (std::numeric_limits<std::size_t>::max)());
00704
00705
00706 std::size_t next_search_start;
00707 boost::match_results<iterator> match_results;
00708 if (boost::regex_search(begin, end, match_results, expr,
00709 boost::match_default | boost::match_partial))
00710 {
00711 if (match_results[0].matched)
00712 {
00713
00714 asio::error_code ec;
00715 std::size_t bytes = match_results[0].second.position();
00716 s.io_service().post(detail::bind_handler(handler, ec, bytes));
00717 return;
00718 }
00719 else
00720 {
00721
00722 next_search_start = match_results[0].first.position();
00723 }
00724 }
00725 else
00726 {
00727
00728 next_search_start = end.position();
00729 }
00730
00731
00732 if (b.size() == b.max_size())
00733 {
00734 s.io_service().post(detail::bind_handler(handler, error::not_found, 0));
00735 return;
00736 }
00737
00738
00739 std::size_t bytes_available =
00740 std::min<std::size_t>(512, b.max_size() - b.size());
00741 s.async_read_some(b.prepare(bytes_available),
00742 detail::read_until_expr_handler<AsyncReadStream, Allocator, ReadHandler>(
00743 s, b, expr, next_search_start, handler));
00744 }
00745
00746 }
00747
00748 #include "asio/detail/pop_options.hpp"
00749
00750 #endif // ASIO_READ_UNTIL_IPP