// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FBL_STRING_BUFFER_H_
#define FBL_STRING_BUFFER_H_

#include "string.h"
#include <stdarg.h>

#include <fbl/string.h>
#include <fbl/string_piece.h>
#include <zircon/assert.h>
#include <zircon/compiler.h>

namespace fbl {
namespace internal {
size_t StringBufferAppendPrintf(char* dest, size_t remaining, const char* format, va_list ap);
}  // namespace internal

// A fixed-size buffer for assembling a string.
//
// fbl::StringBuffer is designed to resemble std::string except that it
// does not allocate heap storage.
//
// The buffer is sized to hold up to N characters plus a null-terminator.
template <size_t N>
class StringBuffer final {
 public:
  // Creates an empty string buffer.
  StringBuffer() : length_(0U) { data_[0] = 0; }

  // Releases the string buffer.
  ~StringBuffer() = default;

  // Returns a pointer to the null-terminated contents of the string.
  char* data() { return data_; }
  const char* data() const { return data_; }
  const char* c_str() const { return data_; }

  // Returns the length of the string, excluding its null terminator.
  size_t length() const { return length_; }
  size_t size() const { return length_; }

  // Returns the length of the string, excluding its null terminator.
  bool empty() const { return length_ == 0U; }

  // Returns the capacity of the buffer.
  constexpr size_t capacity() const { return N; }

  // Character iterators, excluding the null terminator.
  char* begin() { return data(); }
  const char* begin() const { return data(); }
  const char* cbegin() const { return data(); }
  char* end() { return data() + length(); }
  const char* end() const { return data() + length(); }
  const char* cend() const { return data() + length(); }

  // Gets a reference to the character at the specified index.
  // Position must be greater than or equal to 0 and less than |length()|.
  char& operator[](size_t pos) { return data_[pos]; }
  const char& operator[](size_t pos) const { return data_[pos]; }

  // Clears the string buffer.
  void Clear() {
    length_ = 0U;
    data_[0] = 0;
  }

  // Resizes the string buffer.
  // If the current length is less than |count|, additional characters are appended
  // with the value |ch|.
  // If the current length is greater than |count|, the string is truncated.
  // |length| must be less than or equal to |N|.
  void Resize(size_t count, char ch = '\0') {
    ZX_DEBUG_ASSERT(count <= N);
    if (length_ < count)
      memset(data_ + length_, ch, count - length_);
    length_ = count;
    data_[length_] = 0;
  }

  // Appends a single character.
  // The result is truncated if the appended content does not fit completely.
  StringBuffer& Append(char ch) {
    if (length_ < N) {
      data_[length_++] = ch;
      data_[length_] = 0;
    }
    return *this;
  }

  // Appends content to the string buffer from a null-terminated C string.
  // The result is truncated if the appended content does not fit completely.
  // |data| must not be null.
  StringBuffer& Append(const char* data) {
    Append(data, constexpr_strlen(data));
    return *this;
  }

  // Appends content to the string buffer from a character array of given length.
  // The result is truncated if the appended content does not fit completely.
  // |data| must not be null.
  StringBuffer& Append(const char* data, size_t length) {
    AppendInternal(data, length);
    return *this;
  }

  // Appends content to the string buffer from a string piece.
  // The result is truncated if the appended content does not fit completely.
  StringBuffer& Append(const fbl::StringPiece& piece) {
    AppendInternal(piece.data(), piece.length());
    return *this;
  }

  // Appends content to the string buffer from another string.
  // The result is truncated if the appended content does not fit completely.
  StringBuffer& Append(const fbl::String& other) {
    AppendInternal(other.data(), other.length());
    return *this;
  }

  // Appends |printf()|-like input.
  // The result is truncated if the appended content does not fit completely.
  StringBuffer& AppendPrintf(const char* format, ...) __PRINTFLIKE(2, 3) {
    va_list ap;
    va_start(ap, format);
    AppendVPrintf(format, ap);
    va_end(ap);
    return *this;
  }

  // Appends |vprintf()|-like input using a |va_list|.
  // The result is truncated if the appended content does not fit completely.
  StringBuffer& AppendVPrintf(const char* format, va_list ap) {
    length_ += internal::StringBufferAppendPrintf(data_ + length_, N - length_, format, ap);
    return *this;
  }

  // Gets the buffer's contents as a string.
  fbl::String ToString() const { return fbl::String(data(), length()); }

  // Gets the buffer's contents as a string piece.
  fbl::StringPiece ToStringPiece() const { return fbl::StringPiece(data(), length()); }

 private:
  void AppendInternal(const char* data, size_t length) {
    size_t remaining = N - length_;
    if (length > remaining)
      length = remaining;
    memcpy(data_ + length_, data, length);
    length_ += length;
    data_[length_] = 0;
  }

  size_t length_ = 0U;
  char data_[N + 1U];
};

}  // namespace fbl

#endif  // FBL_STRING_BUFFER_H_
