<commit_before>#include "./input_reader.h"
#include <v8.h>
#include <nan.h>
#include <tree_sitter/runtime.h>

namespace node_tree_sitter {

using namespace v8;

struct InputReader {
  v8::Persistent<v8::Object> object;
  char *buffer;

 public:
  InputReader(char *buffer) :
    buffer(buffer)
    {}
};

static int Seek(void *data, size_t position) {
  InputReader *reader = (InputReader *)data;
  Handle<Function> fn = Handle<Function>::Cast(NanNew(reader->object)->Get(NanNew<String>("seek")));
  if (!fn->IsFunction())
    return 0;

  Handle<Value> argv[1] = { NanNew<Integer>(position) };
  Handle<Number> result = Handle<Number>::Cast(fn->Call(NanNew(reader->object), 1, argv));
  return result->NumberValue();
}

static void Release(void *data) {
  InputReader *reader = (InputReader *)data;
  delete reader->buffer;
}

static const char * Read(void *data, size_t *bytes_read) {
  InputReader *reader = (InputReader *)data;
  Handle<Function> read_fn = Handle<Function>::Cast(NanNew(reader->object)->Get(NanNew<String>("read")));
  if (!read_fn->IsFunction())
    return "";

  Handle<String> result = Handle<String>::Cast(read_fn->Call(NanNew(reader->object), 0, NULL));
  if (!result->IsString())
    return "";
  *bytes_read = result->WriteUtf8(reader->buffer, 1024, NULL, 2);
  return reader->buffer;
}

TSInput InputReaderMake(Local<Object> object) {
  TSInput result;
  InputReader *reader = new InputReader(new char[1024]);
  NanAssignPersistent(reader->object, object);
  result.data = (void *)reader;
  result.seek_fn = Seek;
  result.read_fn = Read;<commit_msg>Always assign bytes_read in input reader<commit_after>#include "./input_reader.h"
#include <v8.h>
#include <nan.h>
#include <tree_sitter/runtime.h>

namespace node_tree_sitter {

using namespace v8;

struct InputReader {
  v8::Persistent<v8::Object> object;
  char *buffer;

 public:
  InputReader(char *buffer) :
    buffer(buffer)
    {}
};

static int Seek(void *data, size_t position) {
  InputReader *reader = (InputReader *)data;
  Handle<Function> fn = Handle<Function>::Cast(NanNew(reader->object)->Get(NanNew<String>("seek")));
  if (!fn->IsFunction())
    return 0;

  Handle<Value> argv[1] = { NanNew<Integer>(position) };
  Handle<Number> result = Handle<Number>::Cast(fn->Call(NanNew(reader->object), 1, argv));
  return result->NumberValue();
}

static void Release(void *data) {
  InputReader *reader = (InputReader *)data;
  delete reader->buffer;
}

static const char * Read(void *data, size_t *bytes_read) {
  InputReader *reader = (InputReader *)data;
  Handle<Function> read_fn = Handle<Function>::Cast(NanNew(reader->object)->Get(NanNew<String>("read")));
  if (!read_fn->IsFunction()) {
    *bytes_read = 0;
    return "";
  }

  Handle<String> result = Handle<String>::Cast(read_fn->Call(NanNew(reader->object), 0, NULL));
  if (!result->IsString()) {
    *bytes_read = 0;
    return "";
  }

  *bytes_read = result->WriteUtf8(reader->buffer, 1024, NULL, 2);
  return reader->buffer;
}

TSInput InputReaderMake(Local<Object> object) {
  TSInput result;
  InputReader *reader = new InputReader(new char[1024]);
  NanAssignPersistent(reader->object, object);
  result.data = (void *)reader;
  result.seek_fn = Seek;
  result.read_fn = Read;
{'fraction_non_alphanumeric': 0.16604938271604938, 'fraction_numerical': 0.011728395061728396, 'mean_word_length': 5.220729366602687, 'pattern_counts': {'":': 0, '<': 37, '<?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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5961518', 'n_tokens_mistral': 1126, 'n_tokens_neox': 1082, 'n_words': 230}