<commit_before>#include <libexif/exif-data.h>
#include <time.h>
#include "data.h"

extern VALUE rb_mExif;
VALUE rb_cData;
static VALUE IFD2SYM[5];

void init_data(){
  rb_cData = rb_define_class_under(rb_mExif, "Data", rb_cObject);
  IFD2SYM[EXIF_IFD_0]                = INT2NUM(0);
  IFD2SYM[EXIF_IFD_1]                = INT2NUM(1);
  IFD2SYM[EXIF_IFD_EXIF]             = ID2SYM(rb_intern("exif"));
  IFD2SYM[EXIF_IFD_GPS]              = ID2SYM(rb_intern("gps"));
  IFD2SYM[EXIF_IFD_INTEROPERABILITY] = ID2SYM(rb_intern("interoperability"));
  int length = sizeof(attrs) / sizeof(char*);
  for(int i = 0; i < length; ++i) rb_define_attr(rb_cData, attrs[i], 1, 0);
  rb_define_attr(rb_cData, "contents", 1, 0);
  rb_define_alias(rb_cData, "to_h", "contents");
  rb_define_singleton_method(rb_cData, "new", rb_new, 1);
  rb_define_method(rb_cData, "dump", rb_dump, 0);
  rb_define_method(rb_cData, "[]", rb_value, 1);
}

static VALUE rb_new(VALUE self, VALUE file_path){
  Check_Type(file_path, T_STRING);
  ExifData *ed = exif_data_new_from_file(StringValueCStr(file_path));
  if(!ed) rb_raise(rb_eRuntimeError, "File not readable or no EXIF data in file.");
  VALUE rb_data = Data_Wrap_Struct(self, NULL, exif_data_free, ed);
  rb_iv_set(rb_data, "@contents", rb_hash_new());
  exif_data_foreach_content(ed, each_content, &rb_data);
  return rb_data;
}

static VALUE rb_dump(VALUE self){
  ExifData *ed;
  Data_Get_Struct(self, ExifData, ed);
  exif_data_dump(ed);
  return Qnil;
}

static VALUE rb_value(VALUE self, VALUE key){
  VALUE rb_contents = rb_iv_get(self, "@contents");
  return rb_hash_aref(rb_contents, key);
}

static void each_content(ExifContent *ec, void *self_ptr){
  VALUE *self = (VALUE*)self_ptr;
  VALUE rb_contents = rb_iv_get(*self, "@contents");
  Check_Type(rb_contents, T_HASH);
  ExifIfd ifd = exif_content_get_ifd(ec);
  VALUE ifd_name = IFD2SYM[ifd]; //rb_str_new_cstr(exif_ifd_get_name(ifd));
  if(ifd == EXIF_IFD_COUNT) rb_raise(rb_eRuntimeError, "Con't get IFD.");
  else rb_hash_aset(rb_contents, ifd_name, rb_hash_new());
  exif_content_foreach_entry(ec, each_entry, self);
}

static void each_entry(ExifEntry *ee, void *self_ptr){
  VALUE *self = (VALUE*)self_ptr;
  VALUE rb_contents = rb_iv_get(*self, "@contents");
  ExifIfd ifd = exif_entry_get_ifd(ee);
  char *attr_name = attr_string(ifd, ee->tag);
  VALUE tag_name = ID2SYM(rb_intern(attr_name + 1));
  char buf[500];
  exif_entry_get_value(ee, buf, sizeof(buf));
  VALUE value;
  switch(ee->format){
  // case EXIF_FORMAT_BYTE:
  //   break;
  // case EXIF_FORMAT_ASCII:
  //   break;
  case EXIF_FORMAT_SHORT:
    value = INT2NUM(atoi(buf));
    break;
  case EXIF_FORMAT_LONG:
    value = INT2NUM(atol(buf));
    break;
  // case EXIF_FORMAT_RATIONAL:
  //   break;
  // case EXIF_FORMAT_SBYTE:
  //   break;
  // case EXIF_FORMAT_UNDEFINED:
  //   break;
  // case EXIF_FORMAT_SSHORT:
  //   break;
  // case EXIF_FORMAT_SLONG:
  //   break;
  // case EXIF_FORMAT_SRATIONAL:
  //   break;
  case EXIF_FORMAT_FLOAT:
    value = rb_float_new(atof(buf));
    break;
  case EXIF_FORMAT_DOUBLE:
    value = rb_float_new(atof(buf));
    break;
  default:
    value = process_value(self, ee->tag, buf);
  }
  rb_hash_aset(rb_hash_aref(rb_contents, IFD2SYM[ifd]), tag_name, value);
  rb_hash_aset(rb_contents, tag_name, value);
  rb_iv_set(*self, attr_name, value);
}

