2016-07-19 1 views
0

Мы с вами работали некоторое время назад. Он предназначен для использования с js-ctypes. В Linux есть эти макросы для работы с добавлением списка файловых дескрипторов (uint32) в массив байтов: FD_SET и FD_IS_SET. Документы здесь - http://linux.die.net/man/2/selectМакросы FD_SET и FD_ISSET, написанные на javascript

Мне было интересно, сможет ли кто-нибудь проверить, правильно ли я сделал это или кто-нибудь знает кого-либо, кто сделал это в javascript? Мне нужно завершить 32-битную/64-битную поддержку для большого и маленького endian, но если она уже там, мне бы очень хотелось ее увидеть, так как когда мы работали над этим, у нас было так много неопределенностей.

Код, fd_set_get_idx был вспомогательной функцией, это все на основе.

var MACROS = { 
     fd_set_set: function(fdset, fd) { 
      let { elem8, bitpos8 } = MACROS.fd_set_get_idx(fd); 
      console.info('elem8:', elem8.toString()); 
      console.info('bitpos8:', bitpos8.toString()); 
      fdset[elem8] = 1 << bitpos8; 
     }, 
     fd_set_isset: function(fdset, fd) { 
      let { elem8, bitpos8 } = MACROS.fd_set_get_idx(fd); 
      console.info('elem8:', elem8.toString()); 
      console.info('bitpos8:', bitpos8.toString()); 
      return !!(fdset[elem8] & (1 << bitpos8)); 
     }, 
    fd_set_get_idx: function(fd) { 
      if (osname == 'darwin' /*is_mac*/) { 
       // We have an array of int32. This should hopefully work on Darwin 
       // 32 and 64 bit. 
       let elem32 = Math.floor(fd/32); 
       let bitpos32 = fd % 32; 
       let elem8 = elem32 * 8; 
       let bitpos8 = bitpos32; 
       if (bitpos8 >= 8) {  // 8 
        bitpos8 -= 8; 
        elem8++; 
       } 
       if (bitpos8 >= 8) {  // 16 
        bitpos8 -= 8; 
        elem8++; 
       } 
       if (bitpos8 >= 8) {  // 24 
        bitpos8 -= 8; 
        elem8++; 
       } 

       return {'elem8': elem8, 'bitpos8': bitpos8}; 
      } else { // else if (osname == 'linux' /*is_linux*/) { // removed the else if so this supports bsd and solaris now 
       // :todo: add 32bit support 
       // Unfortunately, we actually have an array of long ints, which is 
       // a) platform dependent and b) not handled by typed arrays. We manually 
       // figure out which byte we should be in. We assume a 64-bit platform 
       // that is little endian (aka x86_64 linux). 
       let elem64 = Math.floor(fd/64); 
       let bitpos64 = fd % 64; 
       let elem8 = elem64 * 8; 
       let bitpos8 = bitpos64; 
       if (bitpos8 >= 8) {  // 8 
        bitpos8 -= 8; 
        elem8++; 
       } 
       if (bitpos8 >= 8) {  // 16 
        bitpos8 -= 8; 
        elem8++; 
       } 
       if (bitpos8 >= 8) {  // 24 
        bitpos8 -= 8; 
        elem8++; 
       } 
       if (bitpos8 >= 8) {  // 32 
        bitpos8 -= 8; 
        elem8++; 
       } 
       if (bitpos8 >= 8) {  // 40 
        bitpos8 -= 8; 
        elem8++; 
       } 
       if (bitpos8 >= 8) {  // 48 
        bitpos8 -= 8; 
        elem8++; 
       } 
       if (bitpos8 >= 8) {  // 56 
        bitpos8 -= 8; 
        elem8++; 
       } 

       return {'elem8': elem8, 'bitpos8': bitpos8}; 
      } 
     } 
}; 
+1

Что не так с добрыми старыми '>>', '<<' и '&', '|' –

+1

Кроме того, можно использовать цикл 'for' ... –

+1

