<commit_before>#include "amf.h"
#include "utils.h"
#include <string.h>
#include <arpa/inet.h>

AmfEnc *
amf_enc_new ()
{
  AmfEnc * enc = g_new0 (AmfEnc, 1);
  enc->buf = g_byte_array_new ();
  enc->version = AMF0_VERSION;
  return enc;
}

void
amf_enc_free (AmfEnc * enc)
{
  g_byte_array_free (enc->buf, TRUE);
  g_free (enc);
}

static void
amf_enc_add (AmfEnc * enc, const guint8 * data, guint len)
{
  enc->buf = g_byte_array_append (enc->buf, data, len);
}

void
amf_enc_add_char (AmfEnc * enc, char c)
{
  amf_enc_add (enc, (guint8 *)&c, 1);
}

void
amf_enc_add_short (AmfEnc * enc, guint16 s)
{
  amf_enc_add (enc, (guint8 *)&s, 2);
}

void
amf_enc_add_int (AmfEnc * enc, guint32 value)
{
  if (enc->version == AMF3_VERSION) {
    guint8 bytes[4];
    int i = 0;

    /* we can only encode 29 bits */
    value &= 0x3FFFFFFF;
    for (i = 0; i < 4; i++) {
      if (i == 3) {
        /* pick out the last 8 bits */
        bytes[i] = value & 0xff;
      } else {
        /* pick out the 7 first bits */
        bytes[i] = value & 0x7f;
      }

      if (i > 0) {
        /* add a marker-bit for saying "there is more" */
        bytes[i] |= 0x80;
      }

      /* shift value right by 7 */
      value = value >> 7;
      /* stop if we have added it all */
      if (value == 0)
        break;
    }
    for (; i > -1; i--) {
      amf_enc_add (enc, &bytes[i], 1);
    }
  } else {
    amf_enc_add (enc, (guint8 *)&value, 4);
  }
}

void
amf_enc_use_amf3 (AmfEnc * enc)
{
  amf_enc_add_char (enc, AMF0_SWITCH_AMF3);
  enc->version = AMF3_VERSION;
}

static void
_write_string (AmfEnc * enc, const gchar * str)
{
  guint len = strlen (str);

  if (enc->version == AMF3_VERSION) {
    amf_enc_add_int (enc, len * 2 + 1);
  } else {
    guint16 str_len = htons (len);
    amf_enc_add_short (enc, str_len);
  }
  amf_enc_add (enc, (const guint8 *)str, len);
}

void
amf_enc_write_key (AmfEnc * enc, const gchar * str)
{
  _write_string (enc, str);
}

void
amf_enc_write_string (AmfEnc * enc, const gchar * str)
{
  amf_enc_add_char (enc,
      enc->version == AMF3_VERSION ? AMF3_STRING : AMF0_STRING);
  _write_string (enc, str);
}

static void
amf_enc_write_int (AmfEnc * enc, gint i)
{
  if (enc->version == AMF3_VERSION)
    amf_enc_add_char (enc, AMF3_INTEGER);
  else
    g_assert_not_reached ();

  amf_enc_add_int (enc, i);
}

void
amf_enc_write_double (AmfEnc * enc, double n)
{
  amf_enc_add_char (enc, AMF0_NUMBER);
  uint64_t encoded = 0;
#if defined(__i386__) || defined(__x86_64__)
  /* Flash uses same floating point format as x86 */
  memcpy (&encoded, &n, 8);
#endif
  uint32_t val = htonl (encoded >> 32);
  amf_enc_add_int (enc, val);
  val = htonl (encoded);
  amf_enc_add_int (enc, val);
}

