2016-07-19 7 views
0

Mein Freund und ich haben vor einer Weile daran gearbeitet. Es ist für die Verwendung mit js-ctypes gedacht. In Linux gibt es diese Makros für das Hinzufügen einer Liste von Dateideskriptoren (uint32's) zu Byte-Array: FD_SET und FD_IS_SET. Die Dokumente sind hier - http://linux.die.net/man/2/selectFD_SET und FD_ISSET Makros geschrieben in Javascript

Ich fragte mich, ob jemand in der Lage wäre zu überprüfen, ob ich das richtig gemacht habe oder weiß jemand von jemandem, der dies in Javascript getan hat? Ich muss die 32bit/64bit-Unterstützung für große und kleine Endianer abschließen, aber wenn es schon da draußen ist, würde ich es gerne sehen, als wir bei der Arbeit so viele Unsicherheiten hatten.

Hier ist der Code, der fd_set_get_idx war die Hilfsfunktion, auf der alles basiert.

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

Was ist los mit guten alten '' '' '' '' '' '' ' –

+1

Auch könnte eine' for' Schleife dort verwenden ... –

+1

Ich kann nicht verstehen, wenn Sie nur wollen Emulieren Sie die 'FD_XXX'-Funktionen oder wenn Sie mit etwas konform sein müssen.JS, speziell ES6, hat [DataView] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/DataView) und [typisierte Arrays] (https://developer.mozilla.org/ de-DE/docs/Web/JavaScript/Referenz/Global_Objects/TypedArray), wenn Sie sie verwenden möchten. Jedenfalls, wenn die Semantik von 'FD_SET (i, set)' nur 'set [i] = i' ist, sehe ich kein Problem darin, es in irgendeiner Endianess oder Größe von Grund auf neu zu implementieren. Könntest Du das erläutern? Auch dieses 'fdset [elem8] = 1 << bitpos8' ist wahrscheinlich falsch. –

Antwort

1

Ich überlasse die Last, die Endianness und die Wortgröße zu identifizieren.
Der folgende Code emuliert die FD_XXX Funktionen und lässt Sie die Endianess und die Größe angeben.

<!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> 

Die fdset Funktion zurückgeben ein Uint8Array, die Sie auf eine native Funktion oder näher ausgestalten passieren kann.
legt den maximalen unterstützten Dateideskriptor fest.


Beachten Sie, dass js ctypes bereits ein Array-Typ hat und die üblichen [U]intXX_t Typen in der nativen endianness, ach da kein Typ ist, der auf 32/64 Bit ganzen Zahlen Karte basiert auf der Plattform und es gibt nicht ein sizeof Operator , so müssen Sie noch eine externe Überprüfung durchführen, um die Wortgröße zu erkennen.

Mit ctypes wäre natürlicher.
Zu Referenzzwecken here ist die offizielle Implementierung der FD_XXX Funktionen.

Sie könnten einen struct mit einem einzelnen Feld des Typs array von uint32/64_t definieren.
Dann imitieren Sie dann das Verhalten des C-Quellcodes und achten Sie darauf, bei Bedarf UInt64 zu verwenden und shifts zu vermeiden.


JS hat nur Doppelnummern haben diese Zahlen 53 Bits der Mantisse 10 Bit des Exponenten und 1 Bit von Zeichen. Wenn die Bitoperatoren verwendet werden, wird die doppelte Zahl in eine ganze Zahl umgewandelt, da es die Mantisse ist, die die Genauigkeit angibt (Exponent ist nur eine Skala, Zeichen nur eine Inversion), diese Zahl kann höchstens soviel Information wie 53 Bits tragen Nummer.

Dass ich mir bewusst bin, bin ich überhaupt kein Experte in js ctypes.

+0

Wow a Herzlichen Dank für diese Mühe! Ich erinnere mich an letzte, als ich daran arbeitete, ertrank ich beim Lesen dieser Links - https://gist.github.com/Noitidart/5ddc5fe43dd9b0d5a207d0f70d72efc4 - Ich überprüfe Ihren Code jetzt! :) – Noitidart

+1

@Noitidart Sie sind willkommen. Überprüfen Sie es, ich bin mir nicht sicher, ob ich Ihre Bedürfnisse wirklich verstanden habe! –

+0

Ich muss zugeben, ich hatte eigentlich keine Ahnung, was der Code oben tat. Ich habe es von einem anderen js-ctypes-Projekt kopiert. Ich habe es so formuliert, als ob ich es mit einem Freund gemacht hätte, weil ich befürchtete, dass das geschlossen würde und ich keine Hilfe finden konnte. Ich bin ein Js-Coder, der das C-Zeug zu js portieren kann, wenn es 1 zu 1 ist. Endlichkeit, 32 Bit und 64 Bit Sachen verstehe ich nicht. Hättest du gerne 30min Zeit, um stayoverflow Chat über diesen Code zu benutzen? Ich benutze es in Ctypes, also übergebe ich es an tatsächliche Plattform C apis, also ist der Puffer, was ich brauchte. Aber ich bin von Anfang an verwirrt, einschließlich der Größe. :( – Noitidart