static VALUE process_value(VALUE *self_ptr, ExifTag tag, char *buf){
  ExifData *ed;
  Data_Get_Struct(*self_ptr, ExifData, ed);
  switch((int)tag){
  case EXIF_TAG_DATE_TIME:
  case EXIF_TAG_DATE_TIME_ORIGINAL:
  case EXIF_TAG_DATE_TIME_DIGITIZED:
  {
    int i;<commit_msg>unused i<commit_after>#include <libexif/exif-data.h>
#include <time.h>
#include "data.h"

extern VALUE rb_mExif;
VALUE rb_cData;
static VALUE IFD2SYM[5];

void init_data(){
  rb_cData = rb_define_class_under(rb_mExif, "Data", rb_cObject);
  IFD2SYM[EXIF_IFD_0]                = INT2NUM(0);
  IFD2SYM[EXIF_IFD_1]                = INT2NUM(1);
  IFD2SYM[EXIF_IFD_EXIF]             = ID2SYM(rb_intern("exif"));
  IFD2SYM[EXIF_IFD_GPS]              = ID2SYM(rb_intern("gps"));
  IFD2SYM[EXIF_IFD_INTEROPERABILITY] = ID2SYM(rb_intern("interoperability"));
  int length = sizeof(attrs) / sizeof(char*);
  for(int i = 0; i < length; ++i) rb_define_attr(rb_cData, attrs[i], 1, 0);
  rb_define_attr(rb_cData, "contents", 1, 0);
  rb_define_alias(rb_cData, "to_h", "contents");
  rb_define_singleton_method(rb_cData, "new", rb_new, 1);
  rb_define_method(rb_cData, "dump", rb_dump, 0);
  rb_define_method(rb_cData, "[]", rb_value, 1);
}

static VALUE rb_new(VALUE self, VALUE file_path){
  Check_Type(file_path, T_STRING);
  ExifData *ed = exif_data_new_from_file(StringValueCStr(file_path));
  if(!ed) rb_raise(rb_eRuntimeError, "File not readable or no EXIF data in file.");
  VALUE rb_data = Data_Wrap_Struct(self, NULL, exif_data_free, ed);
  rb_iv_set(rb_data, "@contents", rb_hash_new());
  exif_data_foreach_content(ed, each_content, &rb_data);
  return rb_data;
}

static VALUE rb_dump(VALUE self){
  ExifData *ed;
  Data_Get_Struct(self, ExifData, ed);
  exif_data_dump(ed);
  return Qnil;
}

static VALUE rb_value(VALUE self, VALUE key){
  VALUE rb_contents = rb_iv_get(self, "@contents");
  return rb_hash_aref(rb_contents, key);
}

static void each_content(ExifContent *ec, void *self_ptr){
  VALUE *self = (VALUE*)self_ptr;
  VALUE rb_contents = rb_iv_get(*self, "@contents");
  Check_Type(rb_contents, T_HASH);
  ExifIfd ifd = exif_content_get_ifd(ec);
  VALUE ifd_name = IFD2SYM[ifd]; //rb_str_new_cstr(exif_ifd_get_name(ifd));
  if(ifd == EXIF_IFD_COUNT) rb_raise(rb_eRuntimeError, "Con't get IFD.");
  else rb_hash_aset(rb_contents, ifd_name, rb_hash_new());
  exif_content_foreach_entry(ec, each_entry, self);
}

static void each_entry(ExifEntry *ee, void *self_ptr){
  VALUE *self = (VALUE*)self_ptr;
  VALUE rb_contents = rb_iv_get(*self, "@contents");
  ExifIfd ifd = exif_entry_get_ifd(ee);
  char *attr_name = attr_string(ifd, ee->tag);
  VALUE tag_name = ID2SYM(rb_intern(attr_name + 1));
  char buf[500];
  exif_entry_get_value(ee, buf, sizeof(buf));
  VALUE value;
  switch(ee->format){
  // case EXIF_FORMAT_BYTE:
  //   break;
  // case EXIF_FORMAT_ASCII:
  //   break;
  case EXIF_FORMAT_SHORT:
    value = INT2NUM(atoi(buf));
    break;
  case EXIF_FORMAT_LONG:
    value = INT2NUM(atol(buf));
    break;
  // case EXIF_FORMAT_RATIONAL:
  //   break;
  // case EXIF_FORMAT_SBYTE:
  //   break;
  // case EXIF_FORMAT_UNDEFINED:
  //   break;
  // case EXIF_FORMAT_SSHORT:
  //   break;
  // case EXIF_FORMAT_SLONG:
  //   break;
  // case EXIF_FORMAT_SRATIONAL:
  //   break;
  case EXIF_FORMAT_FLOAT:
    value = rb_float_new(atof(buf));
    break;
  case EXIF_FORMAT_DOUBLE:
    value = rb_float_new(atof(buf));
    break;
  default:
    value = process_value(self, ee->tag, buf);
  }
  rb_hash_aset(rb_hash_aref(rb_contents, IFD2SYM[ifd]), tag_name, value);
  rb_hash_aset(rb_contents, tag_name, value);
  rb_iv_set(*self, attr_name, value);
}

static VALUE process_value(VALUE *self_ptr, ExifTag tag, char *buf){
  ExifData *ed;
  Data_Get_Struct(*self_ptr, ExifData, ed);
  switch((int)tag){
  case EXIF_TAG_DATE_TIME:
  case EXIF_TAG_DATE_TIME_ORIGINAL:
  case EXIF_TAG_DATE_TIME_DIGITIZED:
  {
{'fraction_non_alphanumeric': 0.13306674020959736, 'fraction_numerical': 0.009100937672366244, 'mean_word_length': 4.702044025157233, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 13, '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': '2305534', 'n_tokens_mistral': 3059, 'n_tokens_neox': 3002, 'n_words': 540}