#include <string>

using std::string;
using std::min;

class PackageStream {
 public:
  PackageStream(string data, int32_t package_len)
    : package_len_(package_len), data_(data) {}

  int32_t PackageLen() const {
    return package_len_;
  }

  int32_t ReadPackage(char* buf) {
    int32_t next_pos = min<int32_t>(data_.size(), pos_ + PackageLen());
    int32_t len = next_pos - pos_;

    memcpy(buf, data_.c_str() + pos_, len);
    pos_ = next_pos;
    return len;
  }

 private:
  const int32_t package_len_;
  int32_t pos_ = 0;

  string data_;
};

class BufferedReader {
 public:
  explicit BufferedReader(PackageStream* stream)
    : stream(stream) {}
  int32_t Read(char* output_buffer, int32_t buffer_len) {
    int32_t package_len = stream->PackageLen();
    int32_t read_len = 0;
    while (buffer_len >= package_len) {
      stream->ReadPackage(output_buffer);
      buffer_len -= package_len;
      read_len += package_len;
    }
    if (package_len > buffer_len) {
      char* temp_buffer = new char[package_len];
      stream->ReadPackage(temp_buffer);
      memcpy(output_buffer, temp_buffer, buffer_len);
      read_len += buffer_len;
    }
    return read_len;
  }

 private:
  PackageStream* stream;
};