[latex3-commits] [git/LaTeX3-latex3-latex3] master: Add \file_hex_dump:n(nn) (12fe42862)

Joseph Wright joseph.wright at morningstar2.co.uk
Tue Nov 19 18:54:57 CET 2019


Repository : https://github.com/latex3/latex3
On branch  : master
Link       : https://github.com/latex3/latex3/commit/12fe42862df6a2d2b2eb4bd264f60961a5aae8e6

>---------------------------------------------------------------

commit 12fe42862df6a2d2b2eb4bd264f60961a5aae8e6
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Tue Nov 19 17:54:57 2019 +0000

    Add \file_hex_dump:n(nn)
    
    Requested by Alex Grahn and Enrico.


>---------------------------------------------------------------

12fe42862df6a2d2b2eb4bd264f60961a5aae8e6
 l3kernel/CHANGELOG.md |   3 ++
 l3kernel/l3file.dtx   | 101 +++++++++++++++++++++++++++++++++++++++++++++++++-
 l3kernel/l3luatex.dtx |  56 +++++++++++++++++++++++-----
 3 files changed, 149 insertions(+), 11 deletions(-)

diff --git a/l3kernel/CHANGELOG.md b/l3kernel/CHANGELOG.md
index 8e4ff7c73..1fccb07c4 100644
--- a/l3kernel/CHANGELOG.md
+++ b/l3kernel/CHANGELOG.md
@@ -7,6 +7,9 @@ this project uses date-based 'snapshot' version identifiers.
 
 ## [Unreleased]
 
+### Added
+- `\file_hex_dump:n(nn)` and `\file_get_hex_dump:n(nn)(TF)`
+
 ### Changed
 - Distribute LaTeX3 News
 
