forked from boostorg/beast
		
	
		
			
				
	
	
		
			338 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			338 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//------------------------------------------------------------------------------
 | 
						|
/*
 | 
						|
    This file is part of Beast: https://github.com/vinniefalco/Beast
 | 
						|
    Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
 | 
						|
 | 
						|
    Permission to use, copy, modify, and/or distribute this software for any
 | 
						|
    purpose  with  or without fee is hereby granted, provided that the above
 | 
						|
    copyright notice and this permission notice appear in all copies.
 | 
						|
 | 
						|
    THE  SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
						|
    WITH  REGARD  TO  THIS  SOFTWARE  INCLUDING  ALL  IMPLIED  WARRANTIES  OF
 | 
						|
    MERCHANTABILITY  AND  FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
						|
    ANY  SPECIAL ,  DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
						|
    WHATSOEVER  RESULTING  FROM  LOSS  OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
						|
    ACTION  OF  CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
						|
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
						|
*/
 | 
						|
//==============================================================================
 | 
						|
 | 
						|
#ifndef BEAST_WEBSOCKET_STATIC_STRING_HPP
 | 
						|
#define BEAST_WEBSOCKET_STATIC_STRING_HPP
 | 
						|
 | 
						|
#include <algorithm>
 | 
						|
#include <array>
 | 
						|
#include <cstdint>
 | 
						|
#include <iterator>
 | 
						|
#include <stdexcept>
 | 
						|
#include <string>
 | 
						|
 | 
						|
