<commit_before>var ffi = require('./ffi')
  , EventEmitter = require('events').EventEmitter
  , POINTER_SIZE = ffi.Bindings.POINTER_SIZE

/**
 * Represents a foreign function in another library. Manages all of the aspects
 * of function execution, including marshalling the data parameters for the
 * function into native types and also unmarshalling the return from function
 * execution.
 */

function ForeignFunction (ptr, returnType, types, async) {
  var numArgs = types.length
    , result = new ffi.Pointer(ffi.sizeOf(returnType))
    , argsList = new ffi.Pointer(numArgs * POINTER_SIZE)
    , cif = new ffi.CIF(returnType, types)
    , self = this

  // XXX: Remove
  this._cif = cif

  // allocate a storage area for each argument,
  // then write the pointer to the argument list
  var argputf = types.map(function (type, i) {
    var argPtr = argsList.seek(i * POINTER_SIZE)

    if (ffi.isStructType(type)) {
      return function (val) {
        argPtr.putPointer(val.ref())
      }
    }

    var valPtr = new ffi.Pointer(ffi.sizeOf(type))
    argPtr.putPointer(valPtr)

    if (type == 'string') {
      return function (val) {
        var ptr = ffi.Pointer.NULL
        if (typeof val !== 'undefined' && val !== null) {
          var len = Buffer.byteLength(val, 'utf8')
          ptr = new ffi.Pointer(len+1)
          ptr.putCString(val)
        }
        valPtr.putPointer(ptr)
      }
    } else if (type == 'pointer') {
      // Bypass the struct check for non-struct types
      return function (val) {
        valPtr._putPointer(val)
      }
    } else {
      // Generic type putter function
      var putCall = 'put' + ffi.TYPE_TO_POINTER_METHOD_MAP[type]
      return function (val) {
        valPtr[putCall](val)
      }
    }
  })

  var drefVal = ffi.derefValuePtrFunc(returnType)
    , caller = new ffi.Bindings.ForeignCaller(
        cif.getPointer()
      , ptr
      , argsList
      , result
      , async
    )

  this._proxy = function () {
    self // XXX: if this isn't in here, callbacks segfault. what.. the.. f?
    var alen = arguments.length

    if (alen !== numArgs) {
      throw new Error('Function arguments did not meet specification')
    }

    // write arguments to storage areas
    for (var i = 0; i < alen; i++) {
      argputf[i](arguments[i])
    }

    var r = caller.exec()

    if (async) {
      var emitter = new EventEmitter()
      r.on('success', function () {
        emitter.emit('success', drefVal(result))
      })
      return emitter
    }

    return drefVal(result)
  }
}
module.exports = ForeignFunction

/**
 * Returns a JavaScript Function proxy for this foreign function.
 */

ForeignFunction.prototype.getFunction = function getFunction () {
  return this._proxy
}

/**
 * Creates a new ForeignFunction instance and returns the JS proxy function.
 */

ForeignFunction.build = function build (ptr, returnType, types, async) {
  var ff = new ForeignFunction(ptr, returnType, types, async)
  return ff.getFunction()
}<commit_msg>Make ForeignFunction() return it's function directly.<commit_after>var ffi = require('./ffi')
  , EventEmitter = require('events').EventEmitter
  , POINTER_SIZE = ffi.Bindings.POINTER_SIZE

/**
 * Represents a foreign function in another library. Manages all of the aspects
 * of function execution, including marshalling the data parameters for the
 * function into native types and also unmarshalling the return from function
 * execution.
 */

function ForeignFunction (ptr, returnType, types, async) {
  var self = this
    , numArgs = types.length
    , drefVal = ffi.derefValuePtrFunc(returnType)
    , result = new ffi.Pointer(ffi.sizeOf(returnType))
    , argsList = new ffi.Pointer(numArgs * POINTER_SIZE)
    , cif = new ffi.CIF(returnType, types)
    , caller = new ffi.Bindings.ForeignCaller(
        cif.getPointer()
      , ptr
      , argsList
      , result
      , async
    )


  // XXX: Can't remove or shit segsaults... WTF....
  this._ = cif

  // allocate a storage area for each argument,
  // then write the pointer to the argument list
  var argputf = types.map(function (type, i) {
    var argPtr = argsList.seek(i * POINTER_SIZE)

    if (ffi.isStructType(type)) {
      return function (val) {
        argPtr.putPointer(val.ref())
      }
    }

    var valPtr = new ffi.Pointer(ffi.sizeOf(type))
    argPtr.putPointer(valPtr)

    if (type == 'string') {
      return function (val) {
        var ptr = ffi.Pointer.NULL
        if (typeof val !== 'undefined' && val !== null) {
          var len = Buffer.byteLength(val, 'utf8')
          ptr = new ffi.Pointer(len+1)
          ptr.putCString(val)
        }
        valPtr.putPointer(ptr)
      }
    } else if (type == 'pointer') {
      // Bypass the struct check for non-struct types
      return function (val) {
        valPtr._putPointer(val)
      }
    } else {
      // Generic type putter function
      var putCall = 'put' + ffi.TYPE_TO_POINTER_METHOD_MAP[type]
      return function (val) {
        valPtr[putCall](val)
      }
    }
  })

  var proxy = function () {
    self // XXX: if this isn't in here, callbacks segfault. what.. the.. f?

    if (arguments.length !== numArgs) {
      throw new Error('Function arguments did not meet specification')
    }

    // write arguments to storage areas
    for (var i=0; i<numArgs; i++) {
      argputf[i](arguments[i])
    }

    var r = caller.exec()

    if (async) {
      var emitter = new EventEmitter()
      r.on('success', function () {
        emitter.emit('success', drefVal(result))
      })
      return emitter
    }

    return drefVal(result)
  }

  // Backwards compat
  proxy.getFunction = function () { return this }

  return proxy
}
module.exports = ForeignFunction

/**
 * Creates a new ForeignFunction instance and returns the JS proxy function.
 */

ForeignFunction.build = function build (ptr, returnType, types, async) {
  var ff = new ForeignFunction(ptr, returnType, types, async)
  return ff.getFunction()
}
{'fraction_non_alphanumeric': 0.11335897007189433, 'fraction_numerical': 0.0010031767262999498, 'mean_word_length': 2.590636254501801, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': 1, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '81984', 'n_tokens_mistral': 1863, 'n_tokens_neox': 1811, 'n_words': 531}