[latex3-commits] [git/LaTeX3-latex3-latex3] l3bitset: added l3bitset and load it (f490cbecb)

Ulrike Fischer fischer at troubleshooting-tex.de
Wed Dec 16 19:18:59 CET 2020


Repository : https://github.com/latex3/latex3
On branch  : l3bitset
Link       : https://github.com/latex3/latex3/commit/f490cbecb2ab37d6db976f19ae5382746843879a

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

commit f490cbecb2ab37d6db976f19ae5382746843879a
Author: Ulrike Fischer <fischer at troubleshooting-tex.de>
Date:   Wed Dec 16 19:18:59 2020 +0100

    added l3bitset and load it


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

f490cbecb2ab37d6db976f19ae5382746843879a
 l3kernel/l3.ins       |   1 +
 l3kernel/l3bitset.dtx | 551 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 552 insertions(+)

diff --git a/l3kernel/l3.ins b/l3kernel/l3.ins
index ad3b5267d..46884ac85 100644
--- a/l3kernel/l3.ins
+++ b/l3kernel/l3.ins
@@ -68,6 +68,7 @@ and all files in that bundle must be distributed together.
         \from{l3str.dtx}        {package}
         \from{l3seq.dtx}        {package}
         \from{l3int.dtx}        {package}
+        \from{l3bitset.dtx}     {package}
         \from{l3flag.dtx}       {package}
         \from{l3prg.dtx}        {package}
         \from{l3sys.dtx}        {package,tex}
