text: /*
   *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
   *
   *  Use of this source code is governed by a BSD-style license
   *  that can be found in the LICENSE file in the root of the source
   *  tree. An additional intellectual property rights grant can be found
   *  in the file PATENTS.  All contributing project authors may
   *  be found in the AUTHORS file in the root of the source tree.
   */
  
  #ifndef WEBRTC_RTC_BASE_CRYPTSTRING_H_
  #define WEBRTC_RTC_BASE_CRYPTSTRING_H_
  
  #include <string.h>
  
  #include <memory>
  #include <string>
  #include <vector>
  
  namespace rtc {
  
  class CryptStringImpl {
  public:
    virtual ~CryptStringImpl() {}
    virtual size_t GetLength() const = 0;
    virtual void CopyTo(char * dest, bool nullterminate) const = 0;
    virtual std::string UrlEncode() const = 0;
    virtual CryptStringImpl * Copy() const = 0;
    virtual void CopyRawTo(std::vector<unsigned char> * dest) const = 0;
  };
  
  class EmptyCryptStringImpl : public CryptStringImpl {
  public:
    ~EmptyCryptStringImpl() override {}
    size_t GetLength() const override;
    void CopyTo(char* dest, bool nullterminate) const override;
    std::string UrlEncode() const override;
    CryptStringImpl* Copy() const override;
    void CopyRawTo(std::vector<unsigned char>* dest) const override;
  };
  
  class CryptString {
   public:
    CryptString();
    size_t GetLength() const { return impl_->GetLength(); }
    void CopyTo(char * dest, bool nullterminate) const { impl_->CopyTo(dest, nullterminate); }
    CryptString(const CryptString& other);
    explicit CryptString(const CryptStringImpl& impl);
    ~CryptString();
    CryptString & operator=(const CryptString & other) {
      if (this != &other) {
        impl_.reset(other.impl_->Copy());
      }
      return *this;
    }
    void Clear() { impl_.reset(new EmptyCryptStringImpl()); }
    std::string UrlEncode() const { return impl_->UrlEncode(); }
    void CopyRawTo(std::vector<unsigned char> * dest) const {
      return impl_->CopyRawTo(dest);
    }
  
   private:
    std::unique_ptr<const CryptStringImpl> impl_;
  };
  
  
  // Used for constructing strings where a password is involved and we
  // need to ensure that we zero memory afterwards
  class FormatCryptString {
  public:
    FormatCryptString() {
      storage_ = new char[32];
      capacity_ = 32;
      length_ = 0;
      storage_[0] = 0;
    }
  
    void Append(const std::string & text) {
      Append(text.data(), text.length());
    }
  
    void Append(const char * data, size_t length) {
      EnsureStorage(length_ + length + 1);
      memcpy(storage_ + length_, data, length);
      length_ += length;
      storage_[length_] = '\0';
    }
  
    void Append(const CryptString * password) {
      size_t len = password->GetLength();
      EnsureStorage(length_ + len + 1);
      password->CopyTo(storage_ + length_, true);
      length_ += len;
    }
  
    size_t GetLength() {
      return length_;
    }
  
    const char * GetData() {
      return storage_;
    }
  
  
    // Ensures storage of at least n bytes
    void EnsureStorage(size_t n) {
      if (capacity_ >= n) {
        return;
      }
  
      size_t old_capacity = capacity_;
      char * old_storage = storage_;
  
      for (;;) {
        capacity_ *= 2;
        if (capacity_ >= n)
          break;
      }
  
      storage_ = new char[capacity_];
  
      if (old_capacity) {
        memcpy(storage_, old_storage, length_);
  
        // zero memory in a way that an optimizer won't optimize it out
        old_storage[0] = 0;
        for (size_t i = 1; i < old_capacity; i++) {
          old_storage[i] = old_storage[i - 1];
        }
        delete[] old_storage;
      }
    }
  
    ~FormatCryptString() {
      if (capacity_) {
        storage_[0] = 0;
        for (size_t i = 1; i < capacity_; i++) {
          storage_[i] = storage_[i - 1];
        }
      }
      delete[] storage_;
    }
  private:
    char * storage_;
    size_t capacity_;
    size_t length_;
  };
  
  class InsecureCryptStringImpl : public CryptStringImpl {
   public:
    std::string& password() { return password_; }
    const std::string& password() const { return password_; }
  
    ~InsecureCryptStringImpl() override = default;
    size_t GetLength() const override;
    void CopyTo(char* dest, bool nullterminate) const override;
    std::string UrlEncode() const override;
    CryptStringImpl* Copy() const override;
    void CopyRawTo(std::vector<unsigned char>* dest) const override;
  
   private:
    std::string password_;
  };
  
  }
  
  #endif  // WEBRTC_RTC_BASE_CRYPTSTRING_H_
  