void
amf_enc_write_bool (AmfEnc * enc, gboolean b)
{
  if (enc->version == AMF3_VERSION) {
    amf_enc_add_char (enc, b ? AMF3_TRUE : AMF3_FALSE);
  } else {
    amf_enc_add_char (enc, AMF0_BOOLEAN);<commit_msg>rtmp-amf: dont use add_int when adding floats<commit_after>#include "amf.h"
#include "utils.h"
#include <string.h>
#include <arpa/inet.h>

AmfEnc *
amf_enc_new ()
{
  AmfEnc * enc = g_new0 (AmfEnc, 1);
  enc->buf = g_byte_array_new ();
  enc->version = AMF0_VERSION;
  return enc;
}

void
amf_enc_free (AmfEnc * enc)
{
  g_byte_array_free (enc->buf, TRUE);
  g_free (enc);
}

static void
amf_enc_add (AmfEnc * enc, const guint8 * data, guint len)
{
  enc->buf = g_byte_array_append (enc->buf, data, len);
}

void
amf_enc_add_char (AmfEnc * enc, char c)
{
  amf_enc_add (enc, (guint8 *)&c, 1);
}

void
amf_enc_add_short (AmfEnc * enc, guint16 s)
{
  amf_enc_add (enc, (guint8 *)&s, 2);
}

void
amf_enc_add_int (AmfEnc * enc, guint32 value)
{
  if (enc->version == AMF3_VERSION) {
    guint8 bytes[4];
    int i = 0;

    /* we can only encode 29 bits */
    value &= 0x3FFFFFFF;
    for (i = 0; i < 4; i++) {
      if (i == 3) {
        /* pick out the last 8 bits */
        bytes[i] = value & 0xff;
      } else {
        /* pick out the 7 first bits */
        bytes[i] = value & 0x7f;
      }

      if (i > 0) {
        /* add a marker-bit for saying "there is more" */
        bytes[i] |= 0x80;
      }

      /* shift value right by 7 */
      value = value >> 7;
      /* stop if we have added it all */
      if (value == 0)
        break;
    }
    for (; i > -1; i--) {
      amf_enc_add (enc, &bytes[i], 1);
    }
  } else {
    amf_enc_add (enc, (guint8 *)&value, 4);
  }
}

void
amf_enc_use_amf3 (AmfEnc * enc)
{
  amf_enc_add_char (enc, AMF0_SWITCH_AMF3);
  enc->version = AMF3_VERSION;
}

static void
_write_string (AmfEnc * enc, const gchar * str)
{
  guint len = strlen (str);

  if (enc->version == AMF3_VERSION) {
    amf_enc_add_int (enc, len * 2 + 1);
  } else {
    guint16 str_len = htons (len);
    amf_enc_add_short (enc, str_len);
  }
  amf_enc_add (enc, (const guint8 *)str, len);
}

void
amf_enc_write_key (AmfEnc * enc, const gchar * str)
{
  _write_string (enc, str);
}

void
amf_enc_write_string (AmfEnc * enc, const gchar * str)
{
  amf_enc_add_char (enc,
      enc->version == AMF3_VERSION ? AMF3_STRING : AMF0_STRING);
  _write_string (enc, str);
}

static void
amf_enc_write_int (AmfEnc * enc, gint i)
{
  if (enc->version == AMF3_VERSION)
    amf_enc_add_char (enc, AMF3_INTEGER);
  else
    g_assert_not_reached ();

  amf_enc_add_int (enc, i);
}

void
amf_enc_write_double (AmfEnc * enc, double n)
{
  amf_enc_add_char (enc, AMF0_NUMBER);
  uint64_t encoded = 0;
#if defined(__i386__) || defined(__x86_64__)
  /* Flash uses same floating point format as x86 */
  memcpy (&encoded, &n, 8);
#endif
  uint32_t val = htonl (encoded >> 32);
  amf_enc_add (enc, (guint8 *)&val, 4);
  val = htonl (encoded);
  amf_enc_add (enc, (guint8 *)&val, 4);
}

void
amf_enc_write_bool (AmfEnc * enc, gboolean b)
{
  if (enc->version == AMF3_VERSION) {
    amf_enc_add_char (enc, b ? AMF3_TRUE : AMF3_FALSE);
  } else {
    amf_enc_add_char (enc, AMF0_BOOLEAN);
{'fraction_non_alphanumeric': 0.14179357021996616, 'fraction_numerical': 0.026395939086294416, 'mean_word_length': 2.977792732166891, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '6547622', 'n_tokens_mistral': 2621, 'n_tokens_neox': 2537, 'n_words': 629}