diff --git a/l3kernel/l3bitset.dtx b/l3kernel/l3bitset.dtx
new file mode 100644
index 000000000..fca6f6ebe
--- /dev/null
+++ b/l3kernel/l3bitset.dtx
@@ -0,0 +1,551 @@
+% \iffalse meta-comment
+%
+%% File: l3bitset.dtx
+%
+% Copyright (C) 2020 The LaTeX3 Project
+%
+% It may be distributed and/or modified under the conditions of the
+% LaTeX Project Public License (LPPL), either version 1.3c of this
+% license or (at your option) any later version.  The latest version
+% of this license is in the file
+%
+%    http://www.latex-project.org/lppl.txt
+%
+% This file is part of the "l3bitset bundle" (The Work in LPPL)
+% and all files in that bundle must be distributed together.
+%
+% -----------------------------------------------------------------------
+%
+% The development version of the bundle can be found at
+%
+%    https://github.com/latex3/latex3
+%
+% for those people who are interested.
+%
+%<*driver>
+\documentclass[full]{l3doc}
+\begin{document}
+  \DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+% \title{^^A
+%   The \pkg{l3bitset} package  \\ Bitsets ^^A
+% }
+%
+% \author{^^A
+%  The \LaTeX3 Project\thanks
+%    {^^A
+%      E-mail:
+%        \href{mailto:latex-team at latex-project.org}
+%          {latex-team at latex-project.org}^^A
+%    }^^A
+% }
+%
+% \date{Released XXXX-XX-XX}
+%
+% \maketitle
+% \begin{documentation}
+%
+% This package defines and implements the data type \texttt{bitset}, a vector of
+% bits. The size of the vector may grow dynamically.
+% Individual bits can be set and cleared by index and by name.
+% The index is unlike other indices in expl3 modules \emph{zero based} as this
+% is the standard for bitset data types.
+% A \texttt{bitset} can be output as binary number or---as needed e.g. in a
+% PDF dictionary---as decimal (arabic) number.
+% Currently only a small subset of the functions provided by the \pkg{bitset}
+% package are implemented here, mainly the functions needed to use bitsets in
+% PDF dictionaries.
+%
+% The bitset is stored as a string and so the vector size is theoretically
+% unlimited, only restricted by \TeX-memory, but the export function
+% \cs{bitset_to_arabic:N} uses a function from the \texttt{int} module and
+% so the length is practically restricted to values smaller than 31 if this
+% output is needed.
+%
+% \section{Creating bitsets}
+% \begin{function}[added = 2020-12-13]
+%   {\bitset_new:N,\bitset_new:c}
+%   \begin{syntax}
+%     \cs{bitset_new:N}  \meta{bitset var} \\
+%   \end{syntax}
+% Creates a new \meta{bitset var} or raises an error if the name is already taken.
+% The declaration is global. The \meta{bitset var} is initially empty.
+%
+%  Bitsets are implemented as string variables consisting of
+%  \texttt{1}'s and \texttt{0}'s.
+%  The rightmost number is the index position 0, so
+%  the string variable can be viewed directly as the binary number.
+%
+% \end{function}
+%
+% \begin{function}[EXP, pTF,added = 2020-12-14]
+%   { \bitset_if_exist:N, \bitset_if_exist:c  }
+%   \begin{syntax}
+%     \cs{bitset_if_exist_p:N} \meta{bitset var}
+%     \cs{bitset_if_exist:NTF} \meta{bitset var} \Arg{true code} \Arg{false code}%
+%   \end{syntax}
+%   Tests whether the \meta{bitset var} exist.
+% \end{function}
+
+%
+% \section{Setting and clearing bits}
+%
+% \begin{function}[added = 2020-12-13]
+%   { \bitset_set:Nn, \bitset_set:cn, \bitset_gset:Nn, \bitset_gset:cn  }
+%   \begin{syntax}
+%     \cs{bitset_set:Nn}   \meta{bitset var}  \Arg{integer expression}\\
+%     \cs{bitset_gset:Nn}  \meta{bitset var}  \Arg{integer expression}
+%   \end{syntax}
+% Evaluates the \meta{integer expression} and sets the bit of the
+% index position it represents to 1. Index position are zero based and set from
+% right to left (so one can view the bitset as a binary number).
+% If needed the length of the bit vector is enlarged.
+% If the \meta{integer expression} evaluates to a negative number, nothing happens.
+% \end{function}
+%
+% \begin{function}[added = 2020-12-13]
+%   { \bitset_clear:Nn, \bitset_clear:cn, \bitset_gclear:Nn, \bitset_clear:cn }
+%   \begin{syntax}
+%     \cs{bitset_clear:Nn}   \meta{bitset var}  \Arg{integer expression}\\
+%     \cs{bitset_gclear:Nn}  \meta{bitset var}  \Arg{integer expression}
+%   \end{syntax}
+% Evaluates the \meta{integer expression} and clears the bit of the
+% index position it represents (sets it to 0).
+% The index is zero based. If the \meta{integer expression} evaluates to a
+% negative number or is larger than the current length of the bit vector
+% nothing happens. If the leading (left most) bit is cleared,
+% zeros are not trimmed but stay in the bit vector.
+% \end{function}
+%
+% \section{Using bitsets}
+%
+% \begin{function}[EXP,added = 2020-12-14]
+%   { \bitset_index:Nn, \bitset_index:cn }
+%   \begin{syntax}
+%     \cs{bitset_index:Nn}   \meta{bitset var}  \Arg{integer expression}
+%   \end{syntax}
+% Evaluates the \meta{integer expression} and output \texttt{1} if the bit is
+% set and \texttt{0} otherwise.
+% \end{function}
+%
+% \begin{function}[EXP,added = 2020-12-13]
+%   {\bitset_to_bin:N, \bitset_to_bin:c}
+%   \begin{syntax}
+%     \cs{bitset_to_bin:N} \meta{bitset var}
+%   \end{syntax}
+% This leaves the current value of the bitset expressed as
+% a binary (string) number in the input stream.
+% If no bit has been set yet, the output is empty.
+% \end{function}
+% \begin{function}[EXP,added = 2020-12-13]
+%   {\bitset_to_arabic:N, \bitset_to_arabic:c}
+%   \begin{syntax}
+%     \cs{bitset_to_arabic:N} \meta{bitset var}
+%   \end{syntax}
+% This leaves the current value of the bitset expressed as
+% a decimal number in the input stream. If no bit has been set yet,
+% the output is zero. The function uses \cs{int_from_bin:n}, so it
+% can only be used with a bitset whose value is smaller than $2^{31}-1$.
+% \end{function}
+%
+%
+% \begin{function}[added = 2020-12-13]
+%   {\bitset_show:N, \bitset_show:c}
+%   \begin{syntax}
+%     \cs{bitset_show:N} \meta{bitset var}
+%   \end{syntax}
+% Displays the binary and decimal value of the \meta{bitset var} on the terminal,
+% \end{function}
+%
+% \begin{function}[added = 2020-12-13]
+%   {\bitset_log:N, \bitset_log:c}
+%   \begin{syntax}
+%     \cs{bitset_log:N} \meta{bitset var}
+%   \end{syntax}
+% Writes the value of the \meta{bitset var} in the log file.
+% \end{function}
+%
+
+% \section{Syntactic sugar: Setting bits by keys}
+%
+%  If a property with the same name as the bitset exists which maps names to
+%  (explizit) numbers, it is possible to set and clear bits by the keys of this property.
+%
+%  For example after this settings
+%
+%  \begin{verbatim}
+%  \bitset_new:N \l_pdfannot_F_bitset
+%  \prop_new:N   \l_pdfannot_F_bitset_prop
+%  \prop_set_from_keyval:Nn \l_pdfannot_F_bitset_prop
+%    {
+%      Invisible      = 0,
+%      Hidden         = 1,
+%      Print          = 2,
+%      NoZoom         = 3,
+%      NoRotate       = 4,
+%      NoView         = 5,
+%      ReadOnly       = 6,
+%      Locked         = 7,
+%      ToggleNoView   = 8,
+%      LockedContents = 9
+%    }
+%  \end{verbatim}
+%  it is possible to set bit 2 by using
+%  |\bitset_set_key:Nn \l_pdfannot_F_bitset {Print}|
+%  If a key is unknown a warning is issued.
+%  It is not needed to give  all index positions a name.
+% \begin{function}[added = 2020-12-13]
+%   {\bitset_set_key:Nn, \bitset_set_key:cn,
+%    \bitset_gset_key:Nn,\bitset_gset_key:cn }
+%   \begin{syntax}
+%     \cs{bitset_set_key:nn}   \meta{bitset var}  \Arg{key}\\
+%     \cs{bitset_gset_key:nn}  \meta{bitset var}  \Arg{key}
+%   \end{syntax}
+% This sets the bit of the position described by key to \texttt{1}.
+%
+% If needed the length of the bit vector is enlarged.
+% \end{function}
+% \begin{function}[added = 2020-12-13]
+%   {\bitset_clear_key:Nn, \bitset_clear_key:cn,
+%    \bitset_gclear_key:Nn, \bitset_clear_key:cn,}
+%   \begin{syntax}
+%     \cs{bitset_clear_key:Nn}   \meta{bitset var}  \Arg{key}\\
+%     \cs{bitset_gclear_key:Nn}  \meta{bitset var}  \Arg{key}
+%   \end{syntax}
+% This sets the bit of the position described by key to 0.
+% If the leading (left most) bit is cleared, zeros are not
+% trimmed but stay in the bit vector.
+% \end{function}
+% \begin{function}[EXP,added = 2020-12-14]
+%   {\bitset_key:Nn}
+%   \begin{syntax}
+%     \cs{bitset_key:Nn}     \meta{bitset var}  \Arg{key}
+%   \end{syntax}
+% This outputs \texttt{1} if the bit is set, \texttt{0} otherwise.
+% \end{function}
+% \end{documentation}
+%
+% \begin{implementation}
+% \section{\pkg{l3bitset} implementation}
+% \TestFiles{m3bitset001,m3bitset002}
+%    \begin{macrocode}
+%<*package>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+%<@@=bitset>
+%    \end{macrocode}
+% A bitset is a string variable.
+%  \begin{macro}
+%    {
+%      \bitset_new:N,  \bitset_new:c
+%    }
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_new:N #1
+  {
+    \str_new:N #1
+  }
+\cs_generate_variant:Nn \bitset_new:N {c}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}[pTF]
+%   {
+%     \bitset_if_exist:N, \bitset_if_exist:c
+%   }
+%
+% Existence tests.
+%    \begin{macrocode}
+\prg_new_eq_conditional:NNn
+  \bitset_if_exist:N \str_if_exist:N { p , T , F , TF }
+\prg_new_eq_conditional:NNn
+  \bitset_if_exist:c \str_if_exist:c
+  { p , T , F , TF }
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+%   {
+%     \bitset_set:Nn, \bitset_set:cn,
+%     \bitset_gset:Nn, \bitset_gset:cn,
+%   }
+% A bit is set by either extending the string or by splitting it and
+% then inserting an 1. It is not checked if the value was already 1.
+%    \begin{macrocode}
+% #1 name, #2 index (integer expression,zero based)
+\cs_new_protected:Npn \bitset_set:Nn #1 #2
+  {
+    \int_compare:nNnT {#2 } > { -1 }
+      {
+        \int_compare:nNnTF {\str_count:N #1 } < { #2 + 1 }
+          {
+            %extend the str
+            \int_step_inline:nn { #2 - \str_count:N #1 }
+              {
+                \str_put_left:Nn #1 { 0 }
+              }
+            \str_put_left:Nn #1 { 1 }
+          }
+          {
+            %replace value
+            \str_set:Nx #1
+              {
+                \str_range:Nnn #1 {1}{-2 - (#2)}
+                1
+                \str_range:Nnn #1 {0 -(#2)}{-1}
+             }
+          }
+      }
+  }
+
+%#1 name, #2 index (integer expression,zero based)
+\cs_new_protected:Npn \bitset_gset:Nn #1 #2
+  {
+    \int_compare:nNnT {#2 } > { -1 }
+      {
+        \int_compare:nNnTF {\str_count:N #1 } < { #2 + 1 }
+          {
+            %extend the str
+            \int_step_inline:nn { #2 - \str_count:N #1 }
+              {
+                \str_gput_left:Nn #1 { 0 }
+              }
+            \str_gput_left:Nn #1 { 1 }
+          }
+          {
+            % replace the value
+            \str_gset:Nx #1
+              {
+                \str_range:Nnn #1 {1}{-2 -(#2)}
+                1
+                \str_range:Nnn #1 {0 -(#2)}{-1}
+              }
+          }
+      }
+  }
+\cs_generate_variant:Nn \bitset_set:Nn  {cn}
+\cs_generate_variant:Nn \bitset_gset:Nn {cn}
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+%   {
+%     \bitset_clear:Nn,  \bitset_clear:cn,
+%     \bitset_gclear:Nn, \bitset_gclear:cn
+%   }
+% Clearing a bit has only to do something if the string is longer than then index.
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_clear:Nn #1 #2  %#1 name, #2 index (zero based)
+ {
+   \int_compare:nNnT {#2 } > { -1 }
+     {
+       \int_compare:nNnT {\str_count:N #1 } > { #2 }
+         {
+           % need to replace the str
+           \str_set:Nx #1
+             {
+               \str_range:Nnn #1 {1}{-2 - (#2)}
+                0
+               \str_range:Nnn #1 { 0 - (#2)}{-1}
+             }
+         }
+     }
+ }
+
+\cs_new_protected:Npn \bitset_gclear:Nn #1 #2  %#1 name, #2 index (zero based)
+ {
+   \int_compare:nNnT {#2 } > { -1 }
+     {
+       \int_compare:nNnT {\str_count:N #1 } > { #2 }
+         {
+           % need to replace the str
+           \str_gset:Nx #1
+             {
+               \str_range:Nnn #1 {1}{-2 -(#2)}
+                0
+               \str_range:Nnn #1 {0 - (#2)}{-1}
+             }
+         }
+     }
+ }
+\cs_generate_variant:Nn \bitset_clear:Nn {cn}
+\cs_generate_variant:Nn \bitset_gclear:Nn {cn}
+%    \end{macrocode}
+%  \end{macro}
+% \begin{macro}
+%   {
+%     \bitset_to_arabic:N, \bitset_to_arabic:c,
+%     \bitset_to_bin:N,    \bitset_to_bin:c,
+%   }
+%   The naming of the commands follow the names in the \texttt{int} module.
+%   \cs{bitset_to_arabic:N} uses \cs{int_from_bin:n} and so can only handle small
+%   numbers. There is no test for the string length, so that long bitset with
+%   many leading zeros work nevertheless.
+%    \begin{macrocode}
+\cs_new:Npn \bitset_to_arabic:N #1
+  {
+    \exp_args:Ne \int_from_bin:n { #1 }
+  }
+
+\cs_new:Npn \bitset_to_bin:N #1
+  {
+    #1
+  }
+
+\cs_generate_variant:Nn \bitset_to_arabic:N  {c}
+\cs_generate_variant:Nn \bitset_to_bin:N {c}
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%   {
+%     \bitset_index:Nn, \bitset_index:cn
+%   }
+%    \begin{macrocode}
+\cs_new:Npn \bitset_index:Nn #1 #2
+ {
+   \int_eval:n { \str_item:Nn #1 { -1 - (#2)} +0 }
+ }
+\cs_generate_variant:Nn \bitset_index:Nn {cn}
+%    \end{macrocode}
+% \end{macro}
+
+% \begin{macro}
+%   {
+%     \bitset_show:N, \bitset_show:c,
+%     \bitset_log:N,  \bitset_log:c
+%   }
+%    \begin{macrocode}
+\cs_new_protected:Npn   \bitset_show:N { \@@_show:NN \msg_show:nnxxxx }
+\cs_generate_variant:Nn \bitset_show:N { c }
+\cs_new_protected:Npn   \bitset_log:N  { \@@_show:NN \msg_log:nnxxxx }
+\cs_generate_variant:Nn \bitset_log:N  { c }
+\cs_new_protected:Npn \__bitset_show:NN #1#2
+  {
+    \__kernel_chk_defined:NT #2
+      {
+        #1 { LaTeX/kernel } { show-bitset }
+           { \token_to_str:N #2 }
+           { \bitset_to_bin:N #2  }
+           { \int_compare:nNnTF { \str_count:N #2 } < {32}
+               { \bitset_to_arabic:N #2  }
+               {---bitset~is~to~long~to~show~it--- }
+           } { }
+      }
+  }
+
+%    \end{macrocode}
+% \end{macro}
+% \begin{macro}
+%   {
+%     \bitset_set_key:Nn, \bitset_set_key:cn,
+%     \bitset_gset_key:Nn, \bitset_gset_key:cn
+%   }
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_set_key:Nn #1 #2
+  {
+    \prop_if_in:cnTF { \cs_to_str:N #1_prop } {#2}
+      {
+        \bitset_set:Nn #1
+          {
+            \prop_item:cn{ \cs_to_str:N #1_prop }{#2}
+          }
+      }
+      {
+        \__kernel_msg_warning:nnxx { kernel } { bitset-unknown-key }
+          { \token_to_str:N #1 }
+          { \tl_to_str:n { #2} }
+      }
+  }
+
+\cs_new_protected:Npn \bitset_gset_key:Nn #1 #2
+  {
+    \prop_if_in:cnTF { \cs_to_str:N #1_prop } {#2}
+      {
+        \bitset_gset:Nn #1
+          {
+            \prop_item:cn{ \cs_to_str:N #1_prop }{#2}
+          }
+      }
+      {
+         \__kernel_msg_warning:nnxx { kernel } { bitset-unknown-key }
+           { \token_to_str:N #1 }
+           { \tl_to_str:n { #2} }
+
+      }
+  }
+\cs_generate_variant:Nn \bitset_set_key:Nn {cn}
+\cs_generate_variant:Nn \bitset_gset_key:Nn {cn}
+
+%    \end{macrocode}
+% \end{macro}%
+% \begin{macro}
+%   {
+%     \bitset_clear_key:Nn,  \bitset_clear_key:cn,
+%     \bitset_gclear_key:Nn, \bitset_gclear_key:cn,
+%   }
+%    \begin{macrocode}
+\cs_new_protected:Npn \bitset_clear_key:Nn #1 #2
+  {
+    \prop_if_in:cnTF { \cs_to_str:N #1_prop } {#2}
+      {
+        \bitset_clear:Nn #1
+          {
+            \prop_item:cn{ \cs_to_str:N #1_prop }{#2}
+          }
+      }
+      {
+        \__kernel_msg_warning:nnxx { kernel } { bitset-unknown-key }
+          { \token_to_str:N #1 }
+          { \tl_to_str:n { #2} }
+      }
+  }
+
+\cs_new_protected:Npn \bitset_gclear_key:Nn #1 #2
+  {
+    \prop_if_in:cnTF { \cs_to_str:N #1_prop } {#2}
+      {
+        \bitset_gclear:Nn #1
+          {
+            \prop_item:cn{ \cs_to_str:N #1_prop }{#2}
+          }
+      }
+      {
+        \__kernel_msg_warning:nnxx { kernel } { bitset-unknown-key }
+          { \token_to_str:N #1 }
+          { \tl_to_str:n { #2} }
+      }
+  }
+\cs_generate_variant:Nn \bitset_clear_key:Nn {cn}
+\cs_generate_variant:Nn \bitset_gclear_key:Nn {cn}
+%    \end{macrocode}
+%  \end{macro}
+% \begin{macro}
+%   {
+%     \bitset_key:Nn, \bitset_key:cn
+%   }
+%    \begin{macrocode}
+\cs_new:Npn \bitset_key:Nn #1 #2
+  {
+    \prop_if_in:cnTF { \cs_to_str:N #1_prop } {#2}
+      {
+        \int_eval:n
+          {
+            \str_item:Nn #1
+              { -1 -(\prop_item:cn{\cs_to_str:N #1_prop}{#2}) }
+            +0
+          }
+     }
+     {
+       0
+     }
+  }
+\cs_generate_variant:Nn \bitset_key:Nn  {cn}
+%    \end{macrocode}
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+% \end{macro}%
+% \end{implementation}
+%
+% \PrintIndex





More information about the latex3-commits mailing list.