namespace beast {
 | 
						|
namespace websocket {
 | 
						|
 | 
						|
/** A string with a fixed-size storage area.
 | 
						|
 | 
						|
    `static_string` objects behave like `std::string` except that
 | 
						|
    the storage is not dynamically allocated but rather fixed in
 | 
						|
    size.
 | 
						|
 | 
						|
    These strings offer performance advantages when a protocol
 | 
						|
    imposes a natural small upper limit on the size of a value.
 | 
						|
*/
 | 
						|
template<std::size_t N, class CharT,
 | 
						|
    class Traits = std::char_traits<CharT>>
 | 
						|
class static_string
 | 
						|
{
 | 
						|
    std::size_t n_;
 | 
						|
    std::array<CharT, N+1> s_;
 | 
						|
 | 
						|
public:
 | 
						|
    using traits_type = Traits;
 | 
						|
    using value_type = typename Traits::char_type;
 | 
						|
    using size_type = std::size_t;
 | 
						|
    using difference_type = std::ptrdiff_t;
 | 
						|
    using pointer = value_type*;
 | 
						|
    using reference = value_type&;
 | 
						|
    using const_pointer = value_type const*;
 | 
						|
    using const_reference = value_type const&;
 | 
						|
    using iterator = value_type*;
 | 
						|
    using const_iterator = value_type const*;
 | 
						|
    using reverse_iterator =
 | 
						|
        std::reverse_iterator<iterator>;
 | 
						|
    using const_reverse_iterator =
 | 
						|
        std::reverse_iterator<const_iterator>;
 | 
						|
 | 
						|
    static_string()
 | 
						|
    {
 | 
						|
        resize(0);
 | 
						|
    }
 | 
						|
 | 
						|
    static_string(static_string const& s)
 | 
						|
        : n_(s.n_)
 | 
						|
    {
 | 
						|
        std::copy(&s.s_[0], &s.s_[0]+s.n_+1, &s_[0]);
 | 
						|
    }
 | 
						|
 | 
						|
    static_string&
 | 
						|
    operator=(static_string const& s)
 | 
						|
    {
 | 
						|
        n_ = s.n_;
 | 
						|
        std::copy(&s.s_[0], &s.s_[0]+s.n_+1, &s_[0]);
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    static_string(CharT const* s)
 | 
						|
    {
 | 
						|
        assign(s);
 | 
						|
    }
 | 
						|
 | 
						|
    static_string& operator=(CharT const* s)
 | 
						|
    {
 | 
						|
        assign(s);
 | 
						|
        return *this;
 | 
						|
    }
 | 
						|
 | 
						|
    reference
 | 
						|
    at(size_type pos)
 | 
						|
    {
 | 
						|
        if(pos >= n_)
 | 
						|
            throw std::out_of_range("static_string::at");
 | 
						|
        return s_[pos];
 | 
						|
    }
 | 
						|
 | 
						|
    const_reference
 | 
						|
    at(size_type pos) const
 | 
						|
    {
 | 
						|
        if(pos >= n_)
 | 
						|
            throw std::out_of_range("static_string::at");
 | 
						|
        return s_[pos];
 | 
						|
    }
 | 
						|
 | 
						|
    reference
 | 
						|
    operator[](size_type pos);
 | 
						|
 | 
						|
    const_reference
 | 
						|
    operator[](size_type pos) const;
 | 
						|
 | 
						|
    CharT&
 | 
						|
    front()
 | 
						|
    {
 | 
						|
        return s_[0];
 | 
						|
    }
 | 
						|
 | 
						|
    CharT const&
 | 
						|
    front() const
 | 
						|
    {
 | 
						|
        return s_[0];
 | 
						|
    }
 | 
						|
 | 
						|
    CharT&
 | 
						|
    back()
 | 
						|
    {
 | 
						|
        return s_[n_-1];
 | 
						|
    }
 | 
						|
 | 
						|
    CharT const&
 | 
						|
    back() const
 | 
						|
    {
 | 
						|
        return s_[n_-1];
 | 
						|
    }
 | 
						|
 | 
						|
    CharT*
 | 
						|
    data()
 | 
						|
    {
 | 
						|
        return &s_[0];
 | 
						|
    }
 | 
						|
 | 
						|
    CharT const*
 | 
						|
    data() const
 | 
						|
    {
 | 
						|
        return &s_[0];
 | 
						|
    }
 | 
						|
 | 
						|
    CharT const*
 | 
						|
    c_str() const
 | 
						|
    {
 | 
						|
        s_[n_] = 0;
 | 
						|
        return &s_[0];
 | 
						|
    }
 | 
						|
 | 
						|
    iterator
 | 
						|
    begin()
 | 
						|
    {
 | 
						|
        return &s_[0];
 | 
						|
    }
 | 
						|
 | 
						|
    const_iterator
 | 
						|
    begin() const
 | 
						|
    {
 | 
						|
        return &s_[0];
 | 
						|
    }
 | 
						|
 | 
						|
    const_iterator
 | 
						|
    cbegin() const
 | 
						|
    {
 | 
						|
        return &s_[0];
 | 
						|
    }
 | 
						|
 | 
						|
    iterator
 | 
						|
    end()
 | 
						|
    {
 | 
						|
        return &s_[n_];
 | 
						|
    }
 | 
						|
 | 
						|
    const_iterator
 | 
						|
    end() const
 | 
						|
    {
 | 
						|
        return &s_[n_];
 | 
						|
    }
 | 
						|
 | 
						|
    const_iterator
 | 
						|
    cend() const
 | 
						|
    {
 | 
						|
        return &s_[n_];
 | 
						|
    }
 | 
						|
 | 
						|
    reverse_iterator
 | 
						|
    rbegin()
 | 
						|
    {
 | 
						|
        return reverse_iterator{end()};
 | 
						|
    }
 | 
						|
 | 
						|
    const_reverse_iterator
 | 
						|
    rbegin() const
 | 
						|
    {
 | 
						|
        return reverse_iterator{end()};
 | 
						|
    }
 | 
						|
 | 
						|
    const_reverse_iterator
 | 
						|
    crbegin() const
 | 
						|
    {
 | 
						|
        return reverse_iterator{cend()};
 | 
						|
    }
 | 
						|
 | 
						|
    reverse_iterator
 | 
						|
    rend()
 | 
						|
    {
 | 
						|
        return reverse_iterator{begin()};
 | 
						|
    }
 | 
						|
 | 
						|
    const_reverse_iterator
 | 
						|
    rend() const
 | 
						|
    {
 | 
						|
        return reverse_iterator{begin()};
 | 
						|
    }
 | 
						|
 | 
						|
    const_reverse_iterator
 | 
						|
    crend() const
 | 
						|
    {
 | 
						|
        return reverse_iterator{cbegin()};
 | 
						|
    }
 | 
						|
 | 
						|
    bool
 | 
						|
    empty() const
 | 
						|
    {
 | 
						|
        return n_ == 0;
 | 
						|
    }
 | 
						|
 | 
						|
    size_type
 | 
						|
    size() const
 | 
						|
    {
 | 
						|
        return n_;
 | 
						|
    }
 | 
						|
 | 
						|
    size_type constexpr
 | 
						|
    max_size() const
 | 
						|
    {
 | 
						|
        return N;
 | 
						|
    }
 | 
						|
 | 
						|
    size_type
 | 
						|
    capacity() const
 | 
						|
    {
 | 
						|
        return N;
 | 
						|
    }
 | 
						|
 | 
						|
    void
 | 
						|
    shrink_to_fit()
 | 
						|
    {
 | 
						|
        // no-op
 | 
						|
    }
 | 
						|
 | 
						|
    void
 | 
						|
    clear()
 | 
						|
    {
 | 
						|
        resize(0);
 | 
						|
    }
 | 
						|
 | 
						|
    // Does not perform value-initialization
 | 
						|
    void
 | 
						|
    resize(std::size_t n);
 | 
						|
 | 
						|
    std::basic_string<CharT, Traits>
 | 
						|
    to_string() const
 | 
						|
    {
 | 
						|
        return std::basic_string<
 | 
						|
            CharT, Traits>{&s_[0], n_};
 | 
						|
    }
 | 
						|
 | 
						|
private:
 | 
						|
    void
 | 
						|
    assign(CharT const* s);
 | 
						|
};
 | 
						|
 | 
						|
template<std::size_t N, class CharT, class Traits>
 | 
						|
auto
 | 
						|
static_string<N, CharT, Traits>::
 | 
						|
operator[](size_type pos) ->
 | 
						|
    reference
 | 
						|
{
 | 
						|
    static CharT null{0};
 | 
						|
    if(pos == n_)
 | 
						|
        return null;
 | 
						|
    return s_[pos];
 | 
						|
}
 | 
						|
 | 
						|
template<std::size_t N, class CharT, class Traits>
 | 
						|
auto
 | 
						|
static_string<N, CharT, Traits>::
 | 
						|
operator[](size_type pos) const ->
 | 
						|
    const_reference
 | 
						|
{
 | 
						|
    static CharT constexpr null{0};
 | 
						|
    if(pos == n_)
 | 
						|
        return null;
 | 
						|
    return s_[pos];
 | 
						|
}
 | 
						|
 | 
						|
template<std::size_t N, class CharT, class Traits>
 | 
						|
void
 | 
						|
static_string<N, CharT, Traits>::
 | 
						|
resize(std::size_t n)
 | 
						|
{
 | 
						|
    if(n > N)
 | 
						|
        throw std::length_error(
 | 
						|
            "static_string overflow");
 | 
						|
    n_ = n;
 | 
						|
    s_[n_] = 0;
 | 
						|
}
 | 
						|
 | 
						|
template<std::size_t N, class CharT, class Traits>
 | 
						|
void
 | 
						|
static_string<N, CharT, Traits>::
 | 
						|
assign(CharT const* s)
 | 
						|
{
 | 
						|
    size_type n = 0;
 | 
						|
    for(auto p = s; *p; ++p)
 | 
						|
        ++n;
 | 
						|
    if(n > N)
 | 
						|
        throw std::out_of_range(
 | 
						|
            "too large");
 | 
						|
    std::copy(s, s+n, s_.begin());
 | 
						|
}
 | 
						|
 | 
						|
} // websocket
 | 
						|
} // beast
 | 
						|
 | 
						|
#endif
 |