@@ -2874,7 +2874,8 @@ inline const char *status_message(int status) {
28742874}
28752875
28762876inline bool can_compress_content_type (const std::string &content_type) {
2877- return (!content_type.find (" text/" ) && content_type != " text/event-stream" ) ||
2877+ return (!content_type.rfind (" text/" , 0 ) &&
2878+ content_type != " text/event-stream" ) ||
28782879 content_type == " image/svg+xml" ||
28792880 content_type == " application/javascript" ||
28802881 content_type == " application/json" ||
@@ -3681,17 +3682,15 @@ class MultipartFormDataParser {
36813682 static const std::string dash_ = " --" ;
36823683 static const std::string crlf_ = " \r\n " ;
36833684
3684- buf_. append (buf, n); // TODO: performance improvement
3685+ buf_append (buf, n);
36853686
3686- while (!buf_. empty () ) {
3687+ while (buf_size () > 0 ) {
36873688 switch (state_) {
36883689 case 0 : { // Initial boundary
36893690 auto pattern = dash_ + boundary_ + crlf_;
3690- if (pattern.size () > buf_.size ()) { return true ; }
3691- auto pos = buf_.find (pattern);
3692- if (pos != 0 ) { return false ; }
3693- buf_.erase (0 , pattern.size ());
3694- off_ += pattern.size ();
3691+ if (pattern.size () > buf_size ()) { return true ; }
3692+ if (!buf_start_with (pattern)) { return false ; }
3693+ buf_erase (pattern.size ());
36953694 state_ = 1 ;
36963695 break ;
36973696 }
@@ -3701,22 +3700,21 @@ class MultipartFormDataParser {
37013700 break ;
37023701 }
37033702 case 2 : { // Headers
3704- auto pos = buf_. find (crlf_);
3705- while (pos != std::string::npos ) {
3703+ auto pos = buf_find (crlf_);
3704+ while (pos < buf_size () ) {
37063705 // Empty line
37073706 if (pos == 0 ) {
37083707 if (!header_callback (file_)) {
37093708 is_valid_ = false ;
37103709 return false ;
37113710 }
3712- buf_.erase (0 , crlf_.size ());
3713- off_ += crlf_.size ();
3711+ buf_erase (crlf_.size ());
37143712 state_ = 3 ;
37153713 break ;
37163714 }
37173715
37183716 static const std::string header_name = " content-type:" ;
3719- const auto header = buf_. substr ( 0 , pos);
3717+ const auto header = buf_head ( pos);
37203718 if (start_with_case_ignore (header, header_name)) {
37213719 file_.content_type = trim_copy (header.substr (header_name.size ()));
37223720 } else {
@@ -3727,66 +3725,60 @@ class MultipartFormDataParser {
37273725 }
37283726 }
37293727
3730- buf_.erase (0 , pos + crlf_.size ());
3731- off_ += pos + crlf_.size ();
3732- pos = buf_.find (crlf_);
3728+ buf_erase (pos + crlf_.size ());
3729+ pos = buf_find (crlf_);
37333730 }
37343731 if (state_ != 3 ) { return true ; }
37353732 break ;
37363733 }
37373734 case 3 : { // Body
37383735 {
37393736 auto pattern = crlf_ + dash_;
3740- if (pattern.size () > buf_. size ()) { return true ; }
3737+ if (pattern.size () > buf_size ()) { return true ; }
37413738
3742- auto pos = find_string (buf_, pattern);
3739+ auto pos = buf_find ( pattern);
37433740
3744- if (!content_callback (buf_. data (), pos)) {
3741+ if (!content_callback (buf_data (), pos)) {
37453742 is_valid_ = false ;
37463743 return false ;
37473744 }
37483745
3749- off_ += pos;
3750- buf_.erase (0 , pos);
3746+ buf_erase (pos);
37513747 }
37523748 {
37533749 auto pattern = crlf_ + dash_ + boundary_;
3754- if (pattern.size () > buf_. size ()) { return true ; }
3750+ if (pattern.size () > buf_size ()) { return true ; }
37553751
3756- auto pos = buf_. find (pattern);
3757- if (pos != std::string::npos ) {
3758- if (!content_callback (buf_. data (), pos)) {
3752+ auto pos = buf_find (pattern);
3753+ if (pos < buf_size () ) {
3754+ if (!content_callback (buf_data (), pos)) {
37593755 is_valid_ = false ;
37603756 return false ;
37613757 }
37623758
3763- off_ += pos + pattern.size ();
3764- buf_.erase (0 , pos + pattern.size ());
3759+ buf_erase (pos + pattern.size ());
37653760 state_ = 4 ;
37663761 } else {
3767- if (!content_callback (buf_. data (), pattern.size ())) {
3762+ if (!content_callback (buf_data (), pattern.size ())) {
37683763 is_valid_ = false ;
37693764 return false ;
37703765 }
37713766
3772- off_ += pattern.size ();
3773- buf_.erase (0 , pattern.size ());
3767+ buf_erase (pattern.size ());
37743768 }
37753769 }
37763770 break ;
37773771 }
37783772 case 4 : { // Boundary
3779- if (crlf_.size () > buf_.size ()) { return true ; }
3780- if (buf_.compare (0 , crlf_.size (), crlf_) == 0 ) {
3781- buf_.erase (0 , crlf_.size ());
3782- off_ += crlf_.size ();
3773+ if (crlf_.size () > buf_size ()) { return true ; }
3774+ if (buf_start_with (crlf_)) {
3775+ buf_erase (crlf_.size ());
37833776 state_ = 1 ;
37843777 } else {
37853778 auto pattern = dash_ + crlf_;
3786- if (pattern.size () > buf_.size ()) { return true ; }
3787- if (buf_.compare (0 , pattern.size (), pattern) == 0 ) {
3788- buf_.erase (0 , pattern.size ());
3789- off_ += pattern.size ();
3779+ if (pattern.size () > buf_size ()) { return true ; }
3780+ if (buf_start_with (pattern)) {
3781+ buf_erase (pattern.size ());
37903782 is_valid_ = true ;
37913783 state_ = 5 ;
37923784 } else {
@@ -3821,41 +3813,80 @@ class MultipartFormDataParser {
38213813 return true ;
38223814 }
38233815
3824- bool start_with (const std::string &a, size_t off,
3816+ std::string boundary_;
3817+
3818+ size_t state_ = 0 ;
3819+ bool is_valid_ = false ;
3820+ MultipartFormData file_;
3821+
3822+ // Buffer
3823+ bool start_with (const std::string &a, size_t spos, size_t epos,
38253824 const std::string &b) const {
3826- if (a. size () - off < b.size ()) { return false ; }
3825+ if (epos - spos < b.size ()) { return false ; }
38273826 for (size_t i = 0 ; i < b.size (); i++) {
3828- if (a[i + off ] != b[i]) { return false ; }
3827+ if (a[i + spos ] != b[i]) { return false ; }
38293828 }
38303829 return true ;
38313830 }
38323831
3833- size_t find_string (const std::string &s, const std::string &pattern) const {
3834- auto c = pattern.front ();
3832+ size_t buf_size () const { return buf_epos_ - buf_spos_; }
38353833
3836- size_t off = 0 ;
3837- while (off < s.size ()) {
3838- auto pos = s.find (c, off);
3839- if (pos == std::string::npos) { return s.size (); }
3834+ const char *buf_data () const { return &buf_[buf_spos_]; }
38403835
3841- auto rem = s.size () - pos;
3842- if (pattern.size () > rem) { return pos; }
3836+ std::string buf_head (size_t l) const { return buf_.substr (buf_spos_, l); }
38433837
3844- if (start_with (s, pos, pattern)) { return pos; }
3838+ bool buf_start_with (const std::string &s) const {
3839+ return start_with (buf_, buf_spos_, buf_epos_, s);
3840+ }
3841+
3842+ size_t buf_find (const std::string &s) const {
3843+ auto c = s.front ();
3844+
3845+ size_t off = buf_spos_;
3846+ while (off < buf_epos_) {
3847+ auto pos = off;
3848+ while (true ) {
3849+ if (pos == buf_epos_) { return buf_size (); }
3850+ if (buf_[pos] == c) { break ; }
3851+ pos++;
3852+ }
3853+
3854+ auto remaining_size = buf_epos_ - pos;
3855+ if (s.size () > remaining_size) { return buf_size (); }
3856+
3857+ if (start_with (buf_, pos, buf_epos_, s)) { return pos - buf_spos_; }
38453858
38463859 off = pos + 1 ;
38473860 }
38483861
3849- return s. size ();
3862+ return buf_size ();
38503863 }
38513864
3852- std::string boundary_;
3865+ void buf_append (const char *data, size_t n) {
3866+ auto remaining_size = buf_size ();
3867+ if (remaining_size > 0 ) {
3868+ for (size_t i = 0 ; i < remaining_size; i++) {
3869+ buf_[i] = buf_[buf_spos_ + i];
3870+ }
3871+ }
3872+ buf_spos_ = 0 ;
3873+ buf_epos_ = remaining_size;
3874+
3875+ if (remaining_size + n > buf_.size ()) {
3876+ buf_.resize (remaining_size + n);
3877+ }
3878+
3879+ for (size_t i = 0 ; i < n; i++) {
3880+ buf_[buf_epos_ + i] = data[i];
3881+ }
3882+ buf_epos_ += n;
3883+ }
3884+
3885+ void buf_erase (size_t size) { buf_spos_ += size; }
38533886
38543887 std::string buf_;
3855- size_t state_ = 0 ;
3856- bool is_valid_ = false ;
3857- size_t off_ = 0 ;
3858- MultipartFormData file_;
3888+ size_t buf_spos_ = 0 ;
3889+ size_t buf_epos_ = 0 ;
38593890};
38603891
38613892inline std::string to_lower (const char *beg, const char *end) {
@@ -4318,7 +4349,7 @@ inline size_t Request::get_param_value_count(const char *key) const {
43184349
43194350inline bool Request::is_multipart_form_data () const {
43204351 const auto &content_type = get_header_value (" Content-Type" );
4321- return !content_type.find (" multipart/form-data" );
4352+ return !content_type.rfind (" multipart/form-data" , 0 );
43224353}
43234354
43244355inline bool Request::has_file (const char *key) const {
@@ -5122,9 +5153,7 @@ Server::create_server_socket(const char *host, int port, int socket_flags,
51225153 if (::bind (sock, ai.ai_addr , static_cast <socklen_t >(ai.ai_addrlen ))) {
51235154 return false ;
51245155 }
5125- if (::listen (sock, CPPHTTPLIB_LISTEN_BACKLOG)) {
5126- return false ;
5127- }
5156+ if (::listen (sock, CPPHTTPLIB_LISTEN_BACKLOG)) { return false ; }
51285157 return true ;
51295158 });
51305159}
0 commit comments