<commit_before>/*
 * Copyright 2007-2013 National ICT Australia (NICTA), Australia
 *
 * This software may be used and distributed solely under the terms of
 * the MIT license (License).  You should find a copy of the License in
 * LICENSE.TXT or at http://opensource.org/licenses/MIT. By downloading
 * or using this software you accept the terms and the liability
 * disclaimer in the License.
 */

/*!\file text_writer.c
  \brief Implements a writer which stores results in a local file.
*/

#include <alloca.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>

#include "oml2/omlc.h"
#include "oml2/oml_filter.h"
#include "oml2/oml_writer.h"
#include "ocomm/o_log.h"
#include "oml_value.h"
#include "client.h"
#include "buffered_writer.h"
#include "string_utils.h"
#include "base64.h"

typedef struct {

  oml_writer_meta meta;
  oml_writer_header_done header_done;


  //! Called before and after writing individual
  // filter results with 'out'
  oml_writer_row_start row_start;
  oml_writer_row_end row_end;

  //! Writing a result.
  oml_writer_out out;

  oml_writer_close close;

  OmlWriter* next;

  //----------------------------

  BufferedWriterHdl bufferedWriter;
  MBuffer* mbuf;        /* Pointer to active buffer from bufferedWriter */
  OmlOutStream* out_stream;
} OmlTextWriter;


static int owt_meta(OmlWriter* writer, char* str);
static int owt_header_done(OmlWriter* writer);
static int owt_row_start(OmlWriter* writer, OmlMStream* ms, double now);
static int owt_row_cols(OmlWriter* writer, OmlValue* values, int value_count);
static int owt_row_end(OmlWriter* writer, OmlMStream* ms);
static OmlWriter* owt_close(OmlWriter* writer);

/**
 * \brief Create a new +OmlWriter+
 * \param file_name the destination file
 * \return a new +OmlWriter+
 */
OmlWriter*
text_writer_new(OmlOutStream* out_stream)
{
  assert(out_stream != NULL);

  OmlTextWriter* self = (OmlTextWriter *)xmalloc(sizeof(OmlTextWriter));
  memset(self, 0, sizeof(OmlTextWriter));
  //pthread_mutex_init(&self->lock, NULL);

  self->bufferedWriter = bw_create(out_stream->write, out_stream, omlc_instance->max_queue, 0);
  self->out_stream = out_stream;

  self->meta = owt_meta;
  self->header_done = owt_header_done;
  self->row_start = owt_row_start;
  self->row_end = owt_row_end;
  self->out = owt_row_cols;
  self->close = owt_close;


  return (OmlWriter*)self;
}
/**
 * \brief Definition of the meta function of the oml net writer
 * \param writer the net writer that will send the data to the server
 * \param str the string to send
 * \return 1 if successful, 0 otherwise
 */
static int owt_meta(OmlWriter* writer, char* str)
{
  OmlTextWriter* self = (OmlTextWriter*)writer;
  if (self->bufferedWriter == NULL) return 0;

  MString *mstr = mstring_create();
  mstring_set (mstr, str);
  mstring_cat (mstr, "\n");
  bw_push_meta(self->bufferedWriter, (uint8_t*)mstring_buf (mstr), mstring_len (mstr));

  mstring_delete (mstr);
  return 1;
}

/**
 * \brief finish the writing of the first information
 * \param writer the writer that write this information
 * \return 1 if successful, 0 otherwise
 */
static int owt_header_done(OmlWriter* writer)
{
  return (owt_meta(writer, "content: text") && owt_meta(writer, ""));
}


/**
 * \brief write the result inside the file
 * \param writer pointer to writer instance
 * \param values type of sample
 * \param value_count size of above array
 * \return 1 if successful, 0 otherwise
 */
