aboutsummaryrefslogblamecommitdiffstats
path: root/util/stream/str.h
blob: 028bd572c036e0d503daae38c90af68d4d78c06f (plain) (tree)
1
2
3
4
5
6
7
8
9
            
 
                     
                            
 
                                
                                     
                                      
 
   





                                               
                                                     
       

                                                                          
      



                                                                                     
      
                                                            
                                                  
                


                 
                                           
 


                                                               
 



                                                
          
                                                         
        
                      
                
                               
  
   
                                         
                                             
       
       
                                                                           






                                                                              
                                             



                                                        
 
                              
 



                                                                          
                                       
     
                                                 





                                                       



                

                                                              
                                                                                               
                                                  
 
                          

                                                

     
                                               

                                                
     
 
                                                    

                                                
     
 
                                                                       
                            


                          
 
                              
 
       





                                                                         
                                                                                
       
                                    
                      
     

                                                                                
                                                






                                                                               
                                              
                             






                                                                              
                                         
                             




                                                                           
                                                        














                                                                    
                                        




                       
  
         
#pragma once

#include "zerocopy.h"
#include "zerocopy_output.h"

#include <util/generic/string.h>
#include <util/generic/noncopyable.h>
#include <util/generic/store_policy.h>

/**
 * @addtogroup Streams_Strings
 * @{
 */

/**
 * Input stream for reading data from a string.
 */
class TStringInput: public IZeroCopyInputFastReadTo {
public:
    /**
     * Constructs a string input stream that reads character data from the
     * provided string.
     *
     * Note that this stream keeps a reference to the provided string, so it's
     * up to the user to make sure that the string doesn't get destroyed while
     * this stream is in use.
     *
     * For reading data from `TStringBuf`s, see `TMemoryInput` (`util/stream/mem.h`).
     *
     * @param s                         String to read from.
     */
    inline TStringInput(const TString& s) noexcept
        : S_(&s)
        , Pos_(0)
    {
    }

    TStringInput(const TString&&) = delete;

    ~TStringInput() override;

    TStringInput(TStringInput&&) noexcept = default;
    TStringInput& operator=(TStringInput&&) noexcept = default;

    inline void Swap(TStringInput& s) noexcept {
        DoSwap(S_, s.S_);
        DoSwap(Pos_, s.Pos_);
    }

protected:
    size_t DoNext(const void** ptr, size_t len) override;
    void DoUndo(size_t len) override;

private:
    const TString* S_;
    size_t Pos_;

    friend class TStringStream;
};

/**
 * Stream for writing data into a string.
 */
class TStringOutput: public IZeroCopyOutput {
public:
    /**
     * Constructs a string output stream that appends character data to the
     * provided string.
     *
     * Note that this stream keeps a reference to the provided string, so it's
     * up to the user to make sure that the string doesn't get destroyed while
     * this stream is in use.
     *
     * @param s                         String to append to.
     */
    inline TStringOutput(TString& s) noexcept
        : S_(&s)
    {
    }

    TStringOutput(TStringOutput&& s) noexcept = default;

    ~TStringOutput() override;

    /**
     * @param size                      Number of additional characters to
     *                                  reserve in output string.
     */
    inline void Reserve(size_t size) {
        S_->reserve(S_->size() + size);
    }

    inline void Swap(TStringOutput& s) noexcept {
        DoSwap(S_, s.S_);
    }

protected:
    size_t DoNext(void** ptr) override;
    void DoUndo(size_t len) override;
    void DoWrite(const void* buf, size_t len) override;
    void DoWriteC(char c) override;

private:
    TString* S_;
};

/**
 * String input/output stream, similar to `std::stringstream`.
 */
class TStringStream: private TEmbedPolicy<TString>, public TStringInput, public TStringOutput {
    using TEmbeddedString = TEmbedPolicy<TString>;

public:
    inline TStringStream()
        : TEmbeddedString()
        , TStringInput(*TEmbeddedString::Ptr())
        , TStringOutput(*TEmbeddedString::Ptr())
    {
    }

    inline TStringStream(const TString& string)
        : TEmbeddedString(string)
        , TStringInput(*TEmbeddedString::Ptr())
        , TStringOutput(*TEmbeddedString::Ptr())
    {
    }

    inline TStringStream(const TStringStream& other)
        : TEmbeddedString(other.Str())
        , TStringInput(*TEmbeddedString::Ptr())
        , TStringOutput(*TEmbeddedString::Ptr())
    {
    }

    inline TStringStream& operator=(const TStringStream& other) {
        // All references remain alive, we need to change position only
        Str() = other.Str();
        Pos_ = other.Pos_;

        return *this;
    }

    ~TStringStream() override;

    /**
     * @returns                         Whether @c this contains any data
     */
    explicit operator bool() const noexcept {
        return !Empty();
    }

    /**
     * @returns                         String that this stream is writing into.
     */
    inline TString& Str() noexcept {
        return *Ptr();
    }

    /**
     * @returns                         String that this stream is writing into.
     */
    inline const TString& Str() const noexcept {
        return *Ptr();
    }

    /**
     * @returns                         Pointer to the character data contained
     *                                  in this stream. The data is guaranteed
     *                                  to be null-terminated.
     */
    inline const char* Data() const noexcept {
        return Ptr()->data();
    }

    /**
     * @returns                         Total number of characters in this
     *                                  stream. Note that this is not the same
     *                                  as the total number of characters
     *                                  available for reading.
     */
    inline size_t Size() const noexcept {
        return Ptr()->size();
    }

    /**
     * @returns                         Whether the string that this stream
     *                                  operates on is empty.
     */
    Y_PURE_FUNCTION inline bool Empty() const noexcept {
        return Str().empty();
    }

    using TStringOutput::Reserve;

    /**
     * Clears the string that this stream operates on and resets the
     * read/write pointers.
     */
    inline void Clear() {
        Str().clear();
        Pos_ = 0;
    }

    // TODO: compatibility with existing code, remove

    Y_PURE_FUNCTION bool empty() const {
        return Empty();
    }

    void clear() {
        Clear();
    }
};

/** @} */