<commit_before>/*
  Copyright 2014 DataStax

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#ifndef __CASS_SERIALIZATION_HPP_INCLUDED__
#define __CASS_SERIALIZATION_HPP_INCLUDED__

#include "address.hpp"
#include "cassandra.h"
#include "common.hpp"

#include <boost/cstdint.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/string_ref.hpp>

#include <assert.h>
#include <string.h>
#include <list>
#include <map>
#include <string>

namespace cass {

// http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
// This frees us from having to deal with endian stuff on every platform.
// If it's not fast enough then we can go back to using the bytes swaps.

// TODO(mpenick): Use output pointers instead of references and make input const
// "decode_byte(input, &value)" is clearer than "decode_byte(input, value)"

inline char* encode_byte(char* output, uint8_t value) {
  output[0] = static_cast<char>(value);
  return output + sizeof(uint8_t);
}

inline char* decode_byte(char* input, uint8_t& output) {
  output = static_cast<uint8_t>(input[0]);
  return input + sizeof(uint8_t);
}

inline void encode_uint16(char* output, uint16_t value) {
  output[0] = static_cast<char>(value >> 8);
  output[1] = static_cast<char>(value >> 0);
}

inline char* decode_uint16(char* input, uint16_t& output) {
  output = (static_cast<uint16_t>(static_cast<uint8_t>(input[1])) << 0) |
           (static_cast<uint16_t>(static_cast<uint8_t>(input[0])) << 8);
  return input + sizeof(uint16_t);
}

inline void encode_int32(char* output, int32_t value) {
  output[0] = static_cast<char>(value >> 24);
  output[1] = static_cast<char>(value >> 16);
  output[2] = static_cast<char>(value >> 8);
  output[3] = static_cast<char>(value >> 0);
}

inline char* decode_int32(char* input, int32_t& output) {
  output = (static_cast<int32_t>(static_cast<uint8_t>(input[3])) << 0) |
           (static_cast<int32_t>(static_cast<uint8_t>(input[2])) << 8) |
           (static_cast<int32_t>(static_cast<uint8_t>(input[1])) << 16) |
           (static_cast<int32_t>(static_cast<uint8_t>(input[0])) << 24);
  return input + sizeof(int32_t);
}

inline void encode_int64(char* output, cass_int64_t value) {
  BOOST_STATIC_ASSERT(sizeof(cass_int64_t) == 8);
  output[0] = static_cast<char>(value >> 56);
  output[1] = static_cast<char>(value >> 48);
  output[2] = static_cast<char>(value >> 40);
  output[3] = static_cast<char>(value >> 32);
  output[4] = static_cast<char>(value >> 24);
  output[5] = static_cast<char>(value >> 16);
  output[6] = static_cast<char>(value >> 8);
  output[7] = static_cast<char>(value >> 0);
}

inline void encode_uint64(uint8_t* output, uint64_t value) {
  BOOST_STATIC_ASSERT(sizeof(cass_uint64_t) == 8);
  output[0] = static_cast<uint8_t>(value >> 56);
  output[1] = static_cast<uint8_t>(value >> 48);
  output[2] = static_cast<uint8_t>(value >> 40);
  output[3] = static_cast<uint8_t>(value >> 32);
  output[4] = static_cast<uint8_t>(value >> 24);
  output[5] = static_cast<uint8_t>(value >> 16);
  output[6] = static_cast<uint8_t>(value >> 8);
  output[7] = static_cast<uint8_t>(value >> 0);
}

inline char* decode_int64(char* input, cass_int64_t& output) {
  BOOST_STATIC_ASSERT(sizeof(cass_int64_t) == 8);
  output = (static_cast<cass_int64_t>(static_cast<uint8_t>(input[7])) << 0) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[6])) << 8) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[5])) << 16) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[4])) << 24) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[3])) << 32) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[2])) << 40) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[1])) << 48) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[0])) << 56);
  return input + sizeof(cass_int64_t);
}

inline void encode_float(char* output, float value) {
  BOOST_STATIC_ASSERT(std::numeric_limits<float>::is_iec559);
  encode_int32(output, *copy_cast<float*, int32_t*>(&value));
}

inline char* decode_float(char* input, float& output) {
  BOOST_STATIC_ASSERT(std::numeric_limits<float>::is_iec559);
  return decode_int32(input, *copy_cast<float*, int32_t*>(&output));
}

inline void encode_double(char* output, double value) {
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
  encode_int64(output, *copy_cast<double*, cass_int64_t*>(&value));
}

inline char* decode_double(char* input, double& output) {
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
  return decode_int64(input, *copy_cast<double*, cass_int64_t*>(&output));
}

inline char* decode_string(char* input, char** output, size_t& size) {
  uint16_t string_size;
  char* pos = decode_uint16(input, string_size);
  size = string_size;
  *output = pos;
  return pos + string_size;
}

inline char* decode_string_ref(char* buffer, boost::string_ref* output) {
  char* str;
  size_t str_size;
  buffer = decode_string(buffer, &str, str_size);
  *output = boost::string_ref(str, str_size);
  return buffer;
}

inline char* decode_long_string(char* input, char** output, size_t& size) {
  int32_t string_size;<commit_msg>Use memcpy to avoid strict aliasing warnings with gcc 4.4<commit_after>/*
  Copyright 2014 DataStax

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

#ifndef __CASS_SERIALIZATION_HPP_INCLUDED__
#define __CASS_SERIALIZATION_HPP_INCLUDED__

#include "address.hpp"
#include "cassandra.h"
#include "common.hpp"

#include <boost/cstdint.hpp>
#include <boost/limits.hpp>
#include <boost/static_assert.hpp>
#include <boost/utility/string_ref.hpp>

#include <assert.h>
#include <string.h>
#include <list>
#include <map>
#include <string>

namespace cass {

// http://commandcenter.blogspot.com/2012/04/byte-order-fallacy.html
// This frees us from having to deal with endian stuff on every platform.
// If it's not fast enough then we can go back to using the bytes swaps.

// TODO(mpenick): Use output pointers instead of references and make input const
// "decode_byte(input, &value)" is clearer than "decode_byte(input, value)"

inline char* encode_byte(char* output, uint8_t value) {
  output[0] = static_cast<char>(value);
  return output + sizeof(uint8_t);
}

inline char* decode_byte(char* input, uint8_t& output) {
  output = static_cast<uint8_t>(input[0]);
  return input + sizeof(uint8_t);
}

inline void encode_uint16(char* output, uint16_t value) {
  output[0] = static_cast<char>(value >> 8);
  output[1] = static_cast<char>(value >> 0);
}

inline char* decode_uint16(char* input, uint16_t& output) {
  output = (static_cast<uint16_t>(static_cast<uint8_t>(input[1])) << 0) |
           (static_cast<uint16_t>(static_cast<uint8_t>(input[0])) << 8);
  return input + sizeof(uint16_t);
}

inline void encode_int32(char* output, int32_t value) {
  output[0] = static_cast<char>(value >> 24);
  output[1] = static_cast<char>(value >> 16);
  output[2] = static_cast<char>(value >> 8);
  output[3] = static_cast<char>(value >> 0);
}

inline char* decode_int32(char* input, int32_t& output) {
  output = (static_cast<int32_t>(static_cast<uint8_t>(input[3])) << 0) |
           (static_cast<int32_t>(static_cast<uint8_t>(input[2])) << 8) |
           (static_cast<int32_t>(static_cast<uint8_t>(input[1])) << 16) |
           (static_cast<int32_t>(static_cast<uint8_t>(input[0])) << 24);
  return input + sizeof(int32_t);
}

inline void encode_int64(char* output, cass_int64_t value) {
  BOOST_STATIC_ASSERT(sizeof(cass_int64_t) == 8);
  output[0] = static_cast<char>(value >> 56);
  output[1] = static_cast<char>(value >> 48);
  output[2] = static_cast<char>(value >> 40);
  output[3] = static_cast<char>(value >> 32);
  output[4] = static_cast<char>(value >> 24);
  output[5] = static_cast<char>(value >> 16);
  output[6] = static_cast<char>(value >> 8);
  output[7] = static_cast<char>(value >> 0);
}

inline void encode_uint64(uint8_t* output, uint64_t value) {
  BOOST_STATIC_ASSERT(sizeof(cass_uint64_t) == 8);
  output[0] = static_cast<uint8_t>(value >> 56);
  output[1] = static_cast<uint8_t>(value >> 48);
  output[2] = static_cast<uint8_t>(value >> 40);
  output[3] = static_cast<uint8_t>(value >> 32);
  output[4] = static_cast<uint8_t>(value >> 24);
  output[5] = static_cast<uint8_t>(value >> 16);
  output[6] = static_cast<uint8_t>(value >> 8);
  output[7] = static_cast<uint8_t>(value >> 0);
}

inline char* decode_int64(char* input, cass_int64_t& output) {
  BOOST_STATIC_ASSERT(sizeof(cass_int64_t) == 8);
  output = (static_cast<cass_int64_t>(static_cast<uint8_t>(input[7])) << 0) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[6])) << 8) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[5])) << 16) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[4])) << 24) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[3])) << 32) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[2])) << 40) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[1])) << 48) |
           (static_cast<cass_int64_t>(static_cast<uint8_t>(input[0])) << 56);
  return input + sizeof(cass_int64_t);
}

inline void encode_float(char* output, float value) {
  BOOST_STATIC_ASSERT(std::numeric_limits<float>::is_iec559);
  int32_t int_value;
  memcpy(&int_value, &value, sizeof(int_value));
  encode_int32(output, int_value);
}

inline char* decode_float(char* input, float& output) {
  BOOST_STATIC_ASSERT(std::numeric_limits<float>::is_iec559);
  int32_t int_value;
  char* pos = decode_int32(input, int_value);
  memcpy(&output, &int_value, sizeof(int_value));
  return pos;
}

inline void encode_double(char* output, double value) {
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
  cass_int64_t int_value;
  memcpy(&int_value, &value, sizeof(int_value));
  encode_int64(output, int_value);
}

inline char* decode_double(char* input, double& output) {
  BOOST_STATIC_ASSERT(std::numeric_limits<double>::is_iec559);
  cass_int64_t int_value;
  char* pos = decode_int64(input, int_value);
  memcpy(&output, &int_value, sizeof(int_value));
  return pos;
}

inline char* decode_string(char* input, char** output, size_t& size) {
  uint16_t string_size;
  char* pos = decode_uint16(input, string_size);
  size = string_size;
  *output = pos;
  return pos + string_size;
}

inline char* decode_string_ref(char* buffer, boost::string_ref* output) {
  char* str;
  size_t str_size;
  buffer = decode_string(buffer, &str, str_size);
  *output = boost::string_ref(str, str_size);
  return buffer;
}

inline char* decode_long_string(char* input, char** output, size_t& size) {
  int32_t string_size;
{'fraction_non_alphanumeric': 0.14706384431546604, 'fraction_numerical': 0.041652441106179584, 'mean_word_length': 5.47705914870094, 'pattern_counts': {'":': 0, '<': 193, '<?xml version=': 0, '>': 225, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5592401', 'n_tokens_mistral': 4519, 'n_tokens_neox': 4222, 'n_words': 884}