Comparaison de la mémoire tampon dans Node.js

Je suis nouveau dans Node.js. Il n’y a pas de comparaison de tampon et je devrais utiliser des modules comme buffertools pour ces fonctionnalités.

Mais je vois un comportement assez étrange lorsque je compare des objects Buffer dans Node pur.

> var b1 = new Buffer([170]); > var b2 = new Buffer([171]); > b1  > b2  > b1  b1 > b2 false > b1 == b2 false 

et

 > var b1 = new Buffer([10]); > var b2 = new Buffer([14]); > b1  > b2  > b1 > b2 false > b1  b1 == b2 false 

Qu’est-ce qui se passe réellement sous le capot?

C’est comme ça que les opérateurs de comparaison travaillent sur les objects:

 var a = {}, b = {}; a === b; //false a == b; //false a > b; //false a < b; //false var c = { valueOf : function () { return 0; } }; var d = { valueOf : function () { return 1; } }; c === d; //false c == d; //false c > d; //false c < d; //true 

Sous la capuche

(sorte de)

Partie 1: Égalité

C'est la partie la plus facile. L'égalité abstraite ( == , spec ) et l'égalité ssortingcte ( === , spec ) vérifient si vous vous référez au même object (sorte de comparaison de références). Dans ce cas, ils ne le sont évidemment pas, ils répondent donc false ( == spec step 10, === spec step 7).

Par conséquent, dans les deux cas:

 b1 == b2 //false b1 === b2 //false 

Partie 2: La comparaison est de retour

Voici la partie intéressante. Regardons comment les opérateurs relationnels ( < et > ) sont définis . Suivons la chaîne d'appels dans les deux cas.

 x = b1 // y = b2 // //11.8.5 The Abstract Relational Comparison Algorithm (http://es5.github.com/#x11.8.5) Let px be the result of calling ToPrimitive(x, hint Number). Let py be the result of calling ToPrimitive(y, hint Number). //9.1 ToPrimitive (http://es5.github.com/#x9.1) InputType is Object, therefore we call the internal [[DefaultValue]] method with hint Number. //8.12.8 [[DefaultValue]] (hint) http://es5.github.com/#x8.12.8 We try and fetch the object's toSsortingng method. If it's defined, call it. 

Et nous avons atteint le point culminant: quelle est la méthode toSsortingng un tampon? La réponse se trouve au plus profond de l’intérieur de node.js. Si vous voulez, allez- y . Ce que nous pouvons découvrir sortingvialement est par expérimentation:

 > b1.toSsortingng() ' ' > b2.toSsortingng() ' ' 

d'accord, ça n'a pas été utile. Vous remarquerez que dans l'algorithme de comparaison relationnelle abstraite (quel grand nom de fantaisie pour < ), il existe une étape pour gérer les chaînes. Il les convertit simplement en leur valeur numérique - les codes de caractère. Faisons cela:

 > b1.toSsortingng().charCodeAt(0) 65533 > b2.toSsortingng().charCodeAt(0) 65533 

65533 est un nombre important. C'est la sum de deux carrés: 142^2 + 213^2 . Il s’agit également du caractère de remplacement Unicode, un caractère signifiant "Je ne sais pas ce qui s’est passé". C'est pourquoi son équivalent hexadécimal est FFFD.

Évidemment, 65533 === 65533 , donc:

 b1 < b2 //is b1.toString().charCodeAt(0) < b2.toString().charCodeAt(0) //is 65533 < 65533 //false b1 > b2 //following same logic as above, false 

Et c'est ça.

Mec, c'est quoi ce bordel?

D'accord, cela a dû être déroutant puisque mes efforts d'explication n'ont pas été bien réfléchis. Pour récapituler, voici ce qui s'est passé:

  1. Vous avez créé un tampon. Benjamin Gruenbaum m'a aidé à recréer votre cas de test en faisant:

    var b1 = new Buffer([170]), b2 = new Buffer([171]);

  2. Lors de la sortie vers la console, les valeurs sont converties en leur équivalent hexadécimal (voir Tampon # inspect ):

    170..toSsortingng(16) === 'aa'

    171..toSsortingng(16) === 'ab'

  3. Cependant, en interne, ils représentaient des caractères non valides (puisqu'il ne s'agit pas d'un encodage hexadécimal; encore une fois, vous êtes libre de plonger dans l'implémentation de la mise en œuvre, je ne le ferai pas (oh ironie)). Par conséquent, une fois convertis en chaîne, ils étaient représentés avec le caractère de remplacement Unicode.

  4. Puisqu'ils sont des objects différents, tout opérateur d'égalité retournera false .

  5. Cependant, en raison de la façon dont ils travaillaient moins et plus que leur travail, ils ont été transformés en chaînes (puis en chiffres) à des fins de comparaison. À la lumière du point 3, c'est la même valeur; par conséquent, ils ne peuvent pas être inférieurs ou supérieurs les uns aux autres, conduisant à false .

Enfin, juste pour mettre un sourire sur votre visage:

 b1 <= b2 //true b1 >= b2 //true 

Il y a déjà une réponse acceptée, mais j’ai pensé que je pourrais tout aussi bien append une remarque car je ne trouve pas la réponse acceptée particulièrement claire ou utile. C’est même incorrect, ne serait-ce que parce que cela répond à des questions que le PO n’a pas posées. Alors résumons cela:

 > var b1 = new Buffer([170]); > var b2 = new Buffer([171]); > b1 < b2 > b1 > b2 > b1 == b2 

Tout ce qui est demandé est: “comment puis-je effectuer une équivalence inférieure ou supérieure à la comparaison (ordre (total)) sur les tampons”.

La réponse est:

  • soit le faire manuellement en parcourant tous les octets des deux tampons et en comparant les octets correspondants, par exemple, b1[ idx ] === b2[ idx ] ,

  • ou utilisez Buffer.compare( b1, b2 ) qui vous donne l’un des Buffer.compare( b1, b2 ) -1 , 0 ou +1 , selon que le premier tampon sortingera avant, exactement ou après le second (le sorting d’une liste d contenant des tampons est alors aussi facile que d.sort( Buffer.compare ) ).

Observez que j’utilise === dans mon premier exemple; mes fréquents commentaires sur ce site concernant l’abus de == en JavaScript devraient clairement expliquer pourquoi.