diff --git a/l3kernel/l3file.dtx b/l3kernel/l3file.dtx
index 2b6c86f8f..75046dc62 100644
--- a/l3kernel/l3file.dtx
+++ b/l3kernel/l3file.dtx
@@ -702,6 +702,35 @@
 %   quote (|"|) characters or is surrounded by a pair of quotes.
 % \end{function}
 %
+% \begin{function}[rEXP, added = 2019-11-19]
+%   {\file_hex_dump:n, \file_hex_dump:nnn}
+%   \begin{syntax}
+%     \cs{file_hex_dump:n} \Arg{file name}
+%     \cs{file_hex_dump:nnn} \Arg{file name} \Arg{offset} \Arg{length}
+%   \end{syntax}
+%   Searches for \meta{file name} using the current \TeX{} search
+%   path and the additional paths controlled by \cs{l_file_search_path_seq}.
+%   It then expands to leave the hexadecimal dump of the file content in the
+%   input stream. The file is read as bytes, which means that in
+%   contrast to most \TeX{} behaviour there will be a difference in result
+%   depending on the line endings used in text files. The same file will
+%   produce the same result between different engines: the algorithm used
+%   is the same in all cases. When the file is not found, the result of
+%   expansion is empty. The \meta{offset} from the start of the file
+%   and \meta{length} are given in bytes.
+% \end{function}
+%
+% \begin{function}[noTF, added = 2019-11-19]
+%   {\file_get_hex_dump:nN, \file_get_hex_dump:nnnN}
+%   \begin{syntax}
+%     \cs{file_get_hex_dump:n} \Arg{file name} \meta{tl var}
+%     \cs{file_get_hex_dump:nnn} \Arg{file name} \Arg{offset} \Arg{length} \meta{tl var}
+%   \end{syntax}
+%   Sets the \meta{tl var} to the result of applying
+%   \cs{file_hex_dump:n}/\cs{file_hex_dump:nnn} to the \meta{file}.
+%   If the file is not found, the \meta{tl var} will be set to \cs{q_no_value}.
+% \end{function}
+%
 % \begin{function}[rEXP, added = 2019-09-03]{\file_mdfive_hash:n}
 %   \begin{syntax}
 %     \cs{file_mdfive_hash:n} \Arg{file name}
@@ -2858,18 +2887,67 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}{\file_hex_dump:nnn, \@@_hex_dump:nnn}
+% \begin{macro}{\file_hex_dump:n, \@@_hex_dump:n}
+%   These are separate as they need multiple arguments \emph{or} the
+%   file size. For \LuaTeX{}, the emulation does not need the file
+%   size so we save a little on expansion.
+%    \begin{macrocode}
+\cs_new:Npn \file_hex_dump:nnn #1#2#3
+  { \exp_args:Ne \@@_hex_dump:nnn { \file_full_name:n {#1} } {#2} {#3} }
+\cs_new:Npn \@@_hex_dump:nnn #1#2#3
+  {
+    \tl_if_blank:nF {#1}
+      { \tex_filedump:D offset ~ #2 ~ length #3 {#1} }
+  }
+\sys_if_engine_luatex:T
+  {
+    \cs_gset:Npn \@@_hex_dump:nnn #1#2#3
+      {
+        \lua_now:e
+          { l3kernel.filedump ( " \lua_escape:e { #1 } " , #2 , #3 ) }
+      }
+  }
+\cs_new:Npn \file_hex_dump:n #1
+  { \exp_args:Ne \@@_hex_dump:n { \file_full_name:n {#1} } }
+\cs_new:Npn \@@_hex_dump:n #1
+  {
+    \tl_if_blank:nF {#1}
+      { \tex_filedump:D length \tex_filesize:D {#1} {#1} }
+  }
+\sys_if_engine_luatex:T
+  {
+    \cs_gset:Npn \@@_hex_dump:n #1
+      {
+        \lua_now:e
+          { l3kernel.filedump ( " \lua_escape:e { #1 } " ) }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
 % \begin{macro}[noTF]
-%   {\file_get_mdfive_hash:nN, \file_get_size:nN, \file_get_timestamp:nN}
+%   {
+%     \file_get_hex_dump:nN,
+%     \file_get_mdfive_hash:nN
+%      \file_get_size:nN,
+%      \file_get_timestamp:nN
+%   }
 % \begin{macro}{\@@_get_details:nnN}
 %   Non-expandable wrappers around the above in the case where appropriate
 %   primitive support exists.
 %    \begin{macrocode}
+\cs_new_protected:Npn \file_get_hex_dump:nN #1#2
+  { \file_get_hex_dump:nNF {#1} #2 { \tl_set:Nn #2 { \q_no_value } } }
 \cs_new_protected:Npn \file_get_mdfive_hash:nN #1#2
   { \file_get_mdfive_hash:nNF {#1} #2 { \tl_set:Nn #2 { \q_no_value } } }
 \cs_new_protected:Npn \file_get_size:nN #1#2
   { \file_get_size:nNF {#1} #2 { \tl_set:Nn #2 { \q_no_value } } }
 \cs_new_protected:Npn \file_get_timestamp:nN #1#2
   { \file_get_timestamp:nNF {#1} #2 { \tl_set:Nn #2 { \q_no_value } } }
+\prg_new_protected_conditional:Npnn \file_get_hex_dump:nN #1#2 { T , F , TF }
+  { \@@_get_details:nnN {#1} { hex_dump } #2 }
 \prg_new_protected_conditional:Npnn \file_get_mdfive_hash:nN #1#2 { T , F , TF }
   { \@@_get_details:nnN {#1} { mdfive_hash } #2 }
 \prg_new_protected_conditional:Npnn \file_get_size:nN #1#2 { T , F , TF }
@@ -2901,6 +2979,7 @@
             \token_to_str:N \(pdf)file
             \str_case:nn {#2}
               {
+                { hex_dump } { dump }
                 { mdfive_hash } { mdfivesum }
                 { timestamp } { moddate }
                 { size } { size }
@@ -2913,6 +2992,26 @@
 % \end{macro}
 % \end{macro}
 %
+% \begin{macro}[noTF]{\file_get_hex_dump:nnnN}
+%   Custom code due to the additional arguments.
+%    \begin{macrocode}
+\cs_new_protected:Npn \file_get_hex_dump:nnnN #1#2#3#4
+  {
+    \file_get_hex_dump:nnnNF {#1} {#2} {#3} #4
+      { \tl_set:Nn #4 { \q_no_value } } 
+  }
+\prg_new_protected_conditional:Npnn \file_get_mdfive_hash:nnnN #1#2#3#4
+  { T , F , TF }
+  {
+    \tl_set:Nx #4
+      { \file_hex_dump:nnn {#1} {#2} {#3} }
+    \tl_if_empty:NTF #4
+      { \prg_return_false: }
+      { \prg_return_true: }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}[EXP]{\@@_str_cmp:nn}
 % \begin{macro}[EXP]{\@@_str_escape:n}
 %   As we are doing a fixed-length \enquote{big} integer comparison, it
diff --git a/l3kernel/l3luatex.dtx b/l3kernel/l3luatex.dtx
index 22780b77f..88f106d54 100644
--- a/l3kernel/l3luatex.dtx
+++ b/l3kernel/l3luatex.dtx
@@ -143,6 +143,17 @@
 %   for user input.
 % \end{function}
 %
+% \begin{function}{l3kernel.filedump}
+%   \begin{syntax}
+%     |l3kernel.filedump(|\meta{file}|,|\meta{length}|,|\meta{offset}|)|
+%   \end{syntax}
+%   Returns the uppercase hexadecimal representation of the content of the
+%   \meta{file} read as bytes. If the \meta{length} is given, only this part
+%   of the file is returned; similarly, one may specify the \meta{offset} from
+%   the start of the file. If the \meta{length} is not given, the entire file
+%   is read starting at the \meta{offset}.
+% \end{function}
+%
 % \begin{function}{l3kernel.filemdfivesum}
 %   \begin{syntax}
 %     |l3kernel.filemdfivesum(|\meta{file}|)|
@@ -310,16 +321,17 @@ l3kernel = l3kernel or { }
 %
 %   Local copies of global tables.
 %    \begin{macrocode}
-local io      = io
-local kpse    = kpse
-local lfs     = lfs
-local math    = math
-local md5     = md5
-local os      = os
-local string  = string
-local tex     = tex
-local texio   = texio
-local unicode = unicode
+local io       = io
+local kpse     = kpse
+local lfs      = lfs
+local math     = math
+local md5      = md5
+local os       = os
+local string   = string
+local tex      = tex
+local texio    = texio
+local tonumber = tonumber
+local unicode  = unicode
 %    \end{macrocode}
 %
 %   Local copies of standard functions.
@@ -395,6 +407,30 @@ l3kernel.resettimer = resettimer
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{macro}{l3kernel.filedump}
+%   Similar comments here to the next function: read the file in binary mode
+%   to avoid any line-end weirdness.
+%    \begin{macrocode}
+local function filedump(name,offset,length)
+  local file = kpse_find(name,"tex",true)
+  if file then
+    local length = tonumber(length) or lfs_attr(file,"size")
+    local offset = tonumber(offset) or 0
+    local f = open(file,"rb")
+    if f then
+      if offset > 0 then
+        f:seek("set",offset)
+      end
+      local data = f:read(length)
+      escapehex(data)
+      f:close()
+    end
+  end
+end
+l3kernel.filedump = filedump
+%    \end{macrocode}
+% \end{macro}
+%
 % \begin{macro}{l3kernel.filemdfivesum}
 %   Read an entire file and hash it: the hash function itself is a built-in.
 %   As Lua is byte-based there is no work needed here in terms of UTF-8





More information about the latex3-commits mailing list