bool Encoder::encode()

in hessian2/basic_codec/string_codec.cc [427:506]


bool Encoder::encode(const absl::string_view &data) {
  Uint64Vector per_chunk_bytes_offsets;
  Uint64Vector four_bytes_char_offsets;

  int64_t length = getUtf8StringLengthAndPerChunkOffsets(
      data, per_chunk_bytes_offsets, four_bytes_char_offsets);
  if (length == -1) {
    return false;
  }

  absl::string_view data_view = data;

#ifdef COMPATIBLE_WITH_JAVA_HESSIAN_LITE
  std::string rewrite_data;
  if (!four_bytes_char_offsets.empty()) {
    rewrite_data = escapeFourBytesUtf8Char(data, four_bytes_char_offsets);
    if (rewrite_data.empty()) {
      return false;
    }

    per_chunk_bytes_offsets.clear();
    four_bytes_char_offsets.clear();

    length = getUtf8StringLengthAndPerChunkOffsets(
        rewrite_data, per_chunk_bytes_offsets, four_bytes_char_offsets);
    data_view = rewrite_data;
  }

  // Check length again.
  if (length == -1) {
    return false;
  }
#endif

  // Java's 16-bit integers are signed, so the maximum value is 32768
  uint32_t str_offset = 0;
  const uint16_t step_length = STRING_CHUNK_SIZE;
  int pos = 0;
  while (static_cast<uint64_t>(length) > STRING_CHUNK_SIZE) {
    writer_->writeByte(0x52);
    writer_->writeBE<uint16_t>(step_length);
    length -= step_length;
    auto raw_offset = per_chunk_bytes_offsets[pos++];
    writer_->rawWrite(data_view.substr(str_offset, raw_offset - str_offset));
    str_offset = raw_offset;
  }

  if (length == 0) {
    // x00  # "", empty string
    writer_->writeByte(0x00);
    return true;
  }

  const size_t data_view_size = data_view.size();

  if (length <= 31) {
    // [x00-x1f] <utf8-data>
    // Compact: short strings
    writer_->writeByte(length);
    writer_->rawWrite(
        data_view.substr(str_offset, data_view_size - str_offset));
    return true;
  }

  // [x30-x34] <utf8-data>
  if (length <= 1023) {
    uint8_t code = length / 256;
    uint8_t remain = length % 256;
    writer_->writeByte(0x30 + code);
    writer_->writeByte(remain);
    writer_->rawWrite(
        data_view.substr(str_offset, data_view_size - str_offset));
    return true;
  }

  writer_->writeByte(0x53);
  writer_->writeBE<uint16_t>(length);
  writer_->rawWrite(data_view.substr(str_offset, data_view_size - str_offset));
  return true;
}