summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/datatool/datatool.sty
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/latex/datatool/datatool.sty')
-rw-r--r--Master/texmf-dist/tex/latex/datatool/datatool.sty3419
1 files changed, 2401 insertions, 1018 deletions
diff --git a/Master/texmf-dist/tex/latex/datatool/datatool.sty b/Master/texmf-dist/tex/latex/datatool/datatool.sty
index 099417295be..6925836a74c 100644
--- a/Master/texmf-dist/tex/latex/datatool/datatool.sty
+++ b/Master/texmf-dist/tex/latex/datatool/datatool.sty
@@ -7,7 +7,7 @@
%% datatool.dtx (with options: `datatool.sty,package')
%%
%% datatool.dtx
-%% Copyright 2007 Nicola Talbot
+%% Copyright 2009 Nicola Talbot
%%
%% This work may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either version 1.3
@@ -39,12 +39,13 @@
%% Grave accent \` Left brace \{ Vertical bar \|
%% Right brace \} Tilde \~}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{datatool}[2007/08/17 v1.01 (NLCT)]
+\ProvidesPackage{datatool}[2009/02/27 v2.0 (NLCT)]
\RequirePackage{xkeyval}
\RequirePackage{ifthen}
\RequirePackage{xfor}
\RequirePackage{fp}
\RequirePackage{substr}
+\RequirePackage{etex}
\newcommand*{\@dtl@separator}{,}
\newcommand*{\DTLsetseparator}[1]{%
\renewcommand*{\@dtl@separator}{#1}%
@@ -1220,32 +1221,16 @@
\@dtl@dovalue
}
\newcommand{\DTLiffirstrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLiffirstrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
-\expandafter\ifnum\csname c@DTLrow\romannumeral
-\dtlforeachlevel\endcsname
-=1\relax#1\else#2\fi
-\fi}
+ \PackageError{datatool}{\string\DTLiffirstrow\space can only
+ be used inside \string\DTLforeach}{}%
+}
\newcommand{\DTLiflastrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLiflastrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
-\ifx\@dtl@nextrow\@nnil
-#1\else #2\fi
-\fi
+ \PackageError{datatool}{\string\DTLiflastrow\space can only
+ be used inside \string\DTLforeach}{}%
}
\newcommand{\DTLifoddrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLifoddrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
-\expandafter\ifodd\csname c@DTLrow\romannumeral
-\dtlforeachlevel\endcsname
-#1\else #2\fi
-\fi
+ \PackageError{datatool}{\string\DTLifoddrow\space can only
+ be used inside \string\DTLforeach}{}%
}
\newif\if@dtl@condition
\newcommand*{\dtl@testlt}[2]{%
@@ -1373,145 +1358,808 @@
\TE@throw\noexpand\dtl@testcurrencyunit{#1}{#2}%
\noexpand\if@dtl@condition}
\newcommand*{\DTLnewdb}[1]{%
-\DTLifdbexists{#1}{%
-\PackageError{datatool}{Database `#1' already exists}{}}{%
-\dtl@message{Creating database `#1'}%
-\expandafter\gdef\csname dtldb@#1\endcsname{}%
-\expandafter\gdef\csname dtlkeys@#1\endcsname{}%
-\expandafter\global\expandafter\newcount\csname dtlrows@#1\endcsname}}
+ \DTLifdbexists{#1}%
+ {%
+ \PackageError{datatool}{Database `#1' already exists}{}%
+ }%
+ {%
+ \dtl@message{Creating database `#1'}%
+ \expandafter\newtoks\csname dtldb@#1\endcsname
+ \expandafter\newtoks\csname dtlkeys@#1\endcsname{}%
+ \expandafter\newcount\csname dtlrows@#1\endcsname
+ \expandafter\newcount\csname dtlcols@#1\endcsname
+ }%
+}
\newcommand*{\DTLrowcount}[1]{%
\expandafter\number\csname dtlrows@#1\endcsname}
+\newcommand*{\DTLcolumncount}[1]{%
+\expandafter\number\csname dtlcols@#1\endcsname}
\newcommand{\DTLifdbempty}[3]{%
-\DTLifdbexists{#1}{%
-\expandafter\ifx\csname dtldb@#1\endcsname\@empty
- #2%
-\else
- #3%
-\fi}{%
-\PackageError{Database `#1' doesn't exist}{}{}}}
-\newcommand*{\DTLnewrow}[1]{%
-\DTLifdbempty{#1}{%
- \expandafter\gdef\csname dtldb@#1\endcsname{{}}%
- \expandafter\global\expandafter\advance
- \csname dtlrows@#1\endcsname by 1\relax
- \dtl@message{New row added to database `#1'}%
-}{%
- \expandafter\let\expandafter\@dtl@olddb\csname dtldb@#1\endcsname%
- \expandafter\toks@\expandafter{\@dtl@olddb,{}}%
- \expandafter\xdef\csname dtldb@#1\endcsname{\the\toks@}%
- \expandafter\global\expandafter\advance
- \csname dtlrows@#1\endcsname by 1\relax
+ \DTLifdbexists{#1}%
+ {\@DTLifdbempty{#1}{#2}{#3}}%
+ {\PackageError{Can't check if database `#1' is empty:
+ database doesn't exist}{}{}}%
+}
+\newcommand{\@DTLifdbempty}[3]{%
+ \expandafter\ifnum\csname dtlrows@#1\endcsname=0\relax
+ #2%
+ \else
+ #3%
+ \fi
+}
+\newcommand*{\DTLnewrow}{%
+ \@ifstar\@sDTLnewrow\@DTLnewrow
+}
+\newcommand*{\@DTLnewrow}[1]{%
+\DTLifdbexists{#1}%
+ {\@sDTLnewrow{#1}}%
+ {\PackageErrors{datatool}{Can't add new row to database `#1':
+ database doesn't exist}{}}%
+}
+\newcommand*{\@sDTLnewrow}[1]{%
+ \global\advance\csname dtlrows@#1\endcsname by 1\relax
+ \toks@gput@right@cx{dtldb@#1}{%
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
\dtl@message{New row added to database `#1'}%
-}}
-\newcommand{\DTLnewdbentry}[3]{%
-\@dtl@toks{#3}%
-\edef\@dtl@dbvalue{\the\@dtl@toks}%
-\edef\@dtl@dbid{#2}%
-\edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
-\DTLifdbempty{#1}{\DTLnewrow{#1}}{}%
-\expandafter\dtl@choplast\expandafter{%
-\csname dtldb@#1\endcsname}{\@dtl@dbrest}{\@dtl@dblastrow}%
-\dtl@ifrowcontains{#2}{\@dtl@dblastrow}{%
-\PackageError{datatool}{Can't add entry with ID `#2' to current
-row of database `#1'}{There is already an entry with this ID on
-the current row}}{%
-\expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
-\ifthenelse{\equal{}{\@dtl@dblastrow}}{%
- \edef\@dtl@dblastrow{\the\@dtl@toks}%
-}{%
- \expandafter\toks@\expandafter{\@dtl@dblastrow}%
- \edef\@dtl@dblastrow{\the\toks@,\the\@dtl@toks}%
-}%
-\expandafter\@dtl@toks\expandafter{\@dtl@dblastrow}%
-\ifthenelse{\equal{}{\@dtl@dbrest}}{%
- \expandafter\long\expandafter\xdef\csname dtldb@#1\endcsname{%
- {\the\@dtl@toks}}%
-}{%
- \expandafter\toks@\expandafter{\@dtl@dbrest}%
- \expandafter\long\expandafter\xdef\csname dtldb@#1\endcsname{%
- \the\toks@,{\the\@dtl@toks}}%
-}%
-\@dtl@setidtype{#1}{#2}{#3}%
-\expandafter\@dtl@setkeys\expandafter{#2}{#1}%
-}%
-\dtl@message{Added #2\space -> #3\space to database `#1'}%
}
-\newcommand{\@dtl@setidtype}[3]{%
-\@dtl@checknumerical{#3}%
-\def\@dtl@value{#3}%
-\@ifundefined{@dtl@idtype@#1@#2}{%
-\ifx\@dtl@value\@empty
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{}%
-\else
- \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
- \the\@dtl@datatype}%
-\fi
-}{%
-\ifx\@dtl@value\@empty
-\else
- \expandafter\ifx\csname @dtl@idtype@#1@#2\endcsname\@empty
- \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
- \the\@dtl@datatype}%
- \else
- \expandafter\@dtl@tmpcount\expandafter=
- \csname @dtl@idtype@#1@#2\endcsname\relax
- \ifcase\@dtl@tmpcount
- \or
- \expandafter\xdef\csname @dtl@idtype@#1@#2\endcsname{%
- \the\@dtl@datatype}%
- \or
- \ifnum\@dtl@datatype=0\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
+\newcount\dtlcolumnnum
+\newcount\dtlrownum
+\newcommand*{\DTLifhaskey}{\@ifstar\@sDTLifhaskey\@DTLifhaskey}
+\newcommand{\@DTLifhaskey}[4]{%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}{#3}{#4}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
+ }%
+}
+\newcommand{\@sDTLifhaskey}[4]{%
+ \@ifundefined{dtl@ci@#1@#2}%
+ {%
+ #4%
+ }%
+ {%
+ #3%
+ }%
+}
+\newcommand*{\DTLgetcolumnindex}{%
+ \@ifstar\@sdtl@getcolumnindex\@dtl@getcolumnindex
+}
+\newcommand*{\@dtl@getcolumnindex}[3]{%
+ \DTLifdbexists{#2}%
+ {%
+ \@sDTLifhaskey{#2}{#3}%
+ {%
+ \@sdtl@getcolumnindex{#1}{#2}{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't contain
+ key `#3'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@sdtl@getcolumnindex}[3]{%
+ \expandafter\let\expandafter#1\csname dtl@ci@#2@#3\endcsname
+}
+\newcommand*{\dtl@columnindex}[2]{%
+ \csname dtl@ci@#1@#2\endcsname
+}
+\newcommand*{\DTLgetkeyforcolumn}{%
+ \@ifstar\@sdtlgetkeyforcolumn\@dtlgetkeyforcolumn}
+\newcommand*{\@dtlgetkeyforcolumn}[3]{%
+ \DTLifdbexists{#2}%
+ {%
+ \ifnum#3<1\relax
+ \PackageError{datatool}{Invalid column index \number#3}{%
+ Column indices start at 1}%
+ \else
+ \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax
+ \PackageError{datatool}{Index \number#3\space out of
+ range for database `#2'}{Database `#2' only has
+ \expandafter\number\csname dtlcols@#2\endcsname\space
+ columns}%
\else
- \ifnum\@dtl@datatype=3\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}%
- \else
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{2}%
+ \@sdtlgetkeyforcolumn{#1}{#2}{#3}%
+ \fi
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exists}{}%
+ }%
+}
+\newcommand*{\@sdtlgetkeyforcolumn}[3]{%
+ \edef\@dtl@dogetkeyforcolumn{\noexpand\@dtl@getkeyforcolumn
+ {\noexpand#1}{#2}{\number#3}}%
+ \@dtl@dogetkeyforcolumn
+}
+\newcommand*{\@dtl@getkeyforcolumn}[3]{%
+ \def\@dtl@get@keyforcolumn##1% before stuff
+ \db@plist@elt@w% start of block
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@key@id@w ##2\db@key@id@end@% key
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@plist@elt@end@% end of block
+ ##5\q@nil{\def#1{##2}}%
+ \edef\@dtl@tmp{\expandafter\the\csname dtldb@#2\endcsname}%
+ \expandafter\@dtl@getkeyforcolumn\@dtl@tmp
+ \db@plist@elt@w% start of block
+ \db@col@id@w #3\db@col@id@end@ index
+ \db@key@id@w \@nil\db@key@id@end@% key
+ \db@type@id@w \db@type@id@end@% data type
+ \db@header@id@w \db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% index
+ \db@plist@elt@end@% end of block
+ \q@nil
+}
+\def\DTLunsettype{}
+\def\DTLstringtype{0}
+\def\DTLinttype{1}
+\def\DTLrealtype{2}
+\def\DTLcurrencytype{3}
+\newcommand*{\DTLgetdatatype}{%
+ \@ifstar\@sdtlgetdatatype\@dtlgetdatatype
+}
+\newcommand*{\@dtlgetdatatype}[3]{%
+ \DTLifdbexists{#2}%
+ {%
+ \@sDTLifhaskey{#2}{#3}%
+ {%
+ \@sdtlgetdatatype{#1}{#2}{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Key `#3' undefined in database `#2'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@sdtlgetdatatype}[3]{%
+ \edef\@dtl@dogetdata{\noexpand\@dtl@getdatatype{\noexpand#1}%
+ {\expandafter\the\csname dtlkeys@#2\endcsname}%
+ {\dtl@columnindex{#2}{#3}}}%
+ \@dtl@dogetdata
+}
+\newcommand*{\@dtl@getdatatype}[3]{%
+ \def\@dtl@get@keydata##1% stuff before
+ \db@plist@elt@w% start of key block
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@key@id@w ##2\db@key@id@end@% key id
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@plist@elt@end@% end of key block
+ ##5% stuff afterwards
+ \q@nil{\def#1{##3}}%
+ \@dtl@get@keydata#2\q@nil
+}
+\newcommand*{\@dtl@getprops}[7]{%
+ \def\@dtl@get@keydata##1% stuff before
+ \db@plist@elt@w% start of key block
+ \db@col@id@w #7\db@col@id@end@% column index
+ \db@key@id@w ##2\db@key@id@end@% key id
+ \db@type@id@w ##3\db@type@id@end@% data type
+ \db@header@id@w ##4\db@header@id@end@% header
+ \db@col@id@w #7\db@col@id@end@% column index
+ \db@plist@elt@end@% end of key block
+ ##5% stuff afterwards
+ \q@nil{%
+ \def#1{##2}% key
+ \def#2{##3}% data type
+ #3={##4}% header
+ #4={##1}% before stuff
+ #5={##5}% after stuff
+ }%
+ \@dtl@get@keydata#6\q@nil
+}
+\newtoks\@dtl@before
+\newtoks\@dtl@after
+\newtoks\@dtl@colhead
+\newcommand*{\@dtl@updatekeys}[3]{%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+ \edef\@dtl@dogetprops{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand\@dtl@type}%
+ {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}%
+ {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}%
+ {\number\dtlcolumnnum}}
+ \@dtl@dogetprops
+ \def\@dtl@tmp{#3}%
+ \ifx\@dtl@tmp\@empty
+ \else
+ \let\@dtl@oldtype\@dtl@type
+ \@dtl@checknumerical{#3}%
+ \ifx\@dtl@type\@empty
+ \edef\@dtl@type{\number\@dtl@datatype}%
+ \else
+ \ifcase\@dtl@datatype % string
+ \def\@dtl@type{0}%
+ \or % int
+ \or % real
+ \ifnum\@dtl@type=1\relax
+ \def\@dtl@type{2}%
+ \fi
+ \or % currency
+ \ifnum\@dtl@type>0\relax
+ \def\@dtl@type{3}%
+ \fi
\fi
\fi
- \or
- \ifnum\@dtl@datatype=0\relax
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{0}%
+ \ifx\@dtl@oldtype\@dtl@type
\else
- \expandafter\gdef\csname @dtl@idtype@#1@#2\endcsname{3}%
+ \toks@gconcat@middle@cx{dtlkeys@#1}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@plist@elt@w% start of key block
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@% column index
+ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@% key id
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@% data type
+ \noexpand\db@header@id@w \the\@dtl@colhead
+ \noexpand\db@header@id@end@% header
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@% column index
+ \noexpand\db@plist@elt@end@% end of key block
+ }%
+ {\@dtl@after}%
\fi
\fi
- \fi
-\fi
-}%
+ }%
+ {%
+ \expandafter\global\expandafter\advance
+ \csname dtlcols@#1\endcsname by 1\relax
+ \dtlcolumnnum=\csname dtlcols@#1\endcsname\relax
+ \expandafter\xdef\csname dtl@ci@#1@#2\endcsname{%
+ \number\dtlcolumnnum}%
+ \def\@dtl@tmp{#3}%
+ \ifx\@dtl@tmp\@empty
+ \edef\@dtl@type{}% don't know data type yet
+ \else
+ \@dtl@checknumerical{#3}%
+ \edef\@dtl@type{\number\@dtl@datatype}%
+ \fi
+ \toks@gput@right@cx{dtlkeys@#1}%
+ {%
+ \noexpand\db@plist@elt@w
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@key@id@w #2\noexpand\db@key@id@end@
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@
+ \noexpand\db@header@id@w #2\noexpand\db@header@id@end@
+ \noexpand\db@col@id@w \the\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@plist@elt@end@
+ }%
+ }%
}
-\newcommand*{\@dtl@setkeys}[2]{%
-\edef\@dtl@tmp{\csname dtlkeys@#2\endcsname}%
-\expandafter\@dtl@toks\expandafter{\@dtl@tmp}%
-\expandafter\ifx\csname dtlkeys@#2\endcsname\@empty
- \expandafter\gdef\csname dtlkeys@#2\endcsname{#1}%
-\else
- \@for\dtl@key:=\@dtl@tmp\do{%
- \ifthenelse{\equal{\dtl@key}{#1}}{\@endfortrue}{}%
+\newcommand*{\DTLsetheader}{\@ifstar\@sDTLsetheader\@DTLsetheader}
+\newcommand*{\@DTLsetheader}[3]{%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sDTLsetheader{#1}{#2}{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't contain key
+ `#2'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#1' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@sDTLsetheader}[3]{%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+ \@dtl@setheaderforindex{#1}{\dtlcolumnnum}{#3}%
+}
+\newcommand*{\@dtl@setheaderforindex}[3]{%
+ \edef\@dtl@dogetprops{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand\@dtl@type}%
+ {\noexpand\@dtl@colhead}{\noexpand\@dtl@before}%
+ {\noexpand\@dtl@after}{\the\csname dtlkeys@#1\endcsname}%
+ {\number#2}}
+ \@dtl@dogetprops
+ \@dtl@colhead={#3}%
+ \edef\@dtl@colnum{\number#2}\relax
+ \toks@gconcat@middle@cx{dtlkeys@#1}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@plist@elt@w% start of block
+ \noexpand\db@col@id@w \@dtl@colnum
+ \noexpand\db@col@id@end@% index
+ \noexpand\db@key@id@w \@dtl@key\noexpand\db@key@id@end@% key
+ \noexpand\db@type@id@w \@dtl@type
+ \noexpand\db@type@id@end@% data type
+ \noexpand\db@header@id@w \the\@dtl@colhead
+ \noexpand\db@header@id@end@% header
+ \noexpand\db@col@id@w \@dtl@colnum
+ \noexpand\db@col@id@end@% index
+ \noexpand\db@plist@elt@end@% end of block
}%
- \if@endfor
+ {\@dtl@after}%
+}
+\newcommand{\DTLnewdbentry}{%
+ \@ifstar\@sDTLnewdbentry\@DTLnewdbentry
+}
+\newcommand{\@DTLnewdbentry}[3]{%
+ \DTLifdbexists{#1}%
+ {\@sDTLnewdbentry{#1}{#2}{#3}}%
+ {\PackageError{datatool}{Can't add new entry to database `#1':
+ database doesn't exist}{}}%
+}
+\newcommand*{\@sDTLnewdbentry}[3]{%
+ \@dtl@updatekeys{#1}{#2}{#3}%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{#1}{#2}\relax
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}%
+ {\number\csname dtlrows@#1\endcsname}}%
+ \dtl@dogetrow
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+ \@dtl@toks{#3}%
+ \toks@gconcat@middle@cx{dtldb@#1}%
+ {\dtlbeforerow}%
+ {%
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \the\dtlcurrentrow
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ \noexpand\db@row@id@w \number\csname dtlrows@#1\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ {\dtlafterrow}%
+ \dtl@message{Added #2\space -> #3\space to database `#1'}%
\else
- \expandafter\xdef\csname dtlkeys@#2\endcsname{\the\@dtl@toks,#1}%
+ \PackageError{datatool}{Can't add entry with ID `#2' to
+ current row of database `#1'}{There is already an entry with
+ this ID in the current row}%
\fi
-\fi
}
-\newcommand*{\@dtl@getidtype}[2]{%
-\csname @dtl@idtype@#1@#2\endcsname}
\newcommand{\DTLifdbexists}[3]{%
-\@ifundefined{dtldb@#1}{#3}{#2}}
-\newcommand{\dtl@ifrowcontains}[4]{%
-\@for\@dtl@element:=#2\do{%
-\dtl@getentryid{\@dtl@element}{\@dtl@entryid}%
-\ifthenelse{\equal{#1}{\@dtl@entryid}}{\@endfortrue}{}%
-}%
-\if@endfor #3\else #4\fi
-}
-\newcommand*{\dtl@getentryid}[2]{\expandafter\@dtl@getentryid#1#2}
-\long\def\@dtl@getentryid#1#2#3{\def#3{#1}}
-\newcommand*{\dtl@getentryvalue}[2]{%
-\expandafter\@dtl@getentryvalue#1#2}
-\long\def\@dtl@getentryvalue#1#2#3{\gdef#3{#2}}
-\global\newcount\dtlforeachlevel
+ \@ifundefined{dtldb@#1}{#3}{#2}}
+\newcommand*{\@dtl@assign}[2]{%
+ \@dtl@assigncmd#1,\@nil\@@{#2}%
+}
+\def\@dtl@assigncmd#1=#2,#3\@@#4{%
+ \@sDTLifhaskey{#4}{#2}%
+ {%
+ \edef\@dtl@dogetentry{%
+ \noexpand\dtlgetentryfromcurrentrow
+ {\noexpand#1}{\dtl@columnindex{#4}{#2}}}%
+ \@dtl@dogetentry
+ \ifx#1\dtlnovalue
+ \@@dtl@setnull{#1}{#2}%
+ \fi
+ \global\let#1=#1\relax
+ }%
+ {%
+ \PackageError{datatool}{Can't assign \string#1\space: there
+ is no key `#2' in data base `#4'}{}%
+ \global\let#1\DTLstringnull
+ }%
+ \def\dtl@tmp{#3}%
+ \ifx\@nnil\dtl@tmp
+ \let\@dtl@next\@dtl@assigncmdnoop
+ \else
+ \let\@dtl@next\@dtl@assigncmd
+ \fi
+ \@dtl@next#3\@@{#4}%
+}
+\def\@dtl@assigncmdnoop#1\@@#2{}
+\newcommand*{\@dtl@setnull}[2]{%
+ \@sDTLifhaskey{\@dtl@dbname}{#2}%
+ {%
+ \@@dtl@setnull{#1}{#2}%
+ }%
+ {%
+ \global\let#1=\DTLstringnull
+ }%
+}
+\newcommand*{\@@dtl@setnull}[2]{%
+ \@sdtlgetdatatype{\@dtl@type}{\@dtl@dbname}{#2}%
+ \ifnum0\@dtl@type=0\relax
+ \global\let#1=\DTLstringnull
+ \else
+ \global\let#1=\DTLnumbernull
+ \fi
+}
+\newcommand*{\DTLstringnull}{NULL}
+\newcommand*{\DTLnumbernull}{0}
+\newcommand*{\DTLifnull}[3]{%
+ \ifx\DTLstringnull#1\relax
+ #2%
+ \else
+ \ifx\DTLnumbernull#1\relax
+ #2%
+ \else
+ #3%
+ \fi
+ \fi
+}
+\def\@dtlnovalue{Undefined Value}
+\def\dtlnovalue{\@dtlnovalue}
+\newcommand*{\DTLgetkeydata}{%
+ \@ifstar\@sdtlgetkeydata\@dtlgetkeydata
+}
+\newcommand*{\@dtlgetkeydata}[5]{%
+ \DTLifdbexists{#2}%
+ {%
+ \@sDTLifhaskey{#2}{#1}%
+ {%
+ \@sdtlgetkeydata{#1}{#2}{#3}{#4}{#5}%
+ }%
+ {%
+ \PackageError{datatool}{Key `#1' not defined in database
+ `#2'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@sdtlgetkeydata}[5]{%
+ \@sdtl@getcolumnindex{#3}{#2}{#1}%
+ \edef\@dtl@dogetkeydata{\noexpand\@dtl@getprops
+ {\noexpand\@dtl@key}{\noexpand#4}{\noexpand\@dtl@colhead}%
+ {\noexpand\@dtl@before}{\noexpand\@dtl@after}%
+ {\expandafter\the\csname dtlkeys@#2\endcsname}%
+ {#3}}%
+ \@dtl@dogetkeydata
+ \edef#5{\the\@dtl@toks}%
+}
+\newcommand{\dtl@gathervalues}[3][key]{%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)\in{#2}\do
+ {%
+ \dtlgetentryfromrow{\@dtl@tmp}{\@dtl@col}{\dtlcurrentrow}%
+ \ifx\@dtl@tmp\dtlnovalue
+ \@dtl@setnull{\@dtl@tmp}{\@dtl@key}%
+ \fi
+ \expandafter\let\csname @dtl@#1@\@dtl@key\endcsname\@dtl@tmp
+ }%
+}
+\newtoks\dtlcurrentrow
+\newtoks\dtlbeforerow
+\newtoks\dtlafterrow
+\newcommand*{\dtlgetrow}[2]{%
+ \expandafter\toks@\expandafter=\csname dtldb@#1\endcsname
+ \edef\@dtl@dogetrow{\noexpand\@dtlgetrow{\the\toks@}{\number#2}}%
+ \@dtl@dogetrow
+}
+\newcommand*{\@dtlgetrow}[2]{%
+ \def\@dtl@getrow##1% before stuff
+ \db@row@elt@w% start of the row
+ \db@row@id@w #2\db@row@id@end@% row id
+ ##2%
+ \db@row@id@w #2\db@row@id@end@% row id
+ \db@row@elt@end@% end of the row
+ ##3% after stuff
+ \q@nil{\dtlbeforerow={##1}\dtlcurrentrow={##2}\dtlafterrow={##3}}%
+ \@dtl@getrow#1\q@nil
+}
+\newcommand*{\dtlgetentryfromcurrentrow}[2]{%
+ \dtlgetentryfromrow{#1}{#2}{\dtlcurrentrow}%
+}
+\newcommand*{\dtlgetentryfromrow}[3]{%
+ \edef\@dtl@do@getentry{\noexpand\dtl@getentryfromrow
+ {\noexpand#1}{\number#2}{\the#3}}%
+ \@dtl@do@getentry
+}
+\newcommand*{\dtl@getentryfromrow}[3]{%
+ \def\dtl@dogetentry##1% before stuff
+ \db@col@id@w #2\db@col@id@end@% Column id
+ \db@col@elt@w ##2\db@col@elt@end@% Value
+ \db@col@id@w #2\db@col@id@end@% Column id
+ ##3% Remaining stuff
+ \q@nil{\def#1{##2}}%
+ \dtl@dogetentry#3%
+ \db@col@id@w #2\db@col@id@end@%
+ \db@col@elt@w \@dtlnovalue\db@col@elt@end@%
+ \db@col@id@w #2\db@col@id@end@%
+ \q@nil
+}
+\newcommand*{\DTLgetvalue}[4]{%
+ \edef\dtl@dogetvalue{\noexpand\dtl@getvalue{\noexpand#1}{#2}%
+ {\number#3}{\number#4}}%
+ \dtl@dogetvalue
+}
+\newcommand*{\dtl@getvalue}[4]{%
+ \def\@dtl@getvalue ##1% stuff before row <r>
+ \db@row@id@w #3\db@row@id@end@% row <r> id
+ ##2% stuff in row <r> before column <c>
+ \db@col@id@w #4\db@col@id@end@% column <c> id
+ \db@col@elt@w ##3\db@col@elt@end@% value
+ ##4% stuff after value
+ \q@nil{\def#1{##3}}%
+ \toks@=\csname dtldb@#2\endcsname
+ \expandafter\@dtl@getvalue\the\toks@% contents of data base
+ \db@row@id@w #3\db@row@id@end@%
+ \db@col@id@w #4\db@col@id@end@%
+ \db@col@elt@w \@dtlnovalue\db@col@elt@end@% undefined value
+ \q@nil
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element at (row=#3,
+ column=#4) in database `#2'}{}%
+ \fi
+}
+\newcommand*{\DTLgetlocation}[4]{%
+ \def\@dtl@getlocation##1% stuff before value
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w ##2\db@col@id@end@% column id
+ ##3% stuff after this column
+ \db@row@id@w ##4\db@row@id@end@% row id
+ ##5% stuff after row
+ \q@nil{\def#1{##4}\def#2{##2}}%
+ \toks@=\csname dtldb@#3\endcsname
+ \expandafter\@dtl@getlocation\the\toks@% contents of data base
+ \db@col@elt@w #4\db@col@elt@end@% value
+ \db@col@id@w \@dtlnovalue\db@col@id@end@% undefined column id
+ \db@row@id@w \@dtlnovalue\db@row@id@end@% undefined row id
+ \q@nil
+ \ifx#1\dtlnovalue
+ \PackageError{datatool}{There is no element `#4' in
+ database `#3'}{}%
+ \fi
+}
+
+\newcommand*{\dtlbreak}{%
+ \PackageError{datatool}{Can't break out of anything}{}%
+}
+\long\def\dtlforint#1=#2\to#3\step#4\do#5{%
+ \let\@dtl@orgbreak\dtlbreak
+ \def\@dtl@endloophook{}%
+ \def\dtlbreak{\def\@dtl@endloophook{#1=#3}}%
+ #1=#2\relax
+ \ifnum#4<0\relax
+ \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \@dtl@endloophook
+ \advance#1 by #4\relax
+ }%
+ \else
+ \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \@dtl@endloophook
+ \advance#1 by #4\relax
+ }%
+ \fi
+ \let\dtlbreak\@dtl@orgbreak
+}
+\newcount\@dtl@foreach@level
+\long\def\dtlgforint#1=#2\to#3\step#4\do#5{%
+ \global#1=#2\relax
+ \global\advance\@dtl@foreach@level by 1\relax
+ \expandafter\global\expandafter
+ \let\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \relax
+ \expandafter\global\expandafter
+ \let\csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+ \gdef\dtlbreak{\expandafter
+ \gdef\csname @dtl@endhook@\the\@dtl@foreach@level\endcsname{%
+ #1=#3}}%
+ \ifnum#4<0\relax
+ \whiledo{\(#1>#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \global\advance#1 by #4\relax
+ }%
+ \else
+ \whiledo{\(#1<#3\)\TE@or\(#1=#3\)}%
+ {%
+ #5%
+ \csname @dtl@endhook@\the\@dtl@foreach@level\endcsname
+ \global\advance#1 by #4\relax
+ }%
+ \fi
+ \expandafter\global\expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \global\advance\@dtl@foreach@level by -1\relax
+}
+\long\def\@dtlforeachrow(#1,#2)\in#3\do#4{%
+ \edef\dtl@tmp{\expandafter\the\csname dtldb@#3\endcsname}%
+ \expandafter\@dtl@foreachrow\dtl@tmp
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@@{#1}{#2}{#4}\q@nil
+}
+\long\def\@dtl@foreachrow\db@row@elt@w%
+\db@row@id@w #1\db@row@id@end@%
+#2\db@row@id@w #3\db@row@id@end@%
+\db@row@elt@end@#4\@@#5#6#7\q@nil{%
+ \gdef#5{#1}%
+ \gdef\@dtl@loopbody{#7}%
+ \global\advance\@dtl@foreach@level by 1\relax
+ \ifx#5\@nnil
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop
+ \else
+ \gdef#6{#2}%
+ \expandafter\let
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+ \gdef\dtlbreak{\expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop}%
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachrow
+ \@dtl@loopbody
+ \expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \fi
+ \expandafter\let\expandafter\@dtl@foreachnext
+ \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ \global\advance\@dtl@foreach@level by -1\relax
+ \@dtl@foreachnext#4\@@{#5}{#6}{#7}\q@nil
+}
+\long\def\@dtl@foreachnoop#1\@@#2\q@nil{}
+\long\def\dtlforeachkey(#1,#2,#3,#4)\in#5\do#6{%
+ \gdef\@dtl@loopbody{#6}%
+ \edef\@dtl@keys{\expandafter\the\csname dtlkeys@#5\endcsname}%
+ \expandafter\@dtl@foreachkey\@dtl@keys
+ \db@plist@elt@w%
+ \db@col@id@w -1\db@col@id@end@%
+ \db@key@id@w \db@key@id@end@%
+ \db@type@id@w \db@type@id@end@%
+ \db@header@id@w \db@header@id@end@%
+ \db@col@id@w -1\db@col@id@end@%
+ \db@plist@elt@end@%
+ \@@{\@dtl@updatefkcs{#1}{#2}{#3}{#4}}\q@nil
+}
+\newcommand*{\@dtl@updatefkcs}[8]{%
+ \gdef#1{#5}%
+ \gdef#2{#6}%
+ \gdef#3{#7}%
+ \gdef#4{#8}%
+}
+\long\def\@dtl@foreachkey\db@plist@elt@w%
+\db@col@id@w #1\db@col@id@end@%
+\db@key@id@w #2\db@key@id@end@%
+\db@type@id@w #3\db@type@id@end@%
+\db@header@id@w #4\db@header@id@end@%
+\db@col@id@w #5\db@col@id@end@%
+\db@plist@elt@end@#6\@@#7\q@nil{%
+ \ifnum#1=-1\relax
+ \let\@dtl@foreachnext\@dtl@foreachnoop
+ \else
+ #7{#2}{#1}{#3}{#4}%
+ \global\advance\@dtl@foreach@level by 1\relax
+ \expandafter\let
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \dtlbreak
+ \gdef\dtlbreak{\expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachnoop}%
+ \expandafter\global\expandafter
+ \let\csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ =\@dtl@foreachkey
+ \@dtl@loopbody
+ \expandafter\let\expandafter\@dtl@foreachnext
+ \csname @dtl@foreachnext\the\@dtl@foreach@level\endcsname
+ \expandafter\let\expandafter\dtlbreak
+ \csname @dtl@break@\the\@dtl@foreach@level\endcsname
+ \global\advance\@dtl@foreach@level by -1\relax
+ \fi
+ \@dtl@foreachnext#6\@@{#7}\q@nil
+}
+\newcommand*{\dtlforcolumn}{\@ifstar\@sdtlforcolumn\@dtlforcolumn}
+\newcommand{\@dtlforcolumn}[4]{%
+ \DTLifdbexists{#2}%
+ {%
+ \@dtlifhaskey{#2}{#3}%
+ {%
+ \@sdtlforcolumn{#1}{#2}{#3}{#4}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't contain
+ key `#3'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand{\@sdtlforcolumn}[4]{%
+ \toks@{#4}%
+ \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
+ {\expandafter\the\csname dtldb@#2\endcsname}%
+ {\dtl@columnindex{#2}{#3}}{\the\toks@}%
+ }%
+ \@dtl@doforcol%
+}
+\newcommand*{\dtlforcolumnidx}{%
+ \@ifstar\@sdtlforcolumnidx\@dtlforcolumnidx
+}
+\newcommand{\@dtlforcolumnidx}[4]{%
+ \DTLifdbexists{#2}%
+ {%
+ \expandafter\ifnum\csname dtlcols@#2\endcsname<#3\relax
+ \PackageError{datatool}{Column index \number#3\space out of
+ bounds for database `#2'}{Database `#2' only has
+ \expandafter\number\csname dtlcols@#2\endcsname\space
+ columns}%
+ \else
+ \ifnum#3<1\relax
+ \PackageError{datatool}{Column index \number#3\space out of
+ bounds for database `#2'}{Indices start from 1}%
+ \else
+ \@sdtlforcolumnidx{#1}{#2}{#3}{#4}%
+ \fi
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand{\@sdtlforcolumnidx}[4]{%
+ \toks@{#4}%
+ \edef\@dtl@doforcol{\noexpand\dtl@forcolumn{\noexpand#1}%
+ {\expandafter\the\csname dtldb@#2\endcsname}%
+ {\number#3}{\the\toks@}%
+ }%
+ \@dtl@doforcol
+}
+\newcommand{\dtl@forcolumn}[4]{%
+ \let\@dtl@oldbreak\dtlbreak
+ \def\dtlbreak{\let\@dtl@forcolnext=\@dtl@forcolnoop}%
+ \def\@dtl@forcolumn##1% before stuff
+ \db@col@id@w #3\db@col@id@end@% column index
+ \db@col@elt@w ##2\db@col@elt@end@% entry
+ \db@col@id@w #3\db@col@id@end@% column index
+ ##3% after stuff
+ \q@nil{%
+ \def#1{##2}% assign value to <cs>
+ \ifx#1\@nnil
+ \let\@dtl@forcolnext=\@dtl@forcolnoop
+ \else
+ #4%
+ \let\@dtl@forcolnext=\@dtl@forcolumn
+ \fi
+ \@dtl@forcolnext##3\q@nil
+ }%
+ \@dtl@forcolumn#2%
+ \db@col@id@w #3\db@col@id@end@%
+ \db@col@elt@w \@nil\db@col@elt@end@%
+ \db@col@id@w #3\db@col@id@end@\q@nil
+ \let\dtlbreak\@dtl@oldbreak
+}
+\def\@dtl@forcolnoop#1\q@nil{}
+
+\newcount\dtlforeachlevel
\newcounter{DTLrowi}
\newcounter{DTLrowii}
\newcounter{DTLrowiii}
@@ -1520,6 +2168,18 @@ the current row}}{%
\def\theHDTLrowi{\theHDTLrow.\arabic{DTLrowi}}
\def\theHDTLrowii{\theHDTLrowi.\arabic{DTLrowii}}
\def\theHDTLrowiii{\theHDTLrowii.\arabic{DTLrowiii}}
+\newcount\dtl@rowi
+\newcount\dtl@rowii
+\newcount\dtl@rowiii
+\newtoks\@dtl@curi
+\newtoks\@dtl@previ
+\newtoks\@dtl@nexti
+\newtoks\@dtl@curii
+\newtoks\@dtl@previi
+\newtoks\@dtl@nextii
+\newtoks\@dtl@curiii
+\newtoks\@dtl@previii
+\newtoks\@dtl@nextiii
\newcommand*{\DTLsavelastrowcount}[1]{%
\ifnum\dtlforeachlevel>2\relax
\def#1{0}%
@@ -1535,492 +2195,1098 @@ the current row}}{%
\fi}
\newcommand*{\DTLforeach}{\@ifstar\@sDTLforeach\@DTLforeach}
\newcommand{\@DTLforeach}[4][\boolean{true}]{%
-\DTLifdbexists{#2}{%
-\refstepcounter{DTLrow}%
-\global\c@DTLrow=\c@DTLrow
-\gdef\@dtl@dbname{#2}%
-\global\advance\dtlforeachlevel by 1\relax
-\ifnum\dtlforeachlevel>3\relax
- \PackageError{datatool}{\string\DTLforeach\space nested too
-deeply}{}%
-\else
- \expandafter\global
- \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax
- \expandafter\global\expandafter\let
- \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
- =\@empty
- \expandafter\global\expandafter\let
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- =\@dtl@dbname
- \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \expandafter\global\expandafter
- \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
- \endcsname=\@dtl@currentrow
- \global\let\@dtl@nextrow\@xfor@nextelement
- \ifx\relax#3\relax
- \else
- \@dtl@assign{#3}%
- \fi
- \ifthenelse{#1}{%
- \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
- \expandafter\edef\expandafter\DTLcurrentindex\expandafter
- {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
- #4%
- }{}%
- \expandafter\let\expandafter\@dtl@thiscurrentrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \ifx\@dtl@thiscurrentrow\@empty
- \else
- \expandafter\@dtl@toks\expandafter{\@dtl@thiscurrentrow}%
- \expandafter
- \ifx
- \csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
- \@empty
- \expandafter
- \xdef\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname{%
- {\the\@dtl@toks}}%
+ \DTLifdbexists{#2}%
+ {%
+ \refstepcounter{DTLrow}%
+ \global\c@DTLrow=\c@DTLrow\relax
+ \gdef\@dtl@dbname{#2}%
+ \global\advance\dtlforeachlevel by 1\relax
+ \ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+ deeply}{Only 3 levels are allowed}%
\else
- \expandafter\let\expandafter\@dtl@foreachrows\expandafter
- =\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
- \expandafter\toks@\expandafter{\@dtl@foreachrows}%
- \expandafter
- \xdef\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname{%
- \the\toks@,{\the\@dtl@toks}}%
+ \@DTLifdbempty{#2}%
+ {}%
+ {%
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \DTLiffirstrow
+ \gdef\DTLiffirstrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =1\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \DTLiflastrow
+ \gdef\DTLiflastrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =\csname dtlcols@#2\endcsname\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ \DTLifoddrow
+ \gdef\DTLifoddrow##1##2{%
+ \expandafter\ifodd
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ =\@dtl@dbname
+ \expandafter\global\expandafter\let
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+ \dtlgforint
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ =1\to\csname dtlrows@#2\endcsname\step1\do
+ {%
+ \@dtl@tmpcount=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#2}%
+ {\number\@dtl@tmpcount}}%
+ \dtl@dogetrow
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \dtlcurrentrow
+ \expandafter\global
+ \csname @dtl@prev\romannumeral\dtlforeachlevel\endcsname
+ = \dtlbeforerow
+ \expandafter\global
+ \csname @dtl@next\romannumeral\dtlforeachlevel\endcsname
+ = \dtlafterrow
+ \ifx\relax#3\relax
+ \else
+ \@dtl@assign{#3}{#2}%
+ \fi
+ \ifthenelse{#1}%
+ {%
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex%
+ \expandafter{%
+ \arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ \edef\@dtl@tmp{\expandafter\the
+ \csname @dtl@cur\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \ifx\@dtl@tmp\@nnil
+ \expandafter\dtl@decrementrows\expandafter
+ {\csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ }{\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \expandafter\dtl@decrementrows\expandafter
+ {\csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ }{\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname}%
+ \edef\@dtl@tmp{%
+ \expandafter\the
+ \csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ \expandafter\the
+ \csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ }%
+ \expandafter\global\expandafter
+ \csname dtldb@#2\endcsname\expandafter{\@dtl@tmp}%
+ \expandafter\global\expandafter
+ \advance\csname dtlrows@#2\endcsname by -1\relax
+ \expandafter\global\expandafter
+ \advance\csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname by -1\relax
+ \else
+ \@dtl@before=\csname @dtl@prev\romannumeral
+ \dtlforeachlevel\endcsname
+ \@dtl@after=\csname @dtl@next\romannumeral
+ \dtlforeachlevel\endcsname
+ \toks@gconcat@middle@cx{dtldb@#2}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \expandafter\number
+ \csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@end@%
+ \expandafter\the
+ \csname @dtl@cur\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@w \expandafter\number
+ \csname dtl@row\romannumeral
+ \dtlforeachlevel\endcsname
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ {\@dtl@after}%
+ \fi
+ }%
+ {}%
+ }%
+ \expandafter\global\expandafter\let\expandafter\DTLiffirstrow
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \expandafter\global\expandafter\let\expandafter\DTLiflastrow
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \expandafter\global\expandafter\let\expandafter\DTLifoddrow
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ }%
\fi
- \fi
-\@endforfalse
-}%
-\expandafter\let\expandafter\@dtl@foreachrows\expandafter
- =\csname @dtl@foreachrows@\romannumeral\dtlforeachlevel\endcsname
-\expandafter\global
- \expandafter\let\csname dtldb@#2\endcsname=\@dtl@foreachrows
-\fi
-\global\advance\dtlforeachlevel by -1\relax
-}{%
-\PackageError{datatool}{Database `#2' doesn't exist}{}}%
+ \global\advance\dtlforeachlevel by -1\relax
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
}
\newcommand{\@sDTLforeach}[4][\boolean{true}]{%
-\DTLifdbexists{#2}{%
-\refstepcounter{DTLrow}%
-\global\c@DTLrow=\c@DTLrow
-\gdef\@dtl@dbname{#2}%
-\global\advance\dtlforeachlevel by 1\relax
-\ifnum\dtlforeachlevel>3\relax
- \PackageError{datatool}{\string\DTLforeach\space nested too
-deeply}{}%
-\else
- \expandafter\global
- \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname = 0\relax
- \expandafter\global\expandafter\let
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- =\@nnil
- \expandafter\let\expandafter\@dtl@db\csname dtldb@#2\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \expandafter\global\expandafter
- \let\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel
- \endcsname=\@dtl@currentrow
- \global\let\@dtl@nextrow\@xfor@nextelement
- \ifx\relax#3\relax
+ \DTLifdbexists{#2}%
+ {%
+ \refstepcounter{DTLrow}%
+ \global\c@DTLrow=\c@DTLrow
+ \global\advance\dtlforeachlevel by 1\relax
+ \ifnum\dtlforeachlevel>3\relax
+ \PackageError{datatool}{\string\DTLforeach\space nested too
+ deeply}{Only 3 levels are allowed}%
+ \else
+ \@DTLifdbempty{#2}%
+ {}%
+ {%
+ \expandafter\global
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ = 0\relax
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \DTLiffirstrow
+ \gdef\DTLiffirstrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =1\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \DTLiflastrow
+ \gdef\DTLiflastrow##1##2{%
+ \expandafter\ifnum
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ =\csname dtlcols@#2\endcsname\relax
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\global\expandafter\let%
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ \DTLifoddrow
+ \gdef\DTLifoddrow##1##2{%
+ \expandafter\ifodd
+ \csname c@DTLrow\romannumeral\dtlforeachlevel\endcsname
+ ##1%
+ \else
+ ##2%
+ \fi}%
+ \expandafter\gdef\csname @dtl@dbname@\romannumeral
+ \dtlforeachlevel\endcsname{#2}%
+ \expandafter\global\expandafter\let
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname
+ = 1\relax
+ \@dtlforeachrow(\dtl@thisidx,\dtl@thisrow)\in{#2}\do%
+ {%
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname
+ = \dtl@thisidx\relax
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \expandafter{\dtl@thisrow}%
+ \ifx\relax#3\relax
+ \else
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \@dtl@assign{#3}{#2}%
+ \fi
+ \ifthenelse{#1}%
+ {%
+ \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
+ \expandafter\edef\expandafter\DTLcurrentindex%
+ \expandafter{%
+ \arabic{DTLrow\romannumeral\dtlforeachlevel}}%
+ #4%
+ }%
+ {}%
+ }%
+ \expandafter\global\expandafter\let\expandafter\DTLiffirstrow
+ \csname @dtl@iffirstrow\the\dtlforeachlevel\endcsname
+ \expandafter\global\expandafter\let\expandafter\DTLiflastrow
+ \csname @dtl@iflastrow\the\dtlforeachlevel\endcsname
+ \expandafter\global\expandafter\let\expandafter\DTLifoddrow
+ \csname @dtl@ifoddrow\the\dtlforeachlevel\endcsname
+ }%
+ \fi
+ \global\advance\dtlforeachlevel by -1\relax
+ }%
+ {%
+ \PackageError{datatool}{Database `#2' doesn't exist}{}%
+ }%
+}
+\newcommand*{\@dtlifreadonly}[2]{%
+ \expandafter\ifx
+ \csname @dtl@ro@\romannumeral\dtlforeachlevel\endcsname1\relax
+ #1%
\else
- \@dtl@assign{#3}%
+ #2%
\fi
- \ifthenelse{#1}{%
- \refstepcounter{DTLrow\romannumeral\dtlforeachlevel}%
- \expandafter\edef\expandafter\DTLcurrentindex\expandafter
- {\arabic{DTLrow\romannumeral\dtlforeachlevel}}%
- #4%
- }{}%
-\@endforfalse
-}%
-\fi
-\global\advance\dtlforeachlevel by -1\relax
-}{%
-\PackageError{datatool}{Database `#2' doesn't exist}{}}%
}
\newcommand*{\DTLappendtorow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLappendtorow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\let\expandafter\@dtl@thisdb
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLappendtorow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
- \else
- \expandafter\@dtl@toks\expandafter{#2}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
- \edef\@dtl@dbid{#1}%
- \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
- \PackageError{datatool}{Can't add entry with ID `#1' to current
- row of database `\@dtl@thisdb'}{There is already an entry with
- this ID on the current row}}{%
- \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
- \ifx\@dtl@thisrow\@empty
- \expandafter
- \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{%
- \the\@dtl@toks}%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLappendrow\space can only be
+ used inside \string\DTLforeach}{}%
\else
- \expandafter\toks@\expandafter{\@dtl@thisrow}%
- \expandafter
- \xdef\csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname{%
- \the\toks@,\the\@dtl@toks}%
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLappendtorow\space can't
+ be used inside \DTLforeach*}{The starred version of
+ \string\DTLforeach\space is read only}%
+ }%
+ {%
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+ \@dtl@updatekeys{\@dtl@thisdb}{#1}{#2}%
+ \expandafter\dtlcolumnnum\expandafter
+ =\dtl@columnindex{\@dtl@thisdb}{#1}\relax
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+ \expandafter\@dtl@toks\expandafter{#2}%
+ \toks@gput@right@cx{@dtl@cur\romannumeral\dtlforeachlevel}%
+ {%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@
+ }%
+ \dtl@message{Appended #1\space -> #2\space to database
+ `\@dtl@thisdb'}%
+ \else
+ \PackageError{datatool}{Can't append entry to row:
+ there is already an entry for key `#1' in this row}{}%
+ \fi
+ }%
\fi
- }
- \@dtl@setidtype{\@dtl@thisdb}{#1}{#2}%
- \expandafter\@dtl@setkeys\expandafter{#1}{\@dtl@thisdb}%
- \fi
-\fi
}
\newcommand*{\DTLremoveentryfromrow}[1]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLremoveentryfromrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\let\expandafter\@dtl@thisdb
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLremoveentryfromrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremoventryfromrow\space
+ can only be used inside \string\DTLforeach}{}%
\else
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
- \let\@dtl@pre=\@empty
- \@for\dtl@thisentry:=\@dtl@thisrow\do{%
- \dtl@getentryid\dtl@thisentry\@dtl@id
- \ifthenelse{\equal{\@dtl@id}{#1}}{%
- }{%
- \expandafter\@dtl@toks\expandafter{\dtl@thisentry}%
- \ifx\@dtl@pre\@empty
- \edef\@dtl@pre{{\the\@dtl@toks}}%
- \else
- \expandafter\toks@\expandafter{\@dtl@pre}%
- \edef\@dtl@pre{\the\toks@,{\the\@dtl@toks}}%
- \fi
- }
- }%
- \expandafter\let
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- =\@dtl@pre
- }{%
- \PackageError{datatool}{Can't remove entry given by key `#1'
- from current row in database `\@dtl@thisdb', no such entry}{}%
- }%
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLremoveentryfromrow\space
+ can't be used inside \string\DTLforeach*}{The starred
+ version of \string\DTLforeach\space is read only}%
+ }%
+ {%
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+ \@dtlifhaskey{\@dtl@thisdb}{#1}%
+ {%
+ \dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax
+ \dtlcolumnnum=\thiscol\relax
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+ \PackageError{datatool}{Can't remove entry given by `#1'
+ from current row in database `\@dtl@thisdb': no such
+ entry}{The current row doesn't contain an entry for
+ key `#1'}%
+ \else
+ \edef\@dtl@dosplitrow{%
+ \noexpand\dtlsplitrow{\the\dtlcurrentrow}%
+ {\number\dtlcolumnnum}{\noexpand\dtl@pre}%
+ {\noexpand\dtl@post}%
+ }%
+ \@dtl@dosplitrow
+ \expandafter\@dtl@toks\expandafter{\dtl@pre}%
+ \expandafter\toks@\expandafter{\dtl@post}%
+ \edef\@dtl@tmp{\the\@dtl@toks \the\toks@}%
+ \dtlcurrentrow=\expandafter{\@dtl@tmp}%
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ = \dtlcurrentrow
+ \dtl@message{Removed entry given by #1\space from current
+ row of database `\@dtl@thisdb'}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't remove entry given by
+ `#1' - no such key exists}{}%
+ }%
+ }%
\fi
-\fi
}
\newcommand*{\DTLreplaceentryforrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLreplaceentryforrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\let\expandafter\@dtl@thisdb
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
- \ifx\@dtl@thisdb\@nnil
- \PackageError{datatool}{\string\DTLreplaceentryforrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can only be used inside \string\DTLforeach}{}%
\else
- \expandafter\@dtl@toks\expandafter{#2}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
- \edef\@dtl@dbid{#1}%
- \edef\dtl@newentry{{\@dtl@dbid}{\the\@dtl@toks}}%
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \dtl@ifrowcontains{#1}{\@dtl@thisrow}{%
- \let\@dtl@pre=\@empty
- \@for\dtl@thisentry:=\@dtl@thisrow\do{%
- \dtl@getentryid\dtl@thisentry\@dtl@id
- \ifthenelse{\equal{\@dtl@id}{#1}}{%
- \expandafter\@dtl@toks\expandafter{\dtl@newentry}%
- }{%
- \expandafter\@dtl@toks\expandafter{\dtl@thisentry}%
- }
- \ifx\@dtl@pre\@empty
- \edef\@dtl@pre{{\the\@dtl@toks}}%
- \else
- \expandafter\toks@\expandafter{\@dtl@pre}%
- \edef\@dtl@pre{\the\toks@,{\the\@dtl@toks}}%
- \fi
- }%
- \expandafter\let
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- =\@dtl@pre
- }{%
- \PackageError{datatool}{Can't remove entry given by key `#1'
- from current row in database `\@dtl@thisdb', no such entry}{}%
- }%
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can't be used inside \string\DTLforeach*}{The starred version
+ of \string\DTLforeach\space is read only}%
+ }%
+ {%
+ \dtlrownum=
+ \csname dtl@row\romannumeral\dtlforeachlevel\endcsname\relax
+ \@dtlifhaskey{\@dtl@thisdb}{#1}%
+ {%
+ \dtl@getcolumnindex{\thiscol}{\@dtl@thisdb}{#1}\relax
+ \dtlcolumnnum=\thiscol\relax
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\dtl@entry}{\number\dtlcolumnnum}%
+ }%
+ \dtl@dogetentry
+ \ifx\dtl@entry\dtlnovalue
+ \PackageError{datatool}{Can't replace entry given by `#1'
+ from current row in database `\@dtl@thisdb': no such
+ entry}{The current row doesn't contain an entry for
+ key `#1'}%
+ \else
+ \edef\@dtl@dosplitrow{%
+ \noexpand\dtlsplitrow{\the\dtlcurrentrow}%
+ {\number\dtlcolumnnum}{\noexpand\dtl@pre}%
+ {\noexpand\dtl@post}%
+ }%
+ \@dtl@dosplitrow
+ \@dtl@toks{#2}% new value
+ \expandafter\@dtl@before\expandafter{\dtl@pre}%
+ \expandafter\@dtl@after\expandafter{\dtl@post}%
+ \toks@gconcat@middle@cx
+ {@dtl@cur\romannumeral\dtlforeachlevel}%
+ {\@dtl@before}%
+ {%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ \noexpand\db@col@elt@w \the\@dtl@toks
+ \noexpand\db@col@elt@end@%
+ \noexpand\db@col@id@w \number\dtlcolumnnum
+ \noexpand\db@col@id@end@%
+ }%
+ {\@dtl@after}%
+ \dtl@message{Updated #1\space -> #2\space in database
+ `\@dtl@thisdb'}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't replace key `#1' - no such
+ key in database `\@dtl@thisdb'}{}%
+ }%
+ }%
\fi
-\fi
}
\newcommand*{\DTLremovecurrentrow}{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLremovecurrentrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\ifx
- \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname\@nnil
- \PackageError{datatool}{\string\DTLremovecurrentrow\space can't
- be used inside \string\DTLforeach*}{The starred version of
- \string\DTLforeach\space is read only}%
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLremovecurrentrow\space can
+ only be used inside \string\DTLforeach}{}%
\else
- \expandafter\let
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- =\@empty
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \@dtlifreadonly
+ {%
+ \PackageError{datatool}{\string\DTLreplaceentryforrow\space
+ can't be used inside \string\DTLforeach*}{The starred version
+ of \string\DTLforeach\space is read only}%
+ }%
+ {%
+ \expandafter\global
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ ={\@nil}%
+ }%
\fi
-\fi
+}
+\newcommand{\DTLaddentryforrow}[5]{%
+ \DTLifdbexists{#1}%
+ {
+ \def\@dtl@notdone{\PackageError{datatool}{Unable to add entry
+ given by key `#4': condition not met for any row in database
+ `#1'}{}}%
+ \DTLforeach[#3]{#1}{#2}%
+ {%
+ \DTLappendtorow{#4}{#5}%
+ \let\@dtl@notdone\relax
+ \dtlbreak
+ }%
+ \@dtl@notdone
+ }%
+ {%
+ \PackageError{datatool}{Unable to add entry given by key `#4':
+ database `#1' doesn't exist}{}%
+ }%
}
\newcommand*{\DTLforeachkeyinrow}[2]{%
-\ifnum\dtlforeachlevel=0\relax
- \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only
- be used inside \string\DTLforeach}{}%
-\else
- \expandafter\let\expandafter\@dtl@thisrow
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
- \@for\dtl@thisentry:=\@dtl@thisrow\do{%
- \dtl@getentryvalue\dtl@thisentry{#1}%
- #2%
- }%
-\fi
+ \ifnum\dtlforeachlevel=0\relax
+ \PackageError{datatool}{\string\DTLforeachkeyinrow\space can only
+ be used inside \string\DTLforeach}{}%
+ \else
+ \expandafter\let\expandafter\@dtl@thisdb
+ \csname @dtl@dbname@\romannumeral\dtlforeachlevel\endcsname
+ \dtlforeachkey(\dtlkey,\dtlcol,\dtltype,\dtlheader)\in
+ \@dtl@thisdb\do{%
+ \dtlcurrentrow =
+ \csname @dtl@cur\romannumeral\dtlforeachlevel\endcsname
+ \edef\dtl@dogetentry{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand#1}{\dtlcol}}%
+ \dtl@dogetentry
+ \ifx#1\dtlnovalue
+ \ifnum0\dtltype=0\relax
+ \let#1=\DTLstringnull
+ \else
+ \let#1=\DTLnumbernull
+ \fi
+ \fi
+ \global\let#1#1%
+ \def\@dtl@loop@body{#2}%
+ \@dtl@loop@body
+ }%
+ \fi
}
-\newcommand{\DTLaddentryforrow}[5]{%
-\gdef\@dtl@dbname{#1}%
-\DTLifdbexists{#1}{%
- \expandafter\@dtl@toks\expandafter{#5}%
- \edef\@dtl@dbvalue{\the\@dtl@toks}%
- \edef\@dtl@dbid{#4}%
- \edef\@dtl@dbentry{{\@dtl@dbid}{\the\@dtl@toks}}%
- \expandafter
- \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
- \let\@dtl@prerow=\@empty
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \@dtl@assign{#2}%
- \ifthenelse{#3}{%
- \expandafter\@dtl@toks\expandafter{\@dtl@dbentry}%
- \ifx\@dtl@currentrow\@empty
- \edef\@dtl@currentrow{{\the\@dtl@toks}}%
+\newcommand*{\dtlbetweencols}{}
+\newcommand*{\dtlbeforecols}{}
+\newcommand*{\dtlaftercols}{}
+\newcommand*{\dtlstringalign}{l}
+\newcommand*{\dtlintalign}{r}
+\newcommand*{\dtlrealalign}{r}
+\newcommand*{\dtlcurrencyalign}{r}
+\newcommand*{\dtladdalign}[4]{%
+ \ifnum#3=1\relax
+ \protected@edef#1{\dtlbeforecols}%
+ \else
+ \protected@edef#1{#1\dtlbetweencols}%
+ \fi
+ \ifx\@empty#2\@empty
+ \protected@edef#1{#1c}%
+ \else
+ \ifcase#2\relax
+ \protected@edef#1{#1\dtlstringalign}%
+ \or
+ \protected@edef#1{#1\dtlintalign}%
+ \or
+ \protected@edef#1{#1\dtlrealalign}%
+ \or
+ \protected@edef#1{#1\dtlcurrencyalign}%
\else
- \expandafter\toks@\expandafter{\@dtl@currentrow}%
- \edef\@dtl@currentrow{\the\toks@,{\the\@dtl@toks}}%
+ \protected@edef#1{#1c}%
+ \PackageError{datatool}{Unknown data type `#2'}{}%
\fi
- \@endfortrue
- }{%
+ \fi
+ \ifnum#3=#4\relax
+ \protected@edef#1{#1\dtlaftercols}%
+ \fi
+}
+\newcommand*{\dtlheaderformat}[1]{\null\hfil\textbf{#1}\hfil\null}
+\newcommand*{\dtlstringformat}[1]{#1}
+\newcommand*{\dtlintformat}[1]{#1}
+\newcommand*{\dtlrealformat}[1]{#1}
+\newcommand*{\dtlcurrencyformat}[1]{#1}
+\newcommand*{\dtldisplaystarttab}{}
+\newcommand*{\dtldisplayendtab}{}
+\newcommand*{\dtldisplayafterhead}{}
+\newcommand*{\dtldisplaystartrow}{}
+
+\newcommand*{\DTLdisplaydb}[1]{%
+ \def\@dtl@doamp{\gdef\@dtl@doamp{&}}
+ \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}}
+ \edef\@dtl@maxcols{\expandafter\number
+ \csname dtlcols@#1\endcsname}%
+ \def\@dtl@tabargs{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols
+ }%
+ \edef\@dtl@dobegintab{\noexpand\begin{tabular}{\@dtl@tabargs}}%
+ \@dtl@dobegintab
+ \dtldisplaystarttab
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \@dtl@doamp
+ \dtlheaderformat{\@dtl@head}%
+ }%
+ \\%
+ \dtldisplayafterhead
+ \@dtl@resetdoamp
+ \DTLforeach*{#1}{}{%
+ \DTLiffirstrow{}{\\\dtldisplaystartrow}%
+ \@dtl@resetdoamp
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \global\let\@dtl@val\@dtl@val
+ \@dtl@doamp
+ \@dtl@datatype=0\dtltype\relax
+ \ifcase\@dtl@datatype
+ \dtlstringformat\@dtl@val
+ \or
+ \dtlintformat\@dtl@val
+ \or
+ \dtlrealformat\@dtl@val
+ \or
+ \dtlcurrencyformat\@dtl@val
+ \else
+ \@dtl@val
+ \fi
+ }%
+ }%
+ \dtldisplayendtab
+ \end{tabular}%
+}
+\define@key{displaylong}{caption}{\def\@dtl@cap{#1}}
+\define@key{displaylong}{contcaption}{\def\@dtl@contcap{#1}}
+\define@key{displaylong}{shortcaption}{\def\@dtl@shortcap{#1}}
+\define@key{displaylong}{label}{\def\@dtl@label{#1}}
+\define@key{displaylong}{foot}{\def\@dtl@foot{#1}}
+\define@key{displaylong}{lastfoot}{\def\@dtl@lastfoot{#1}}
+\newcommand*{\@dtl@resetdostartrow}{%
+ \gdef\@dtl@dostartrow{%
+ \gdef\@dtl@dostartrow{\\\dtldisplaystartrow}}%
+}
+\newcommand*{\DTLdisplaylongdb}[2][]{%
+ \def\@dtl@cap{\@nil}%
+ \def\@dtl@contcap{\@nil}%
+ \def\@dtl@label{\@nil}%
+ \def\@dtl@shortcap{\@dtl@cap}%
+ \def\@dtl@foot{\@nil}%
+ \def\@dtl@lastfoot{\@nil}%
+ \setkeys{displaylong}{#1}%
+ \def\@dtl@doamp{\gdef\@dtl@doamp{&}}
+ \def\@dtl@resetdoamp{\gdef\@dtl@doamp{\gdef\@dtl@doamp{&}}}
+ \@dtl@resetdostartrow
+ \edef\@dtl@maxcols{\expandafter\number
+ \csname dtlcols@#2\endcsname}%
+ \def\@dtl@tabargs{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {%
+ \dtladdalign\@dtl@tabargs\@dtl@type\@dtl@idx\@dtl@maxcols
}%
- \expandafter\@dtl@toks\expandafter{\@dtl@currentrow}%
- \ifx\@dtl@prerow\@empty
- \edef\@dtl@prerow{{\the\@dtl@toks}}%
+ \edef\@dtl@dobegintab{\noexpand\begin{longtable}{\@dtl@tabargs}}%
+ \@dtl@dobegintab
+ \dtldisplaystarttab
+ \ifx\@dtl@foot\@nnil
\else
- \expandafter\toks@\expandafter{\@dtl@prerow}%
- \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}%
+ \@dtl@foot\endfoot
\fi
-}%
-\if@endfor
- \expandafter\@dtl@toks\expandafter{\@forremainder}%
- \expandafter\toks@\expandafter{\@dtl@prerow}%
- \edef\@dtl@prerow{\the\toks@,{\the\@dtl@toks}}%
- \expandafter\global\expandafter
- \let\csname dtldb@\@dtl@dbname\endcsname=\@dtl@prerow
-\else
- \PackageError{datatool}{Unable to add `#5' for key `#4' - condition
- not met for any row in database `#1'}{}%
-\fi
-\@endforfalse
-}{%
-\PackageError{datatool}{Database `#1' doesn't exist}{}}%
+ \ifx\@dtl@lastfoot\@nnil
+ \else
+ \@dtl@lastfoot\endlastfoot
+ \fi
+ \ifx\@dtl@cap\@nnil
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endhead\dtldisplayafterhead
+ \else
+ \caption[\@dtl@shortcap]{\@dtl@cap}%
+ \ifx\@dtl@label\@nnil
+ \else
+ \label{\@dtl@label}%
+ \fi
+ \\%
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endfirsthead
+ \ifx\@dtl@contcap\@nnil
+ \caption{\@dtl@cap}%
+ \else
+ \caption{\@dtl@contcap}%
+ \fi
+ \\%
+ \@dtl@resetdoamp
+ \dtlforeachkey(\@dtl@key,\@dtl@idx,\@dtl@type,\@dtl@head)%
+ \in{#2}\do
+ {\@dtl@doamp{\dtlheaderformat{\@dtl@head}}}%
+ \@dtl@resetdoamp
+ \@dtl@resetdostartrow
+ \endhead\dtldisplayafterhead
+ \fi
+ \DTLforeach*{#2}{}{%
+ \@dtl@dostartrow
+ \@dtl@resetdoamp
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \global\let\@dtl@val\@dtl@val
+ \@dtl@doamp
+ \@dtl@datatype=0\dtltype\relax
+ \ifcase\@dtl@datatype
+ \dtlstringformat\@dtl@val
+ \or
+ \dtlintformat\@dtl@val
+ \or
+ \dtlrealformat\@dtl@val
+ \or
+ \dtlcurrencyformat\@dtl@val
+ \fi
+ }%
+ }%
+ \dtldisplayendtab
+ \end{longtable}%
}
-\newcommand*{\@dtl@assign}[2][\@dtl@currentrow]{%
-\@dtl@assigncmd#2,\relax\@@{#1}%
+\newcommand*{\dtlswaprows}[3]{%
+ \ifnum#2=#3\relax
+ \else
+ \ifnum#2<#3\relax
+ \edef\@dtl@rowAidx{\number#2}%
+ \edef\@dtl@rowBidx{\number#3}%
+ \else
+ \edef\@dtl@rowAidx{\number#3}%
+ \edef\@dtl@rowBidx{\number#2}%
+ \fi
+ \edef\@dtl@dosplit{\noexpand\dtlgetrow{#1}{\@dtl@rowAidx}}%
+ \@dtl@dosplit
+ \expandafter\def\expandafter\@dtl@firstpart\expandafter
+ {\the\dtlbeforerow}%
+ \@dtl@toksA=\dtlcurrentrow
+ \edef\@dtl@dosplit{\noexpand\@dtlgetrow
+ {\the\dtlafterrow}{\@dtl@rowBidx}}%
+ \@dtl@dosplit
+ \expandafter\def\expandafter\@dtl@secondpart\expandafter
+ {\the\dtlbeforerow}%
+ \@dtl@toksB=\dtlcurrentrow
+ \expandafter\def\expandafter\@dtl@thirdpart\expandafter
+ {\the\dtlafterrow}%
+ \toks@=\expandafter{\@dtl@firstpart}%
+ \@dtl@toks=\expandafter{\@dtl@secondpart}%
+ \edef\@dtl@tmp{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@%
+ \the\@dtl@toksB
+ \noexpand\db@row@id@w \@dtl@rowAidx\noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ \the\@dtl@toks}%
+ \toks@=\expandafter{\@dtl@tmp}%
+ \@dtl@toks=\expandafter{\@dtl@thirdpart}%
+ \edef\@dtl@tmp{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@%
+ \the\@dtl@toksA
+ \noexpand\db@row@id@w \@dtl@rowBidx\noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ \the\@dtl@toks}%
+ \expandafter\global\csname dtldb@#1\endcsname=\expandafter
+ {\@dtl@tmp}%
+ \fi
}
-\def\@dtl@assigncmd#1=#2,#3\@@#4{%
-\@for\@dtl@entry:=#4\do{%
-\dtl@getentryid\@dtl@entry\@dtl@id
-\ifthenelse{\equal{\@dtl@id}{#2}}{%
-\dtl@getentryvalue\@dtl@entry#1%
-\@endfortrue}{}%
-}%
-\if@endfor
-\else
- \@dtl@setnull{#1}{#2}%
-\fi
-\@endforfalse
-\ifx\relax#3%
- \let\@dtl@next=\@dtl@assigncmdnoop
-\else
- \let\@dtl@next=\@dtl@assigncmd
-\fi
-\@dtl@next#3\@@{#4}%
+\newcommand*{\dtl@decrementrows}[2]{%
+ \def\@dtl@newlist{}%
+ \edef\@dtl@min{\number#2}%
+ \expandafter\@dtl@decrementrows\the#1%
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@nil
+ #1=\expandafter{\@dtl@newlist}%
+}
+\def\@dtl@decrementrows\db@row@elt@w\db@row@id@w #1\db@row@id@end@%
+#2\db@row@id@w #3\db@row@id@end@\db@row@elt@end@#4\@nil{%
+ \def\@dtl@thisrow{#1}%
+ \ifx\@dtl@thisrow\@nnil
+ \let\@dtl@donextdec=\@dtl@gobbletonil
+ \else
+ \ifnum\@dtl@thisrow>\@dtl@min
+ \@dtl@tmpcount=\@dtl@thisrow\relax
+ \advance\@dtl@tmpcount by -1\relax
+ \toks@{#2}%
+ \@dtl@toks=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\@dtl@toks
+ \noexpand\db@row@elt@w% row header
+ \noexpand\db@row@id@w \number\@dtl@tmpcount
+ \noexpand\db@row@id@end@% row id
+ \the\toks@ % row contents
+ \noexpand\db@row@id@w \number\@dtl@tmpcount
+ \noexpand\db@row@id@end@% row id
+ \noexpand\db@row@elt@end@% row end
+ }%
+ \else
+ \toks@{#2}%
+ \@dtl@toks=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\@dtl@toks
+ \noexpand\db@row@elt@w% row header
+ \noexpand\db@row@id@w #1%
+ \noexpand\db@row@id@end@% row id
+ \the\toks@ % row contents
+ \noexpand\db@row@id@w #3%
+ \noexpand\db@row@id@end@% row id
+ \noexpand\db@row@elt@end@% row end
+ }%
+ \fi
+ \let\@dtl@donextdec=\@dtl@decrementrows
+ \fi
+ \@dtl@donextdec#4\@nil
+}
+\newcommand*{\DTLremoverow}[2]{%
+ \DTLifdbexists{#1}%
+ {%
+ \ifnum#2>0\relax
+ \expandafter\ifnum\csname dtlrows@#1\endcsname<#2\relax
+ \expandafter\ifnum\csname dtlrows@#1\endcsname=1\relax
+ \PackageError{datatool}{Can't remove row `\number#2' from
+ database `#1': no such row}{Database `#1' only has
+ 1 row}%
+ \else
+ \PackageError{datatool}{Can't remove row `\number#2' from
+ database `#1': no such row}{Database `#1' only has
+ \expandafter\number\csname dtlrows@#1\endcsname\space
+ rows}%
+ \fi
+ \else
+ \@DTLremoverow{#1}{#2}%
+ \fi
+ \else
+ \PackageError{datatool}{Can't remove row \number#2: index
+ out of bounds}{Row indices start at 1}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Can't remove row: database `#1' doesn't
+ exist}{}%
+ }%
}
-\def\@dtl@assigncmdnoop#1\@@#2{}
-\newcommand*{\@dtl@setnull}[2]{%
-\@ifundefined{@dtl@idtype@\@dtl@dbname @#2}{%
-\global\let#1=\DTLstringnull}{%
-\edef\@dtl@tmp{0\@dtl@getidtype{\@dtl@dbname}{#2}}%
-\expandafter\ifnum\@dtl@tmp=0\relax
- \global\let#1=\DTLstringnull
-\else
- \global\let#1=\DTLnumbernull
-\fi
-}}
-\newcommand*{\DTLstringnull}{NULL}
-\newcommand*{\DTLnumbernull}{0}
-\newcommand*{\DTLifnull}[3]{%
-\ifx\DTLstringnull#1\relax
- #2%
-\else
- \ifx\DTLnumbernull#1\relax
- #2%
- \else
- #3%
- \fi
-\fi}
-\newcommand{\dtl@gathervalues}[3][key]{%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname dtlkeys@#2\endcsname%
-\def\@dtl@list{}%
-\@for\dtl@key:=\@dtl@tmp\do{%
- \expandafter\@dtl@setnull\expandafter{%
- \csname @dtl@#1@\dtl@key\endcsname}{\dtl@key}%
- \@for\dtl@thiselement:=#3\do{%
- \dtl@getentryid\dtl@thiselement\@dtl@id
- \ifthenelse{\equal{\@dtl@id}{\dtl@key}}{%
- \dtl@getentryvalue\dtl@thiselement\@dtl@value%
- \expandafter\toks@\expandafter{\@dtl@value}%
- \expandafter\edef\csname @dtl@#1@\dtl@key\endcsname{%
- \the\toks@}%
- \@endfortrue}{}%
- }%
-\@endforfalse
-}%
+\newcommand*{\@DTLremoverow}[2]{%
+ \edef\dtl@dogetrow{\noexpand\dtlgetrow{#1}{\number#2}}%
+ \dtl@dogetrow
+ \expandafter\dtl@decrementrows\expandafter
+ {\dtlbeforerow}{#2}%
+ \expandafter\dtl@decrementrows\expandafter
+ {\dtlafterrow}{#2}%
+ \edef\dtl@tmp{\the\dtlbeforerow \the\dtlafterrow}%
+ \expandafter\global\csname dtldb@#1\endcsname
+ =\expandafter{\dtl@tmp}%
+ \expandafter\global\expandafter\advance
+ \csname dtlrows@#1\endcsname by -1\relax
+}
+\newcommand*{\DTLsumforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlsumforkeys
+}
+\newcommand*{\@dtlsumforkeys}[4][]{%
+ \def#4{0}%
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {\DTLadd{#4}{#4}{\DTLthisval}}{}%
+ }%
+ }%
+ }%
}
-\newcommand*{\DTLsumforkeys}[4][\boolean{true}\and
-\DTLisnumerical{\DTLthisval}]{%
-\def#4{0}%
-\@for\@dtl@dbname:=#2\do{%
- \DTLifdbexists{\@dtl@dbname}{%
- \expandafter
- \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
- \@for\@dtl@key:=#3\do{%
- \protected@edef\DTLthisval{%
- \csname @dtl@key@\@dtl@key\endcsname}%
- \ifthenelse{#1}{\DTLadd{#4}{#4}{\DTLthisval}}{}%
- }}%
- }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+\newcommand*{\DTLsumcolumn}[3]{%
+ \def#3{0}%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLadd{#3}{#3}{\DTLthisval}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
}%
-}%
}
-\newcommand*{\DTLmeanforkeys}[4][\boolean{true}\and
-\DTLisnumerical{\DTLthisval}]{%
-\def#4{0}%
-\def\dtl@n{0}%
-\@for\@dtl@dbname:=#2\do{%
-\DTLifdbexists{\@dtl@dbname}{%
- \expandafter
- \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
- \@for\@dtl@key:=#3\do{%
- \protected@edef\DTLthisval{%
- \csname @dtl@key@\@dtl@key\endcsname}%
- \ifthenelse{#1}{%
- \DTLadd{#4}{#4}{\DTLthisval}%
- \DTLadd{\dtl@n}{\dtl@n}{1}%
- }{}%
- }}%
-}{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}}}%
-\ifnum\dtl@n=0\relax
- \PackageError{datatool}{Can't compute mean, no data!}{}%
-\else
- \DTLdiv{#4}{#4}{\dtl@n}%
-\fi
-}
-\newcommand*{\DTLvarianceforkeys}[4][\boolean{true}\and
-\DTLisnumerical{\DTLthisval}]{%
-\DTLmeanforkeys[#1]{#2}{#3}{\dtl@mean}%
-\def#4{0}%
-\@for\@dtl@dbname:=#2\do{%
- \DTLifdbexists{\@dtl@dbname}{%
- \expandafter
- \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
- \@for\@dtl@key:=#3\do{%
- \protected@edef\DTLthisval{%
- \csname @dtl@key@\@dtl@key\endcsname}%
- \ifthenelse{#1}{%
- \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
- \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
- \DTLadd{#4}{#4}{\dtl@diff}%
- }{}%
- }}%
- }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+\newcommand*{\DTLmeanforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlmeanforkeys
+}
+\newcount\@dtl@elements
+\newcommand*{\@dtlmeanforkeys}[4][]{%
+ \def#4{0}%
+ \@dtl@elements=0\relax
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \DTLadd{#4}{#4}{\DTLthisval}%
+ \advance\@dtl@elements by 1\relax
+ }{}%
+ }%
+ }%
}%
-}%
-\ifnum\dtl@n=0\relax
- \PackageError{datatool}{Can't compute variance, no data!}{}%
-\else
- \DTLdiv{#4}{#4}{\dtl@n}%
-\fi
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Unable to evaluate mean: no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#4}{#4}{\@dtl@n}%
+ \fi
}
-\newcommand*{\DTLsdforkeys}[4][\boolean{true}\and
-\DTLisnumerical{\DTLthisval}]{%
-\DTLvarianceforkeys[#1]{#2}{#3}{#4}%
-\DTLsqrt{#4}{#4}%
+\newcommand*{\DTLmeanforcolumn}[3]{%
+ \def#3{0}%
+ \@dtl@elements=0\relax
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLadd{#3}{#3}{\DTLthisval}%
+ \advance\@dtl@elements by 1\relax
+ }%
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Can't compute mean for
+ column `#2' in database `#1': no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#3}{#3}{\@dtl@n}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
}
-\newcommand*{\DTLminforkeys}[4][\boolean{true}\and
-\DTLisnumerical{\DTLthisval}]{%
-\def#4{}%
-\@for\@dtl@dbname:=#2\do{%
-\DTLifdbexists{\@dtl@dbname}{%
- \expandafter
- \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
- \@for\@dtl@key:=#3\do{%
- \protected@edef\DTLthisval{%
- \csname @dtl@key@\@dtl@key\endcsname}%
- \ifthenelse{#1}{%
- \ifx#4\@empty
- \let#4=\DTLthisval
- \else
- \DTLmin{#4}{#4}{\DTLthisval}%
- \fi
- }{}%
-}}%
- }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+\newcommand*{\DTLvarianceforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlvarianceforkeys
+}
+\newcommand*{\@dtlvarianceforkeys}[4][]{%
+ \@dtlmeanforkeys[#1]{#2}{#3}{\dtl@mean}%
+ \def#4{0}%
+ \@dtl@elements=0\relax
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#4}{#4}{\dtl@diff}%
+ \advance\@dtl@elements by 1\relax
+ }{}%
+ }%
+ }%
}%
-}}
-\newcommand*{\DTLmaxforkeys}[4][\boolean{true}\and
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Unable to evaluate variance: no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#4}{#4}{\@dtl@n}%
+ \fi
+}
+\newcommand*{\DTLvarianceforcolumn}[3]{%
+ \DTLmeanforcolumn{#1}{#2}{\dtl@mean}%
+ \def#3{0}%
+ \@dtl@elements=0\relax
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \DTLsub{\dtl@diff}{\DTLthisval}{\dtl@mean}%
+ \DTLmul{\dtl@diff}{\dtl@diff}{\dtl@diff}%
+ \DTLadd{#3}{#3}{\dtl@diff}%
+ \advance\@dtl@elements by 1\relax
+ }%
+ \ifnum\@dtl@elements=0\relax
+ \PackageError{datatool}{Can't compute variance for
+ column `#2' in database `#1': no data}{}%
+ \else
+ \edef\@dtl@n{\number\@dtl@elements}%
+ \DTLdiv{#3}{#3}{\@dtl@n}%
+ \fi
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+\newcommand*{\DTLsdforkeys}[1][\boolean{true}\and
\DTLisnumerical{\DTLthisval}]{%
-\def#4{}%
-\@for\@dtl@dbname:=#2\do{%
-\DTLifdbexists{\@dtl@dbname}{%
- \expandafter
- \let\expandafter\@dtl@db\csname dtldb@\@dtl@dbname\endcsname%
- \@for\@dtl@currentrow:=\@dtl@db\do{%
- \dtl@gathervalues{\@dtl@dbname}{\@dtl@currentrow}%
- \@for\@dtl@key:=#3\do{%
- \protected@edef\DTLthisval{%
- \csname @dtl@key@\@dtl@key\endcsname}%
- \ifthenelse{#1}{%
- \ifx#4\@empty
- \let#4=\DTLthisval
- \else
- \DTLmax{#4}{#4}{\DTLthisval}%
- \fi
- }{}%
-}}%
- }{\PackageError{datatool}{Database `\@dtl@dbname' doesn't exist}{}%
+ \def\@dtl@cond{#1}%
+ \@dtlsdforkeys
+}
+\newcommand*{\@dtlsdforkeys}[4][]{%
+ \@dtlvarianceforkeys[#1]{#2}{#3}{#4}%
+ \DTLsqrt{#4}{#4}%
+}
+\newcommand*{\DTLsdforcolumn}[3]{%
+ \DTLvarianceforcolumn{#1}{#2}{#3}%
+ \DTLsqrt{#3}{#3}%
+}
+\newcommand*{\DTLminforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlminforkeys
+}
+\newcommand*{\@dtlminforkeys}[4][]{%
+ \def#4{}%
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \ifx#4\@empty
+ \let#4\DTLthisval
+ \else
+ \DTLmin{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+ }%
+ }%
}%
-}}
+}
+\newcommand*{\DTLminforcolumn}[3]{%
+ \def#3{}%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \ifx#3\@empty
+ \let#3\DTLthisval
+ \else
+ \DTLmin{#3}{#3}{\DTLthisval}%
+ \fi
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
+\newcommand*{\DTLmaxforkeys}[1][\boolean{true}\and
+ \DTLisnumerical{\DTLthisval}]{%
+ \def\@dtl@cond{#1}%
+ \@dtlmaxforkeys
+}
+\newcommand*{\@dtlmaxforkeys}[4][]{%
+ \def#4{}%
+ \@for\@dtl@dbname:=#2\do{%
+ \@sDTLforeach{\@dtl@dbname}%
+ {#1}% assignment list
+ {%
+ \@for\@dtl@key:=#3\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlcurrentrow=\expandafter{\dtl@thisrow}%
+ \dtlgetentryfromrow{\DTLthisval}{\@dtl@col}{\dtlcurrentrow}%
+ \expandafter\ifthenelse\expandafter{\@dtl@cond}%
+ {%
+ \ifx#4\@empty
+ \let#4\DTLthisval
+ \else
+ \DTLmax{#4}{#4}{\DTLthisval}%
+ \fi
+ }{}%
+ }%
+ }%
+ }%
+}
+\newcommand*{\DTLmaxforcolumn}[3]{%
+ \def#3{}%
+ \DTLifdbexists{#1}%
+ {%
+ \@sDTLifhaskey{#1}{#2}%
+ {%
+ \@sdtlforcolumn{\DTLthisval}{#1}{#2}%
+ {%
+ \ifx#3\@empty
+ \let#3\DTLthisval
+ \else
+ \DTLmax{#3}{#3}{\DTLthisval}%
+ \fi
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Key `#2' doesn't
+ exist in database `#1'}{}%
+ }%
+ }%
+ {%
+ \PackageError{datatool}{Data base `#1' doesn't
+ exist}{}%
+ }%
+}
\newcommand*{\DTLcomputebounds}[8][\boolean{true}]{%
\let#5=\relax
\let#6=\relax
@@ -2045,228 +3311,266 @@ deeply}{}%
}%
}
\newcommand*{\DTLgetvalueforkey}[5]{%
-{%
-\global\let#1=\DTLstringnull
-\@sDTLforeach{#3}{\dtl@valueA=#2,\dtl@refvalue=#4}{%
-\DTLifnull{\dtl@refvalue}{}{%
-\ifthenelse{\equal{\dtl@refvalue}{#5}}{%
-\global\let#1=\dtl@valueA
-\@endfortrue
-}{}}}%
-}}
+ \DTLgetrowforkey{\@dtl@row}{#3}{#4}{#5}%
+ \@sdtl@getcolumnindex{\@dtl@col}{#3}{#2}%
+ {%
+ \dtlcurrentrow=\expandafter{\@dtl@row}%
+ \edef\@dtl@dogetval{\noexpand\dtlgetentryfromcurrentrow
+ {\noexpand\@dtl@val}{\@dtl@col}}%
+ \@dtl@dogetval
+ \global\let#1=\@dtl@val
+ }%
+}
\newcommand*{\DTLgetrowforkey}[4]{%
-{%
-\global\let#1=\@empty
-\@sDTLforeach{#2}{\dtl@refvalue=#3}{%
-\DTLifnull{\dtl@refvalue}{}{%
-\ifthenelse{\equal{\dtl@refvalue}{#4}}{%
-\expandafter\global\expandafter\let\expandafter#1
- \csname @dtl@thiscurrentrow@\romannumeral\dtlforeachlevel\endcsname
-\@endfortrue
-}{}}}%
-}}
+ \global\let#1=\@empty
+ \@sDTLforeach{#2}{\dtl@refvalue=#3}{%
+ \DTLifnull{\dtl@refvalue}%
+ {}%
+ {%
+ \ifthenelse{\equal{\dtl@refvalue}{#4}}%
+ {%
+ \xdef#1{\the\dtlcurrentrow}%
+ \dtlbreak
+ }%
+ {}%
+ }%
+ }%
+}
+\newcommand*{\dtlsplitrow}[4]{%
+ \def\@dtlsplitrow##1%before stuff
+ \db@col@id@w #2\db@col@id@end@% column id
+ ##2% unwanted stuff
+ \db@col@id@w #2\db@col@id@end@% column id
+ ##3% after stuff
+ \q@nil{\def#3{##1}\def#4{##3}}%
+ \@dtlsplitrow#1\q@nil
+}
+\newtoks\@dtl@list
\newcommand*{\DTLsort}{\@ifstar\@sDTLsort\@DTLsort}
-\newcommand*{\@DTLsort}[3][]{%
-\edef\@dtl@replacementkeys{#1}%
-\edef\@dtl@sortorder{#2}%
-\edef\@dtl@dbname{#3}%
-\let\@dtl@comparecs=\dtlcompare
-\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname
-\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
-\expandafter\global\expandafter
- \let\csname dtldb@#3\endcsname=\@dtl@list}
-\newcommand*{\@sDTLsort}[3][]{%
-\edef\@dtl@replacementkeys{#1}%
-\edef\@dtl@sortorder{#2}%
-\edef\@dtl@dbname{#3}%
-\let\@dtl@comparecs=\dtlicompare
-\expandafter\let\expandafter\@dtl@list\csname dtldb@#3\endcsname
-\dtl@sortlist{\@dtl@list}{\@dtl@sortcriteria}%
-\expandafter\global\expandafter
- \let\csname dtldb@#3\endcsname=\@dtl@list}
+\newcommand{\@DTLsort}[3][]{%
+ \DTLifdbexists{#3}%
+ {%
+ \edef\@dtl@replacementkeys{#1}%
+ \edef\@dtl@sortorder{#2}%
+ \let\@dtl@comparecs=\dtlcompare
+ \dtl@sortdata{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#3' doesn't exist}{}%
+ }%
+}
+\newcommand{\@sDTLsort}[3][]{%
+ \DTLifdbexists{#3}%
+ {%
+ \edef\@dtl@replacementkeys{#1}%
+ \edef\@dtl@sortorder{#2}%
+ \let\@dtl@comparecs=\dtlicompare
+ \dtl@sortdata{#3}%
+ }%
+ {%
+ \PackageError{datatool}{Database `#3' doesn't exist}{}%
+ }%
+}
+\newtoks\@dtl@rowa
+\newtoks\@dtl@rowb
+\newcommand*{\dtl@sortdata}[1]{%
+ \def\@dtl@sortedlist{}%
+ \edef\@dtl@dbname{#1}%
+ \@dtlforeachrow(\@dtl@rowAnum,\@dtl@rowAcontents)\in{#1}\do{%
+ \@dtl@rowa=\expandafter{\@dtl@rowAcontents}%
+ \def\@dtl@newlist{}%
+ \@dtl@insertdonefalse
+ \dtlrownum=0\relax
+ \expandafter\@dtl@foreachrow\@dtl@sortedlist
+ \db@row@elt@w%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@id@w \@nil\db@row@id@end@%
+ \db@row@elt@end@%
+ \@@{\@dtl@rowBnum}{\@dtl@rowBcontents}{%
+ \@dtl@rowb=\expandafter{\@dtl@rowBcontents}%
+ \dtlrownum=\@dtl@rowBnum
+ \if@dtl@insertdone
+ \advance\dtlrownum by 1\relax
+ \else
+ \@dtl@sortcriteria{\@dtl@rowa}{\@dtl@rowb}%
+ \ifnum\dtl@sortresult<0\relax
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{%
+ \the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowa
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ \advance\dtlrownum by 1\relax
+ \@dtl@insertdonetrue
+ \fi
+ \fi
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowb
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ }\q@nil
+ \if@dtl@insertdone
+ \else
+ \advance\dtlrownum by 1\relax
+ \toks@=\expandafter{\@dtl@newlist}%
+ \edef\@dtl@newlist{\the\toks@
+ \noexpand\db@row@elt@w%
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \the\@dtl@rowa
+ \noexpand\db@row@id@w \number\dtlrownum
+ \noexpand\db@row@id@end@%
+ \noexpand\db@row@elt@end@%
+ }%
+ \fi
+ \let\@dtl@sortedlist=\@dtl@newlist
+ }%
+ \expandafter\global\csname dtldb@#1\endcsname=\expandafter
+ {\@dtl@sortedlist}%
+}
\newcommand{\@dtl@sortcriteria}[2]{%
-\@for\@dtl@level:=\@dtl@sortorder\do{%
- \expandafter\@dtl@getsortdirection\@dtl@level=\relax%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@key}{%
- \ifx\@dtl@replacementkeys\@empty
- \PackageError{datatool}{Unknown key `\@dtl@key' for database
- `\@dtl@dbname'}{}%
- \else
- \dtl@gathervalues[keya]{\@dtl@dbname}{#1}%
- \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}%
- \@ifundefined{@dtl@keya@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@key\endcsname}%
- \@ifundefined{@dtl@keyb@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@key\endcsname}%
- \let\@dtl@keya=\@dtl@key
- \let\@dtl@keyb=\@dtl@key
- \DTLifnull{\@dtl@tmpa}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keya@\@dtl@keya}{}{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@keya\endcsname
- \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keya=\@dtl@key \fi
- \@endforfalse
- }{}%
- \DTLifnull{\@dtl@tmpb}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@keyb\endcsname
- \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi
- \@endforfalse
- }{}%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keya}{%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{%
- \dtl@sortresult=0\relax}{\dtl@sortresult=-1\relax}%
- }{%
- \@ifundefined{@dtl@idtype@\@dtl@dbname @\@dtl@keyb}{%
- \dtl@sortresult=1\relax}{%
- \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}%
- }%
- }%
- \fi
- }{%
- \ifx\@dtl@replacementkeys\@empty
- \dtl@compare{\@dtl@key}{#1}{#2}%
- \else
- \dtl@gathervalues[keya]{\@dtl@dbname}{#1}%
- \dtl@gathervalues[keyb]{\@dtl@dbname}{#2}%
- \@ifundefined{@dtl@keya@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpa}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@key\endcsname}%
- \@ifundefined{@dtl@keyb@\@dtl@key}{%
- \@dtl@setnull{\@dtl@tmpb}{\@dtl@key}%
- }{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@key\endcsname}%
- \let\@dtl@keya=\@dtl@key
- \let\@dtl@keyb=\@dtl@key
- \DTLifnull{\@dtl@tmpa}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keya@\@dtl@keya}{}{%
- \expandafter\let\expandafter\@dtl@tmpa\expandafter
- =\csname @dtl@keya@\@dtl@keya\endcsname
- \DTLifnull{\@dtl@tmpa}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keya=\@dtl@key \fi
- \@endforfalse
- }{}%
- \DTLifnull{\@dtl@tmpb}{%
- % find first non null key in list of replacement keys
- \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
- \@ifundefined{@dtl@keyb@\@dtl@keyb}{}{%
- \expandafter\let\expandafter\@dtl@tmpb\expandafter
- =\csname @dtl@keyb@\@dtl@keyb\endcsname
- \DTLifnull{\@dtl@tmpb}{}{\@endfortrue}}%
- }%
- \if@endfor \else\let\@dtl@keyb=\@dtl@key \fi
- \@endforfalse
- }{}%
- \dtl@compare@{\@dtl@keya}{\@dtl@keyb}{#1}{#2}%
- \fi
- \multiply\dtl@sortresult by \@dtl@sortdirection\relax
- \ifnum\dtl@sortresult=0\relax
- \else
- \@endfortrue
- \fi
- }%
-}%
+ \@for\@dtl@level:=\@dtl@sortorder\do{%
+ \expandafter\@dtl@getsortdirection\@dtl@level=\relax
+ \let\@dtl@keya=\@dtl@key
+ \let\@dtl@keyb=\@dtl@key
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@key}%
+ \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}%
+ \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}%
+ \ifx\@dtl@a\dtlnovalue
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+ \ifx\@dtl@b\dtlnovalue
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+ \DTLifnull{\@dtl@a}%
+ {%
+ \@for\@dtl@keya:=\@dtl@replacementkeys\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keya}%
+ \dtlgetentryfromrow{\@dtl@a}{\@dtl@col}{#1}%
+ \ifx\@dtl@a\dtlnovalue
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+ \DTLifnull{\@dtl@a}{}{\@endfortrue}%
+ }%
+ \ifx\@dtl@keya\@nnil
+ \let\@dtl@keya\@dtl@key
+ \@dtl@setnull{\@dtl@a}{\@dtl@key}%
+ \fi
+ }%
+ {}%
+ \DTLifnull{\@dtl@b}%
+ {%
+ \@for\@dtl@keyb:=\@dtl@replacementkeys\do{%
+ \@sdtl@getcolumnindex{\@dtl@col}{\@dtl@dbname}{\@dtl@keyb}%
+ \dtlgetentryfromrow{\@dtl@b}{\@dtl@col}{#2}%
+ \ifx\@dtl@b\dtlnovalue
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+ \DTLifnull{\@dtl@b}{}{\@endfortrue}%
+ }%
+ \ifx\@dtl@keyb\@nnil
+ \let\@dtl@keyb\@dtl@key
+ \@dtl@setnull{\@dtl@b}{\@dtl@key}%
+ \fi
+ }%
+ {}%
+ \@dtl@toksA=\expandafter{\@dtl@a}%
+ \@dtl@toksB=\expandafter{\@dtl@b}%
+ \edef\@dtl@docompare{\noexpand\dtl@compare@
+ {\@dtl@keya}{\@dtl@keyb}%
+ {\noexpand\@dtl@toksA}{\noexpand\@dtl@toksB}}%
+ \@dtl@docompare
+ \ifnum\dtl@sortresult=0\relax
+ \@endforfalse
+ \else
+ \@endfortrue
+ \fi
+ }%
}
\def\@dtl@getsortdirection#1=#2\relax{%
-\def\@dtl@key{#1}%
-\def\@dtl@sortdirection{#2}%
-\ifx\@dtl@sortdirection\@empty
- \def\@dtl@sortdirection{-1}%
-\else
- \@dtl@get@sortdirection#2%
- \ifthenelse{\equal{\@dtl@sortdirection}{ascending}}{%
- \def\@dtl@sortdirection{-1}}{%
- \ifthenelse{\equal{\@dtl@sortdirection}{descending}}{%
- \def\@dtl@sortdirection{1}}{%
- \PackageError{datatool}{Invalid sort direction
- `\@dtl@sortdirection'}{%
- The sort direction can only be one of `ascending' or
- `descending'}\def\@dtl@sortdirection{-1}}}%
-\fi
+ \def\@dtl@key{#1}%
+ \def\@dtl@sortdirection{#2}%
+ \ifx\@dtl@sortdirection\@empty
+ \def\@dtl@sortdirection{-1}%
+ \else
+ \@dtl@get@sortdirection#2%
+ \def\@dtl@dir{ascending}%
+ \ifx\@dtl@sortdirection\@dtl@dir
+ \def\@dtl@sortdirection{-1}%
+ \else
+ \def\@dtl@dir{descending}%
+ \ifx\@dtl@sortdirection\@dtl@dir
+ \def\@dtl@sortdirection{1}%
+ \else
+ \PackageError{datatool}{Invalid sort direction
+ `\@dtl@sortdirection'}{The sort direction can only be
+ one of `ascending' or `descending'}%
+ \def\@dtl@sortdirection{-1}
+ \fi
+ \fi
+ \fi
}
\def\@dtl@get@sortdirection#1={\def\@dtl@sortdirection{#1}}
-\newtoks\@dtl@toksA\newtoks\@dtl@toksB
+\newtoks\@dtl@toksA
+\newtoks\@dtl@toksB
+\newtoks\@dtl@toks
\newcommand{\dtl@compare}[3]{%
-\dtl@gathervalues{\@dtl@dbname}{#2}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}%
-\edef\@dtl@a{\the\@dtl@toksA}%
-\dtl@gathervalues{\@dtl@dbname}{#3}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}%
-\edef\@dtl@b{\the\@dtl@toksB}%
-\expandafter\@dtl@datatype\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
-\ifnum\@dtl@datatype=0\relax
- \edef\@dtl@tmpcmp{%
- \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
- {\the\@dtl@toksA}{\the\@dtl@toksB}}%
- \@dtl@tmpcmp
-\else
- \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
- \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
- \dtl@sortresult=0\relax}}%
-\fi
-\ifdtlverbose
-\@onelevel@sanitize\@dtl@a
-\@onelevel@sanitize\@dtl@b
-\fi
-\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \dtl@compare@{#1}{#1}{#2}{#3}%
}
\newcommand{\dtl@compare@}[4]{%
-\dtl@gathervalues{\@dtl@dbname}{#3}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#1\endcsname
-\expandafter\@dtl@toksA\expandafter{\@dtl@tmp}%
-\edef\@dtl@a{\the\@dtl@toksA}%
-\dtl@gathervalues{\@dtl@dbname}{#4}%
-\expandafter\let\expandafter\@dtl@tmp\expandafter
- =\csname @dtl@key@#2\endcsname
-\expandafter\@dtl@toksB\expandafter{\@dtl@tmp}%
-\edef\@dtl@b{\the\@dtl@toksB}%
-\expandafter\@dtl@tmpcount\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#1\endcsname\relax
-\expandafter\@dtl@datatype\expandafter=
- \csname @dtl@idtype@\@dtl@dbname @#2\endcsname\relax
-\multiply\@dtl@datatype by \@dtl@tmpcount\relax
-\ifnum\@dtl@datatype=0\relax
- \edef\@dtl@tmpcmp{%
- \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
- {\the\@dtl@toksA}{\the\@dtl@toksB}}%
- \@dtl@tmpcmp
-\else
- \DTLifnumlt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=-1\relax}{%
- \DTLifnumgt{\@dtl@a}{\@dtl@b}{\dtl@sortresult=1\relax}{%
- \dtl@sortresult=0\relax}}%
-\fi
-\ifdtlverbose
-\@onelevel@sanitize\@dtl@a
-\@onelevel@sanitize\@dtl@b
-\fi
-\dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \DTLgetdatatype{\@dtl@typeA}{\@dtl@dbname}{#1}%
+ \ifx\@dtl@typeA\DTLunsettype
+ \let\@dtl@typeA\DTLstringtype
+ \fi
+ \DTLgetdatatype{\@dtl@typeB}{\@dtl@dbname}{#2}%
+ \ifx\@dtl@typeB\DTLunsettype
+ \let\@dtl@typeB\DTLstringtype
+ \fi
+ \@dtl@tmpcount=\@dtl@typeA\relax
+ \multiply\@dtl@tmpcount by \@dtl@typeB\relax
+ \ifnum\@dtl@tmpcount=0\relax
+ \edef\@dtl@tmpcmp{%
+ \noexpand\@dtl@comparecs{\noexpand\dtl@sortresult}%
+ {\the#3}{\the#4}%
+ }%
+ \@dtl@tmpcmp
+ \ifdtlverbose
+ \edef\@dtl@a{\the#3}%
+ \edef\@dtl@b{\the#4}%
+ \fi
+ \else
+ \edef\@dtl@a{\the#3}%
+ \edef\@dtl@b{\the#4}%
+ \DTLifnumlt{\@dtl@a}{\@dtl@b}%
+ {%
+ \dtl@sortresult=-1\relax
+ }%
+ {%
+ \DTLifnumgt{\@dtl@a}{\@dtl@b}%
+ {%
+ \dtl@sortresult=1\relax
+ }%
+ {%
+ \dtl@sortresult=0\relax
+ }%
+ }%
+ \fi
+ \ifdtlverbose
+ \@onelevel@sanitize\@dtl@a
+ \@onelevel@sanitize\@dtl@b
+ \dtl@message{`\@dtl@a' <=> `\@dtl@b' = \number\dtl@sortresult}%
+ \fi
}
\newcommand*{\dtl@choplast}[3]{%
\let#2\@empty
@@ -2306,7 +3610,6 @@ deeply}{}%
\@endforfalse}%
\let#1=\@dtl@sortedlist
}
-\newtoks\@dtl@toks
\newcommand{\dtl@insertinto}[3]{%
\def\@dtl@newsortedlist{}%
\@dtl@insertdonefalse
@@ -2351,6 +3654,22 @@ deeply}{}%
}
\newif\if@dtl@insertdone
\newcount\dtl@sortresult
+\newcommand{\toks@gput@right@cx}[2]{%
+ \def\@toks@name{#1}%
+ \edef\@dtl@stuff{#2}%
+ \global\csname\@toks@name\endcsname\expandafter
+ \expandafter\expandafter{\expandafter\the
+ \csname\expandafter\@toks@name\expandafter\endcsname\@dtl@stuff}%
+}
+\newcommand{\toks@gconcat@middle@cx}[4]{%
+ \def\@toks@name{#1}%
+ \edef\@dtl@stuff{#3}%
+ \global\csname\@toks@name\endcsname\expandafter\expandafter
+ \expandafter\expandafter\expandafter
+ \expandafter\expandafter{\expandafter\expandafter\expandafter
+ \the\expandafter\expandafter\expandafter#2%
+ \expandafter\@dtl@stuff\the#4}%
+}
\newcommand*{\DTLadd}[3]{%
\DTLconverttodecimal{#2}{\@dtl@numi}%
\DTLconverttodecimal{#3}{\@dtl@numii}%
@@ -2909,155 +4228,270 @@ deeply}{}%
}}}
\newwrite\@dtl@write
\newcommand*{\DTLsavedb}[2]{%
-\DTLifdbexists{#1}{%
-\openout\@dtl@write=#2%
-\edef\@dtl@keys{\csname dtlkeys@#1\endcsname}%
-\def\@dtl@header{}%
-\@for\@dtl@key:=\@dtl@keys\do{%
-\expandafter\@dtl@toks\expandafter{\@dtl@header}%
-\ifx\@dtl@header\@empty
- \IfSubStringInString{\@dtl@separator}{\@dtl@key}{%
- \protected@edef\@dtl@header{%
- \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
- }{%
- \protected@edef\@dtl@header{\@dtl@key}%
- }%
-\else
- \IfSubStringInString{\@dtl@separator}{\@dtl@key}{%
- \protected@edef\@dtl@header{\the\@dtl@toks\@dtl@separator
- \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
- }{%
- \protected@edef\@dtl@header{\the\@dtl@toks\@dtl@separator
- \@dtl@key}%
- }%
-\fi
-}%
-\protected@write\@dtl@write{}{\@dtl@header}%
-\expandafter\let\expandafter\@dtl@db\csname dtldb@#1\endcsname%
-\@for\@dtl@currentrow:=\@dtl@db\do{%
-\dtl@gathervalues{#1}{\@dtl@currentrow}%
-\def\@dtl@outputrow{}%
-\@for\@dtl@key:=\@dtl@keys\do{%
-\protected@edef\@dtl@element{\csname @dtl@key@\@dtl@key\endcsname}%
-\expandafter\@dtl@toks\expandafter{\@dtl@outputrow}%
-\ifx\@dtl@outputrow\@empty
- \IfSubStringInString{\@dtl@separator}{\@dtl@element}{%
- \protected@edef\@dtl@outputrow{%
- \@dtl@delimiter\@dtl@element\@dtl@delimiter}%
- }{%
- \protected@edef\@dtl@outputrow{\@dtl@element}%
- }%
-\else
- \IfSubStringInString{\@dtl@separator}{\@dtl@element}{%
- \protected@edef\@dtl@outputrow{\the\@dtl@toks\@dtl@separator
- \@dtl@delimiter\@dtl@element\@dtl@delimiter}%
- }{%
- \protected@edef\@dtl@outputrow{\the\@dtl@toks\@dtl@separator
- \@dtl@element}%
- }%
-\fi
-}%
-\protected@write\@dtl@write{}{\@dtl@outputrow}%
-}%
-\closeout\@dtl@write
-}{%
-\PackageError{datatool}{Database `#1' doesn't exist}{}%
-}}
+ \DTLifdbexists{#1}%
+ {%
+ \openout\@dtl@write
+ \def\@dtl@header{}%
+ \dtlforeachkey(\@dtl@key,\@dtl@col,\@dtl@type,\@dtl@head)%
+ \in{#1}\do
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@key}%
+ {%
+ \ifx\@dtl@header\@empty
+ \protected@edef\@dtl@header{%
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ \else
+ \toks@=\expandafter{\@dtl@header}%
+ \protected@edef\@dtl@header{%
+ \the\toks@\@dtl@separator
+ \@dtl@delimiter\@dtl@key\@dtl@delimiter}%
+ \fi
+ }%
+ {%
+ \ifx\@dtl@header\@empty
+ \protected@edef\@dtl@header{\@dtl@key}%
+ \else
+ \toks@=\expandafter{\@dtl@header}%
+ \protected@edef\@dtl@header{\the\toks@
+ \@dtl@separator\@dtl@key}%
+ \fi
+ }%
+ }%
+ \protected@write\@dtl@write{}{\@dtl@header}%
+ \@sDTLforeach{#1}{}%
+ {%
+ \def\@dtl@row{}%
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \IfSubStringInString{\@dtl@separator}{\@dtl@val}%
+ {%
+ \ifx\@dtl@row\@empty
+ \protected@edef\@dtl@row{%
+ \@dtl@delimiter\@dtl@val\@dtl@delimiter}%
+ \else
+ \toks@=\expandafter{\@dtl@row}%
+ \protected@edef\@dtl@row{\the\toks@\@dtl@separator
+ \@dtl@delimiter\@dtl@val\@dtl@delimiter}%
+ \fi
+ }%
+ {%
+ \ifx\@dtl@row\@empty
+ \protected@edef\@dtl@row{\@dtl@val}%
+ \else
+ \toks@=\expandafter{\@dtl@row}%
+ \protected@edef\@dtl@row{\the\toks@\@dtl@separator
+ \@dtl@val}%
+ \fi
+ }%
+ \protected@write\@dtl@write{}{\@dtl@row}%
+ }%
+ }%
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
\newcommand*{\DTLsavetexdb}[2]{%
-\DTLifdbexists{#1}{%
-\def\@dtl@dbname{#1}%
-\openout\@dtl@write=#2%
-\edef\@dtl@keys{\csname dtlkeys@#1\endcsname}%
-\protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
-\expandafter\let\expandafter\@dtl@db\csname dtldb@#1\endcsname%
-\@for\@dtl@currentrow:=\@dtl@db\do{%
-\dtl@gathervalues{#1}{\@dtl@currentrow}%
-\protected@write\@dtl@write{}{\string\DTLnewrow{#1}}%
-\@for\@dtl@key:=\@dtl@keys\do{%
-\expandafter\DTLifnull\csname @dtl@key@\@dtl@key\endcsname
-{}{%
-\protected@edef\@dtl@element{\csname @dtl@key@\@dtl@key\endcsname}%
-\protected@write\@dtl@write{}{\string\DTLnewdbentry
- {#1}{\@dtl@key}{\@dtl@element}}%
-}%
-}%
-}%
-\closeout\@dtl@write
-}{%
-\PackageError{datatool}{Database `#1' doesn't exist}{}%
-}}
+ \DTLifdbexists{#1}%
+ {%
+ \openout\@dtl@write=#2\relax
+ \protected@write\@dtl@write{}{\string\DTLnewdb{#1}}%
+ \@sDTLforeach{#1}{}%
+ {%
+ \protected@write\@dtl@write{}{\string\DTLnewrow*{#1}}%
+ \DTLforeachkeyinrow{\@dtl@val}%
+ {%
+ \DTLifnull{\@dtl@val}%
+ {\def\@dtl@val{}}%
+ {}%
+ \protected@write\@dtl@write{}{%
+ \string\DTLnewdbentry*{#1}{\dtlkey}{\@dtl@val}}%
+ }%
+ }%
+ \dtlforeachkey(\@dtl@k,\@dtl@c,\@dtl@t,\@dtl@h)\in{#1}\do
+ {%
+ \@onelevel@sanitize\@dtl@h
+ \protected@write\@dtl@write{}{%
+ \string\DTLsetheader*{#1}{\@dtl@k}{\@dtl@h}}%
+ }%
+ \closeout\@dtl@write
+ }%
+ {%
+ \PackageError{datatool}{Can't save database `#1': no such
+ database}{}%
+ }%
+}
+\newcommand{\@longempty}{}
\newread\@dtl@read
\newcount\dtl@entrycr
-\gdef\DTLloaddb#1#2{%
-\IfFileExists{#2}{%
-\begingroup
-\catcode`\"12\relax
-\openin\@dtl@read=#2%
-\dtl@message{Reading `#2'}%
-\DTLnewdb{#1}%
-\ifeof\@dtl@read
-\else
- \loop
- \@dtl@conditionfalse
+\define@boolkey{loaddb}[dtl]{noheader}[true]{}
+\define@key{loaddb}{keys}{%
+ \dtl@entrycr=0\relax
+ \@for\@dtl@key:=#1\do
+ {%
+ \advance\dtl@entrycr by 1\relax
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname{%
+ \@dtl@key}%
+ }%
+}
+\define@key{loaddb}{headers}{%
+ \dtl@entrycr=0\relax
+ \@for\@dtl@head:=#1\do
+ {%
+ \advance\dtl@entrycr by 1\relax
+ \toks@=\expandafter{\@dtl@head}%
+ \expandafter
+ \edef\csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname{%
+ \the\toks@}%
+ }%
+}
+\newcommand*{\dtldefaultkey}{Column}
+\newcommand*{\@dtl@readline}[2]{%
+ \read#1 to #2%
+ \dtl@trim#2%
+}
+\newcommand*{\@dtl@readrawline}[2]{%
+ \@dtl@rawread#1 to #2%
+ \dtl@trim#2%
+ \dtl@domappings\@dtl@line
+}
+
+\newcommand*{\DTLloaddb}{%
+ \let\@dtl@doreadline\@dtl@readline
+ \@dtlloaddb
+}
+\newcommand*{\@dtlloaddb}[3][]{%
+ \IfFileExists{#3}{%
+ \begingroup
+ \catcode`\"12\relax
+ \dtlnoheaderfalse
+ \setkeys{loaddb}{#1}%
+ \openin\@dtl@read=#3%
+ \dtl@message{Reading `#3'}%
+ \DTLnewdb{#2}%
\ifeof\@dtl@read
+ \PackageWarning{datatool}{File `#3' has no data}%
\else
- \read\@dtl@read to \@dtl@line
- \dtl@trim\@dtl@line
- \if\@dtl@line\par
- \@dtl@conditiontrue
+ \ifdtlnoheader
+ \else
+ \loop
+ \@dtl@conditionfalse
+ \ifeof\@dtl@read
+ \else
+ \@dtl@doreadline\@dtl@read\@dtl@line
+ \ifx\@dtl@line\@longempty
+ \@dtl@conditiontrue
+ \fi
+ \fi
+ \if@dtl@condition
+ \repeat
+ \protected@edef\@dtl@lin@{%
+ \@dtl@separator\@dtl@line\@dtl@separator}%
+ \dtl@entrycr=0\relax
+ \loop
+ \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
+ \advance\dtl@entrycr by 1\relax
+ \expandafter\@dtl@toks\expandafter{\@dtl@key}%
+ \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {%
+ \expandafter
+ \edef\csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname{\the\@dtl@toks}%
+ }%
+ {%
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {%
+ \expandafter
+ \edef\csname @dtl@inhd@\romannumeral
+ \dtl@entrycr\endcsname{\the\@dtl@toks}%
+ }%
+ {}%
+ }%
+ \ifx\@dtl@lin@\@dtl@separator
+ \@dtl@conditionfalse
+ \else
+ \@dtl@conditiontrue
+ \fi
+ \if@dtl@condition
+ \repeat
\fi
+ \ifeof\@dtl@read
+ \ifdtlnoheader
+ \PackageWarning{datatool}{No data in `#3'}%
+ \else
+ \PackageWarning{datatool}{Only header row found in `#3'}%
+ \fi
+ \else
+ \@dtl@conditiontrue
+ \loop
+ \@dtl@doreadline\@dtl@read\@dtl@line
+ \ifx\@dtl@line\@longempty
+ \else
+ \@sDTLnewrow{#2}%
+ \expandafter\@dtl@toks\expandafter{\@dtl@line}%
+ \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
+ \@dtl@separator}%
+ \dtl@entrycr=0\relax
+ {%
+ \@dtl@conditiontrue
+ \loop
+ \expandafter\@dtl@lopoff\@dtl@lin@\to
+ \@dtl@lin@\@dtl@thisentry
+ \advance\dtl@entrycr by 1\relax
+ \@ifundefined{@dtl@inky@\romannumeral\dtl@entrycr}%
+ {%
+ \edef\@dtl@thiskey{\dtldefaultkey
+ \number\dtl@entrycr}%
+ \expandafter\let
+ \csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname\@dtl@thiskey
+ }%
+ {%
+ \edef\@dtl@thiskey{%
+ \csname @dtl@inky@\romannumeral
+ \dtl@entrycr\endcsname}%
+ }%
+ \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
+ \edef\@do@dtlnewentry{\noexpand\@sDTLnewdbentry
+ {#2}{\@dtl@thiskey}{\the\@dtl@toks}}%
+ \@do@dtlnewentry
+ \ifx\@dtl@lin@\@dtl@separator
+ \@dtl@conditionfalse
+ \fi
+ \if@dtl@condition
+ \repeat
+ }%
+ \fi
+ \ifeof\@dtl@read \@dtl@conditionfalse\fi
+ \if@dtl@condition
+ \repeat
+ \fi
\fi
- \if@dtl@condition
- \repeat
- \ifeof\@dtl@read
- \else
- \protected@edef\@dtl@lin@{\@dtl@separator\@dtl@line\@dtl@separator}%
- \@dtl@tmpcount=0\relax
- \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
- \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
- \advance\@dtl@tmpcount by 1\relax
- \expandafter\@dtl@toks\expandafter{\@dtl@key}%
- \expandafter
- \edef\csname @dtl@inky@\romannumeral\@dtl@tmpcount\endcsname{%
- \the\@dtl@toks}%
- }%
- \ifeof\@dtl@read
- \else
- \@dtl@conditiontrue
- \loop
- \read\@dtl@read to \@dtl@line
- \dtl@trim\@dtl@line
- \ifthenelse{\equal{\@dtl@line}{}}{}%
- {%
- \DTLnewrow{#1}%
- \expandafter\@dtl@toks\expandafter{\@dtl@line}%
- \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
- \@dtl@separator}%
- \dtl@entrycr=0\relax
- \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
- \expandafter\@dtl@lopoff\@dtl@lin@\to
- \@dtl@lin@\@dtl@thisentry
- \advance\dtl@entrycr by 1\relax
- \edef\@dtl@thiskey{%
- \csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname}%
- \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
- \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry
- {#1}{\@dtl@thiskey}{\the\@dtl@toks}}%
- \@do@dtlnewentry
- }%
- }%
- \ifeof\@dtl@read \@dtl@conditionfalse\fi
- \if@dtl@condition
- \repeat
- \fi
- \fi
-\fi
-\closein\@dtl@read
-\endgroup
-}{%
-\PackageError{datatool}{Can't load database `#1' (file `#2'
-doesn't exist)}{}%
-}}
+ \closein\@dtl@read
+ \edef\@dtl@maxcols{\expandafter
+ \number\csname dtlcols@#2\endcsname}%
+ \dtlgforint\dtl@entrycr=1\to\@dtl@maxcols\step1\do
+ {%
+ \@ifundefined{@dtl@inhd@\romannumeral\dtl@entrycr}%
+ {}%
+ {%
+ \expandafter\let\expandafter\@dtl@head
+ \csname @dtl@inhd@\romannumeral\dtl@entrycr\endcsname
+ \@dtl@toks=\expandafter{\@dtl@head}%
+ \edef\@dtl@dosetheader{\noexpand\@dtl@setheaderforindex
+ {#2}{\number\dtl@entrycr}{\the\@dtl@toks}}%
+ \@dtl@dosetheader
+ }%
+ }%
+ \endgroup
+ }{%
+ \PackageError{datatool}{Can't load database `#2' (file `#3'
+ doesn't exist)}{}%
+ }%
+}
\newcommand{\dtl@trim}[1]{%
\def\@dtl@trmstr{}%
\expandafter\@dtl@starttrim#1\@nil%
@@ -3072,75 +4506,10 @@ doesn't exist)}{}%
\@dtl@dotrim%
}
\long\def\@dtl@trim#1 \@nil{\long\def\@dtl@trmstr{#1}}
-\gdef\DTLloadrawdb#1#2{%
-\IfFileExists{#2}{%
-\openin\@dtl@read=#2%
-\dtl@message{Reading `#2'}%
-\DTLnewdb{#1}%
-\ifeof\@dtl@read
-\else
- \loop
- \@dtl@conditionfalse
- \ifeof\@dtl@read
- \else
- \@dtl@rawread\@dtl@read to\@dtl@line
- \dtl@trim\@dtl@line
- \if\@dtl@line\par
- \@dtl@conditiontrue
- \fi
- \fi
- \if@dtl@condition
- \repeat
- \ifeof\@dtl@read
- \else
- \dtl@domappings\@dtl@line
- \protected@edef\@dtl@lin@{\@dtl@separator\@dtl@line\@dtl@separator}%
- \@dtl@tmpcount=0\relax
- \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
- \expandafter\@dtl@lopoff\@dtl@lin@\to\@dtl@lin@\@dtl@key
- \advance\@dtl@tmpcount by 1\relax
- \expandafter\@dtl@toks\expandafter{\@dtl@key}%
- \expandafter
- \edef\csname @dtl@inky@\romannumeral\@dtl@tmpcount\endcsname{%
- \the\@dtl@toks}%
- }%
- \ifeof\@dtl@read
- \else
- \@dtl@conditiontrue
- \loop
- \@dtl@rawread\@dtl@read to\@dtl@line
- \dtl@trim\@dtl@line
- \ifthenelse{\equal{\@dtl@line}{}}{}%
- {%
- \DTLnewrow{#1}%
- \dtl@domappings\@dtl@line
- \expandafter\@dtl@toks\expandafter{\@dtl@line}%
- \edef\@dtl@lin@{\@dtl@separator\the\@dtl@toks
- \@dtl@separator}%
- \dtl@entrycr=0\relax
- \whiledo{\not\equal{\@dtl@lin@}{\@dtl@separator}}{%
- \expandafter\@dtl@lopoff\@dtl@lin@\to
- \@dtl@lin@\@dtl@thisentry
- \advance\dtl@entrycr by 1\relax
- \edef\@dtl@thiskey{%
- \csname @dtl@inky@\romannumeral\dtl@entrycr\endcsname}%
- \expandafter\@dtl@toks\expandafter{\@dtl@thisentry}%
- \edef\@do@dtlnewentry{\noexpand\DTLnewdbentry
- {#1}{\@dtl@thiskey}{\the\@dtl@toks}}%
- \@do@dtlnewentry
- }%
- }%
- \ifeof\@dtl@read \@dtl@conditionfalse\fi
- \if@dtl@condition
- \repeat
- \fi
- \fi
-\fi
-\closein\@dtl@read
-}{%
-\PackageError{datatool}{Can't load database `#1' (file `#2'
-doesn't exist)}{}%
-}}
+\newcommand*\DTLloadrawdb{%
+ \let\@dtl@doreadline\@dtl@readrawline
+ \@dtlloaddb
+}
\begingroup
\catcode`\%=\active
\catcode`$=\active
@@ -3258,6 +4627,19 @@ doesn't exist)}{}%
\@dtl@dosubstnext{#1}{#2}%
}
\def\@dtl@dosubstitutenoop#1#2{}
+\newcommand*{\DTLifinlist}[4]{%
+ \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{%
+ \def\@before{##1}%
+ \def\@after{##2}%
+ }%
+ \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil
+ \end@dtl@doifinlist
+ \ifx\@after\@nnil
+ #4%
+ \else
+ #3%
+ \fi
+}
\newcommand*{\@dtl@currencies}{\$,\pounds}
\newcommand*{\DTLnewcurrencysymbol}[1]{%
\expandafter\toks@\expandafter{\@dtl@currencies}%
@@ -3308,11 +4690,12 @@ doesn't exist)}{}%
\fi
}
\newcommand*{\dtlshowdb}[1]{%
-\expandafter\show\csname dtldb@#1\endcsname}
+\expandafter\showthe\csname dtldb@#1\endcsname}
\newcommand*{\dtlshowdbkeys}[1]{%
-\expandafter\show\csname dtlkeys@#1\endcsname}
+\expandafter\showthe\csname dtlkeys@#1\endcsname}
\newcommand*{\dtlshowtype}[2]{%
-\expandafter\show\csname @dtl@idtype@#1@#2\endcsname}
+ \DTLgetdatatype{\@dtl@type}{#1}{#2}\show\@dtl@type
+}
\endinput
%%
%% End of file `datatool.sty'.