static int owt_row_cols(OmlWriter* writer, OmlValue* values, int value_count)
{
  OmlTextWriter* self = (OmlTextWriter*)writer;
  MBuffer* mbuf;
  if ((mbuf = self->mbuf) == NULL) return 0; /* previous use of mbuf failed */

  int i;
  OmlValue* v = values;
  for (i = 0; i < value_count; i++, v++) {
    int res;
    switch (oml_value_get_type(v)) {
    case OML_LONG_VALUE: {
      res = mbuf_print(mbuf, "\t%" PRId32, oml_value_clamp_long (v->value.longValue));
      break;
    }
    case OML_INT32_VALUE:  res = mbuf_print(mbuf, "\t%" PRId32,  v->value.int32Value);  break;
    case OML_UINT32_VALUE: res = mbuf_print(mbuf, "\t%" PRIu32,  v->value.uint32Value); break;
    case OML_INT64_VALUE:  res = mbuf_print(mbuf, "\t%" PRId64,  v->value.int64Value);  break;
    case OML_UINT64_VALUE: res = mbuf_print(mbuf, "\t%" PRIu64,  v->value.uint64Value); break;
    case OML_DOUBLE_VALUE: res = mbuf_print(mbuf, "\t%f",  v->value.doubleValue); break;
    case OML_STRING_VALUE: {
      OmlValueU *u = oml_value_get_value(v);
      char *n = alloca(backslash_encode_size(omlc_get_string_size(*u)));
      backslash_encode(omlc_get_string_ptr(*u), n);
      res = mbuf_print(mbuf, "\t%s", n);
      break;
    }
    case OML_BLOB_VALUE: {
      if(NULL == v->value.blobValue.ptr || 0 == v->value.blobValue.length)
        logwarn ("Attempting to send NULL or empty blob; blob of length 0 will be sent\n");

      size_t enc_sz = base64_size_string(v->value.blobValue.length);
      char *enc = alloca(enc_sz);
      base64_encode_blob(v->value.blobValue.length, v->value.blobValue.ptr, enc);
      res = mbuf_print(mbuf, "\t%s", enc);
      break;
    }
    default:
      res = -1;
      logerror( "Unsupported value type '%d'\n", oml_value_get_type(v));
      return 0;
    }
    if (res < 0) {
      mbuf_reset_write(mbuf);
      self->mbuf = NULL;
      return 0;
    }
  }<commit_msg>Clean up NULL pointer case in text_writer.c<commit_after>/*
 * Copyright 2007-2013 National ICT Australia (NICTA), Australia
 *
 * This software may be used and distributed solely under the terms of
 * the MIT license (License).  You should find a copy of the License in
 * LICENSE.TXT or at http://opensource.org/licenses/MIT. By downloading
 * or using this software you accept the terms and the liability
 * disclaimer in the License.
 */

/*!\file text_writer.c
  \brief Implements a writer which stores results in a local file.
*/

#include <alloca.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>

#include "oml2/omlc.h"
#include "oml2/oml_filter.h"
#include "oml2/oml_writer.h"
#include "ocomm/o_log.h"
#include "oml_value.h"
#include "client.h"
#include "buffered_writer.h"
#include "string_utils.h"
#include "base64.h"

typedef struct {

  oml_writer_meta meta;
  oml_writer_header_done header_done;


  //! Called before and after writing individual
  // filter results with 'out'
  oml_writer_row_start row_start;
  oml_writer_row_end row_end;

  //! Writing a result.
  oml_writer_out out;

  oml_writer_close close;

  OmlWriter* next;

  //----------------------------

  BufferedWriterHdl bufferedWriter;
  MBuffer* mbuf;        /* Pointer to active buffer from bufferedWriter */
  OmlOutStream* out_stream;
} OmlTextWriter;


static int owt_meta(OmlWriter* writer, char* str);
static int owt_header_done(OmlWriter* writer);
static int owt_row_start(OmlWriter* writer, OmlMStream* ms, double now);
static int owt_row_cols(OmlWriter* writer, OmlValue* values, int value_count);
static int owt_row_end(OmlWriter* writer, OmlMStream* ms);
static OmlWriter* owt_close(OmlWriter* writer);

/**
 * \brief Create a new +OmlWriter+
 * \param file_name the destination file
 * \return a new +OmlWriter+
 */
OmlWriter*
text_writer_new(OmlOutStream* out_stream)
{
  assert(out_stream != NULL);

  OmlTextWriter* self = (OmlTextWriter *)xmalloc(sizeof(OmlTextWriter));
  memset(self, 0, sizeof(OmlTextWriter));
  //pthread_mutex_init(&self->lock, NULL);

  self->bufferedWriter = bw_create(out_stream->write, out_stream, omlc_instance->max_queue, 0);
  self->out_stream = out_stream;

  self->meta = owt_meta;
  self->header_done = owt_header_done;
  self->row_start = owt_row_start;
  self->row_end = owt_row_end;
  self->out = owt_row_cols;
  self->close = owt_close;


  return (OmlWriter*)self;
}
/**
 * \brief Definition of the meta function of the oml net writer
 * \param writer the net writer that will send the data to the server
 * \param str the string to send
 * \return 1 if successful, 0 otherwise
 */
static int owt_meta(OmlWriter* writer, char* str)
{
  OmlTextWriter* self = (OmlTextWriter*)writer;
  if (self->bufferedWriter == NULL) return 0;

  MString *mstr = mstring_create();
  mstring_set (mstr, str);
  mstring_cat (mstr, "\n");
  bw_push_meta(self->bufferedWriter, (uint8_t*)mstring_buf (mstr), mstring_len (mstr));

  mstring_delete (mstr);
  return 1;
}

/**
 * \brief finish the writing of the first information
 * \param writer the writer that write this information
 * \return 1 if successful, 0 otherwise
 */
static int owt_header_done(OmlWriter* writer)
{
  return (owt_meta(writer, "content: text") && owt_meta(writer, ""));
}


/**
 * \brief write the result inside the file
 * \param writer pointer to writer instance
 * \param values type of sample
 * \param value_count size of above array
 * \return 1 if successful, 0 otherwise
 */
static int owt_row_cols(OmlWriter* writer, OmlValue* values, int value_count)
{
  OmlTextWriter* self = (OmlTextWriter*)writer;
  MBuffer* mbuf;
  if ((mbuf = self->mbuf) == NULL) return 0; /* previous use of mbuf failed */

  int i;
  OmlValue* v = values;
  for (i = 0; i < value_count; i++, v++) {
    int res;
    switch (oml_value_get_type(v)) {
    case OML_LONG_VALUE: {
      res = mbuf_print(mbuf, "\t%" PRId32, oml_value_clamp_long (v->value.longValue));
      break;
    }
    case OML_INT32_VALUE:  res = mbuf_print(mbuf, "\t%" PRId32,  v->value.int32Value);  break;
    case OML_UINT32_VALUE: res = mbuf_print(mbuf, "\t%" PRIu32,  v->value.uint32Value); break;
    case OML_INT64_VALUE:  res = mbuf_print(mbuf, "\t%" PRId64,  v->value.int64Value);  break;
    case OML_UINT64_VALUE: res = mbuf_print(mbuf, "\t%" PRIu64,  v->value.uint64Value); break;
    case OML_DOUBLE_VALUE: res = mbuf_print(mbuf, "\t%f",  v->value.doubleValue); break;
    case OML_STRING_VALUE: {
      if(v->value.stringValue.ptr && 0 < v->value.stringValue.length) {
        char *enc = alloca(backslash_encode_size(omlc_get_string_size(v->value)));
        backslash_encode(omlc_get_string_ptr(v->value), enc);
        res = mbuf_print(mbuf, "\t%s", enc);
      } else {
        logwarn ("Attempting to send NULL or empty string; string of length 0 will be sent\n");
        res = mbuf_print(mbuf, "\t");
      }
      break;
    }
    case OML_BLOB_VALUE: {
      if(v->value.blobValue.ptr && 0 < v->value.blobValue.length) {
        char *enc = alloca(base64_size_string(v->value.blobValue.length));
        base64_encode_blob(v->value.blobValue.length, v->value.blobValue.ptr, enc);
        res = mbuf_print(mbuf, "\t%s", enc);
      } else {
        logwarn ("Attempting to send NULL or empty blob; blob of length 0 will be sent\n");
        res = mbuf_print(mbuf, "\t");
      }
      break;
    }
    default:
      res = -1;
      logerror( "Unsupported value type '%d'\n", oml_value_get_type(v));
      return 0;
    }
    if (res < 0) {
      mbuf_reset_write(mbuf);
      self->mbuf = NULL;
      return 0;
    }
  }
{'fraction_non_alphanumeric': 0.12839125306233554, 'fraction_numerical': 0.01143271935396062, 'mean_word_length': 3.730472103004292, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '322935', 'n_tokens_mistral': 4040, 'n_tokens_neox': 3878, 'n_words': 1045}