Я не могу понять, если вы просто хотите эмулировать функции «FD_XXX» или если вам что-то нужно.JS, особенно ES6, имеет [DataView] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/DataView) и [типизированные массивы] (https://developer.mozilla.org/ ru-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), если вы хотите их использовать. Во всяком случае, если семантика 'FD_SET (i, set)' просто 'set [i] = i' Я не вижу никаких проблем при ее реализации, в любой endianess или размере, с нуля. Вы можете уточнить? Кроме того, это 'fdset [elem8] = 1 << bitpos8', скорее всего, неверно. –

ответ

1

Я оставляю бремя идентификации континентности и размера слова для вас.
Приведенный ниже код эмулирует функции FD_XXX и позволяет указать контурность и размер.

<!doctype> 
<html> 
    <head> 
     <script> 
      var SIZE_32 = 4 
      var SIZE_64 = 8 

      var LITTLE_ENDIAN = [0, 1, 2, 3, 4, 5, 6, 7]; 
      var BIG_ENDIAN = [7, 6, 5, 4, 3, 2, 1, 0]; 

      function fdset(setSize, endianness, size) 
      { 
       var buffer = new Uint8Array(div(setSize + 7, 8)); 



       function div(a, b) 
       { 
        return Math.floor(a/b); 
       } 

       function make_index(index) 
       { 
        return div(index, 8 * size) * size + endianness[div(index % (8 * size), 8)] % size; 
       } 

       buffer.set_bit = function(index) 
       { 
        buffer[make_index(index)] |= 1 << (index % 8); 
       }; 

       buffer.clear_bit = function(index) 
       { 
        buffer[make_index(index)] &= ~(index % 8); 
       }; 

       buffer.get_bit = function(index) 
       { 
        return buffer[make_index(index)] & 1 << (index % 8); 
       }; 

       buffer.zero = function() 
       { 
        buffer.fill(0); 
       } 


       return buffer; 
      } 

      function FD_SET(fd, fdset) 
      { 
       fdset.set_bit(fd); 
      } 

      function FD_ISSET(fd, fdset) 
      { 
       return !!fdset.get_bit(fd); 
      } 

      function FD_CLR(fd, fdset) 
      { 
       return fdset.clear_bit(fd); 
      } 

      function FD_ZERO(fdset) 
      { 
       return fdset.zero(); 
      } 


     </script> 
    </head> 
    <body> 
     <script> 
      var s = fdset(128, LITTLE_ENDIAN, SIZE_64); 

      //s in an Uint8Array 

      console.log(s); 

      FD_SET(0, s); //Byte 0 = 1 
      FD_SET(9, s); //Byte 1 = 2 
      FD_SET(18, s); //Byte 2 = 4 
      FD_SET(27, s); //Byte 3 = 8 
      FD_SET(36, s); //Byte 4 = 16 
      FD_SET(45, s); //Byte 5 = 32 
      FD_SET(54, s); //Byte 6 = 64 
      FD_SET(63, s); //Byte 7 = 128 

      FD_SET(120, s); //Byte 15 = 1 
      FD_SET(113, s); //Byte 14 = 2 
      FD_SET(106, s); //Byte 13 = 4 
      FD_SET(99, s); //Byte 12 = 8 
      FD_SET(92, s); //Byte 11 = 16 
      FD_SET(85, s); //Byte 10 = 32 
      FD_SET(78, s); //Byte 9 = 64 
      FD_SET(71, s); //Byte 8 = 128 

      console.log(s); 

      //64 bits, BE: [128, 64, 32, 16, 8, 4, 2, 1, 1, 2, 4, 8, 16, 32, 64, 128] 
      //64 bits, LE: [1, 2, 4, 8, 16, 32, 64, 128, 128, 64, 32, 16, 8, 4, 2, 1] 
      //32 bits, BE: [8, 4, 2, 1, 128, 64, 32, 16, 16, 32, 64, 128, 1, 2, 4, 8] 
      //32 bits, LE: [1, 2, 4, 8, 16, 32, 64, 128, 128, 64, 32, 16, 8, 4, 2, 1] 
     </script> 
    </body> 
</html> 

fdset функция возвращать Uint8Array, что вы можете перейти к нативной функции или доработать.
setSize устанавливает максимальный файловый дескриптор.


Обратите внимание, что JS ctypes уже имеет тип массива и обычные [U]intXX_t типов в родном порядке байт, увы нет типа отображающих 32/64 битых целых чисел, основанных на платформе и не существует a sizeof оператор , поэтому вам все равно необходимо выполнить внешнюю проверку, чтобы определить размер слова.

Использование ctypes было бы более естественным.
Для справочной цели here является официальной реализацией функций FD_XXX.

Вы можете определить struct с одним полем типа array из uint32/64_t.
Затем имитируйте поведение исходного кода C, стараясь при необходимости использовать UInt64 и избегая shifts.


JS имеет только двойные номера, эти числа имеют 53 бита мантиссы, 10 бит экспоненты и 1 бит знака. Когда используются битовые операторы, двойной номер преобразуется в целое число, так как именно мантисса определяет точность (показатель экспоненты - это просто масштаб, знак только инверсия), это число может нести как можно больше информации, как 53 бит номер.

Это я знаю, я не специалист совсем в Js ctypes.

+0

Wow a искренне благодарю вас за эти усилия! Я помню, как последний раз, когда я работал над этим, я утонул в чтении этих ссылок - https://gist.github.com/Noitidart/5ddc5fe43dd9b0d5a207d0f70d72efc4 - я проверю ваш код прямо сейчас! :) – Noitidart

+1

@Noitidart Добро пожаловать. Дважды проверьте это, я не уверен, что я действительно понял ваши потребности! –

+0

Должен признаться, я действительно понятия не имел, что делал выше код. Я скопировал его из другого проекта js-ctypes. Я сформулировал это, как будто я сделал это с другом, потому что я беспокоился, что это закрывается, и я не мог найти никакой помощи. Я js-кодер, который может передавать материал C в js, если это 1 к 1. Я не понимаю endianess, 32bit и 64bit вещи. Хотели бы вы, например, 30 минут, чтобы использовать чат stackoverflow об этом коде? Я использую его в ctypes, поэтому передаю его на реальную платформу C apis, поэтому буфер нужен мне. Но я смущаюсь с самого начала, включая настройку размера. :( – Noitidart

 Смежные вопросы

  • Нет связанных вопросов^_^