From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: Byte swapping and bindat Date: Fri, 10 Jun 2022 17:42:41 -0400 Message-ID: References: <87pmjglllc.fsf.ref@yahoo.com> <87pmjglllc.fsf@yahoo.com> <83mtekzf9f.fsf@gnu.org> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="9894"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux) Cc: EMACS development team To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Fri Jun 10 23:43:31 2022 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nzmPi-0002J3-Be for ged-emacs-devel@m.gmane-mx.org; Fri, 10 Jun 2022 23:43:30 +0200 Original-Received: from localhost ([::1]:48400 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nzmPg-0001GG-RN for ged-emacs-devel@m.gmane-mx.org; Fri, 10 Jun 2022 17:43:28 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:41564) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nzmP3-0000aD-7X for emacs-devel@gnu.org; Fri, 10 Jun 2022 17:42:49 -0400 Original-Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:4596) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nzmP0-0007s8-HB; Fri, 10 Jun 2022 17:42:48 -0400 Original-Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 9DB198109E; Fri, 10 Jun 2022 17:42:44 -0400 (EDT) Original-Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id CD6BC80762; Fri, 10 Jun 2022 17:42:42 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1654897362; bh=xShXwew4yA50Dio4J/Ch1lGDbip73TPCocmzCEnzfbo=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From; b=OeF1mMvdg1tHUyRiMRzNsxHI13P+Kkp2AeCnLAWIt9ifBmvW4zPo38XCWrrlPQ+mV rgcMm3s0hNeaCZOzxN3YqcdudH1k8PL/qEzxvbvMtyFHGidRvY5DcA9xoCfUYbk/xV /ECdasJoIMZQ8vA5YOFM7lRe9L/dALIXEbppczFWDsUboajFOKsI8cxfEt1YtrHhmT /lz//v7ZDCDhGAha92g09Xn+03120nQq1d5S8CuzOw9AsdIZ+wONFEt6lZeDK9qMXh WeSkCgoyIb1LPMAlFUuY3dFsior+VapYnlqavGwxHeyQOJp4wza3uNQWbLj0ygGw/E M9UazP7AxBCwg== Original-Received: from pastel (unknown [45.72.221.51]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 82B7F1201B4; Fri, 10 Jun 2022 17:42:42 -0400 (EDT) In-Reply-To: <83mtekzf9f.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 10 Jun 2022 18:53:32 +0300") Received-SPF: pass client-ip=132.204.25.50; envelope-from=monnier@iro.umontreal.ca; helo=mailscanner.iro.umontreal.ca X-Spam_score_int: -42 X-Spam_score: -4.3 X-Spam_bar: ---- X-Spam_report: (-4.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:291009 Archived-At: Eli Zaretskii [2022-06-10 18:53:32] wrote: >> Date: Fri, 10 Jun 2022 09:32:31 -0400 >> From: Stefan Monnier via Users list for the GNU Emacs text editor >> >> (let* ((threshold 32) >> (type (bindat-type (kind uint 8) >> (length sint 32 (> kind threshold))))) >> (list (bindat-unpack type "\x10\x00\x00\x01\x01") >> (bindat-unpack type "\x80\x00\x00\x01\x01"))) >> => >> (((kind . 16) (length . 257)) >> ((kind . 128) (length . 16842752))) > > It would be nice to have sint documented in the ELisp manual... Good point. I think it would also be nice to unify `uint` and `uintr`. What about the patch below? Stefan diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi index 55fb93ec5a8..63570d2117f 100644 --- a/doc/lispref/processes.texi +++ b/doc/lispref/processes.texi @@ -3470,13 +3470,15 @@ Bindat Types @itemx byte Unsigned byte, with length 1. -@item uint @var{bitlen} -Unsigned integer in network byte order, with @var{bitlen} bits. +@item uint @var{bitlen} &optional @var{le} +Unsigned integer in network byte order (big-endian), with @var{bitlen} bits. @var{bitlen} has to be a multiple of 8. +If @var{le} is non-@code{nil}, then use little-endian. -@item uintr @var{bitlen} -Unsigned integer in little endian order, with @var{bitlen} bits. +@item sint @var{bitlen} @var{le} +Signed integer in network byte order (big-endian), with @var{bitlen} bits. @var{bitlen} has to be a multiple of 8. +If @var{le} is non-@code{nil}, then use little-endian. @item str @var{len} Unibyte string (@pxref{Text Representations}) of length @var{len} bytes. diff --git a/lisp/emacs-lisp/bindat.el b/lisp/emacs-lisp/bindat.el index 5f3c772983a..48ae7c8545b 100644 --- a/lisp/emacs-lisp/bindat.el +++ b/lisp/emacs-lisp/bindat.el @@ -77,7 +77,7 @@ ;; (bindat-type ;; (type u8) ;; (opcode u8) -;; (length uintr 32) ;; little endian order +;; (length uint 32 t) ;; little endian order ;; (id strz 8) ;; (data vec length) ;; (_ align 4))) @@ -663,14 +663,17 @@ bindat--type (`(length . ,_) `(cl-incf bindat-idx 1)) (`(pack . ,args) `(bindat--pack-u8 . ,args)))) -(cl-defmethod bindat--type (op (_ (eql 'uint)) n) +(cl-defmethod bindat--type (op (_ (eql 'uint)) n &optional le) (if (eq n 8) (bindat--type op 'byte) (bindat--pcase op - ('unpack `(bindat--unpack-uint ,n)) + ('unpack + `(if ,le (bindat--unpack-uintr ,n) (bindat--unpack-uint ,n))) (`(length . ,_) `(cl-incf bindat-idx (/ ,n 8))) - (`(pack . ,args) `(bindat--pack-uint ,n . ,args))))) + (`(pack . ,args) + `(if ,le (bindat--pack-uintr ,n . ,args) + (bindat--pack-uint ,n . ,args)))))) -(cl-defmethod bindat--type (op (_ (eql 'uintr)) n) +(cl-defmethod bindat--type (op (_ (eql 'uintr)) n) ;Obsolete since Emacs-29. (if (eq n 8) (bindat--type op 'byte) (bindat--pcase op ('unpack `(bindat--unpack-uintr ,n)) @@ -849,8 +852,7 @@ bindat-type "Return the Bindat type value to pack&unpack TYPE. TYPE is a Bindat type expression. It can take the following forms: - uint BITLEN - Big-endian unsigned integer - uintr BITLEN - Little-endian unsigned integer + uint BITLEN [LE] - unsigned integer (big-endian if LE is nil) str LEN - Byte string strz [LEN] - Zero-terminated byte-string bits LEN - Bit vector (LEN is counted in bytes) @@ -935,9 +937,9 @@ bindat--make-docstring (if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc))))) (bindat-defmacro u8 () "Unsigned 8bit integer." '(byte)) -(bindat-defmacro sint (bitlen r) +(bindat-defmacro sint (bitlen le) "Signed integer of size BITLEN. -Bigendian if R is nil and little endian if not." +Big-endian if LE is nil and little-endian if not." (let ((bl (make-symbol "bitlen")) (max (make-symbol "max")) (wrap (make-symbol "wrap"))) @@ -945,7 +947,7 @@ sint (,max (ash 1 (1- ,bl))) (,wrap (+ ,max ,max))) (struct :pack-var v - (n if ,r (uintr ,bl) (uint ,bl) + (n uint ,bl ,le :pack-val (if (< v 0) (+ v ,wrap) v)) :unpack-val (if (>= n ,max) (- n ,wrap) n))))) diff --git a/test/lisp/emacs-lisp/bindat-tests.el b/test/lisp/emacs-lisp/bindat-tests.el index 48170727525..1ce402977f5 100644 --- a/test/lisp/emacs-lisp/bindat-tests.el +++ b/test/lisp/emacs-lisp/bindat-tests.el @@ -36,7 +36,7 @@ data-bindat-spec (bindat-type (type u8) (opcode u8) - (length uintr 16) ;; little endian order + (length uint 16 'le) ;; little endian order (id strz 8) (data vec length) (_ align 4))) @@ -128,18 +128,17 @@ bindat-test--sint (r (zerop (% kind 2)))) (dotimes (_ 100) (let* ((n (random (ash 1 bitlen))) - (i (- n (ash 1 (1- bitlen))))) + (i (- n (ash 1 (1- bitlen)))) + (stype (bindat-type sint bitlen r)) + (utype (bindat-type if r (uintr bitlen) (uint bitlen)))) (should (equal (bindat-unpack - (bindat-type sint bitlen r) - (bindat-pack (bindat-type sint bitlen r) i)) + stype + (bindat-pack stype i)) i)) (when (>= i 0) - (should (equal (bindat-pack - (bindat-type if r (uintr bitlen) (uint bitlen)) i) - (bindat-pack (bindat-type sint bitlen r) i))) - (should (equal (bindat-unpack - (bindat-type if r (uintr bitlen) (uint bitlen)) - (bindat-pack (bindat-type sint bitlen r) i)) + (should (equal (bindat-pack utype i) + (bindat-pack stype i))) + (should (equal (bindat-unpack utype (bindat-pack stype i)) i)))))))) (defconst bindat-test--LEB128