%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This is a helper package with an elementary list datastructure.
%
% Its implementation is based on Knuth's list macros in "The TeXbook".
%
% It features a convenient set of list macros, but it is not fast.
% In fact, every elementary operation requires time O(N), so working
% with this list easily leads to O(N^2) runtime.
%
% The following macros are supplied:
%
% \pgfplotslistnewempty
% \pgfplotslistnew
% \pgfplotslistcopy
% \pgfplotslistpopfront
% \pgfplotslistfront
% \pgfplotslistpushback
% \pgfplotslistpushfront
% \pgfplotslistsize
% \pgfplotslistselect
% \pgfplotslistset
% \pgfplotslistcheckempty
% \pgfplotslistforeach
%
% @see \pgfplotsapplist a "real" list with O(1) pushback, but limited application.
% @see \pgfplotsapplistX a preasymptotical fast list to accumulate elements.
% @see \pgfplotsapplistXX an optimized version of \pgfplotsapplistX.
%
% Copyright 2007/2008 by Christian Feuersänger.
%
% This program is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see .
%
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newif\ifpgfplotslistempty
% Low-level IMPLEMENTATION NOTE
% the list is stored in the form
% '\pgfpl@@{}\pgfpl@@{}\pgfpl@@{}....\pgfpl@@{}'
\newif\ifpgfplots@loop@CONTINUE
\newif\ifpgfplotslist@is@backslash@terminated
% Creates a new, empty list.
\long\def\pgfplotslistnewempty#1{\let#1=\pgfutil@empty}
% Creates a new list with an abirtrary number of elements.
% Arguments:
% #1: the list's name (a macro name)
% #2: the elements in the form
% first\\second\\third\\ ...\\
% like in tabular with one column.
% You can also use comma-separated lists
% first,second,third
%
% Example:
% 1.
% \pgfplotslistnew\foolist{First Element\\Second Element\\Third Element\\}
% WARNING: do NOT forget the final '\\'!
%
% 2.
% \pgfplotslistnew\foolist{First Element,Second Element,Third Element}
%
% Use braces '{}' to use '\\' or ',' as arguments.
%
\long\def\pgfplotslistnew#1#2{%
\pgfkeys@spdef\pgfplotslist@loc@TMPa{#2}%
\def\pgfplotslist@loc@TMPb{\pgfplotslistnew@{#1}}%
\expandafter\pgfplotslist@loc@TMPb\expandafter{\pgfplotslist@loc@TMPa}%
}
\long\def\pgfplotslistnew@#1#2{%
\pgfplotslist@check@backslash@list #2\\\pgfplotslist@EOI
\ifpgfplotslist@is@backslash@terminated
\pgfplotslistnew@backslash@{#1}{#2}%
\else
\pgfplots@foreach@to@list{#2}\to#1%
\fi
}
% Is this here *ever* used!? I guess not.
\long\def\pgfplotslistnew@backslash#1#2{%
\pgfplotslistnewempty{#1}%
\pgfplotslist@check@backslash@list #2\\\pgfplotslist@EOI
\ifpgfplotslist@is@backslash@terminated
\long\def\pgfplotslistnew@impl@rest{#2\pgfplotslist@EOI\\}%
\def\pgfplotslistnew@backslash@loop{\pgfplotslistnew@impl{#1}}%
\else
\def\pgfplotslistnew@backslash@loop{\pgfplotslistnew@impl@comma{#1}}%
\long\def\pgfplotslistnew@impl@rest{#2\pgfplotslist@EOI,}%
\fi
\expandafter\pgfplotslistnew@backslash@loop\pgfplotslistnew@impl@rest
}%
\long\def\pgfplotslistnew@backslash@#1#2{%
\pgfplotslistnewempty{#1}%
\def\pgfplotslistnew@backslash@loop{\pgfplotslistnew@impl{#1}}%
\pgfplotslistnew@backslash@loop#2\pgfplotslist@EOI\\%
}%
% helper macro for \pgfplotslistnew
\long\def\pgfplotslistnew@impl#1#2\\{%
\def\pgfplotslist@loc@TMPa{#2}%
\ifx\pgfplotslist@loc@TMPa\pgfplotslist@EOI
\else
\pgfplotslistpushback{#2}\to#1\relax%
\expandafter\pgfplotslistnew@backslash@loop
\fi
}
\long\def\pgfplotslistnew@impl@comma#1#2,{%
\def\pgfplotslist@loc@TMPa{#2}%
\ifx\pgfplotslist@loc@TMPa\pgfplotslist@EOI
\else
\pgfplotslistpushback{#2}\to#1\relax%
\expandafter\pgfplotslistnew@backslash@loop
\fi
}
\def\pgfplotslist@EOI{\pgfplotslist@EOI}
\def\pgfplotslist@backslashsep{\\}
\long\def\pgfplotslist@check@backslash@list#1\\#2\pgfplotslist@EOI{%
\def\pgfplotslist@loc@TMPx{#2}%
\ifx\pgfplotslist@loc@TMPx\pgfutil@empty
\pgfplotslist@is@backslash@terminatedfalse
\let\pgfplotslist@check@backslash@list@next=\relax
\else
\def\pgfplotslist@loc@TMPy{ }%
\ifx\pgfplotslist@loc@TMPx\pgfplotslist@loc@TMPy
\pgfplotslist@is@backslash@terminatedfalse
\let\pgfplotslist@check@backslash@list@next=\relax
\else
\ifx\pgfplotslist@loc@TMPx\pgfplotslist@backslashsep
% ok. The list is something like 'a\\b\\' so the
% complete input is
% 'a\\b\\ \\ \EOI'
% we have iterated long enough to find only the '\\'
% right before the \EOI. It is thus backslash
% terminated.
\pgfplotslist@is@backslash@terminatedtrue
\let\pgfplotslist@check@backslash@list@next=\relax
\else
% Iterate. We want to check the last list element.
\long\def\pgfplotslist@check@backslash@list@next{\pgfplotslist@check@backslash@list#2\pgfplotslist@EOI}%
\fi
\fi
\fi
\pgfplotslist@check@backslash@list@next
}%
% Copies list #1 to list #2.
\def\pgfplotslistcopy#1\to#2{\let#2=#1}
% #1: the item to prepend
% #2: the list as macro name
% Example:
% \pgfplotslistpushfront Next first Element\to\foolist
\long\def\pgfplotslistpushfront#1\to#2{%
\t@pgfplots@toka={\pgfpl@@{#1}}%
\t@pgfplots@tokb=\expandafter{#2}%
\edef#2{\the\t@pgfplots@toka\the\t@pgfplots@tokb}%
}
\long\def\pgfplotslistpushfrontglobal#1\to#2{%
\t@pgfplots@toka={\pgfpl@@{#1}}%
\t@pgfplots@tokb=\expandafter{#2}%
\xdef#2{\the\t@pgfplots@toka\the\t@pgfplots@tokb}%
}
% Assembles a low-level list item representation into the token
% register #2.
\long\def\pgfplotslist@assembleentry#1\into#2{%
#2={\pgfpl@@{#1}}%
}
% #1: the item to append
% #2: the list as macro name
% Example:
% \pgfplotslistpushback Next last element\to\foolist
\long\def\pgfplotslistpushback#1\to#2{%
\t@pgfplots@toka={\pgfpl@@{#1}}%
\ifx#2\pgfutil@empty
\t@pgfplots@tokb={}%
\else
\t@pgfplots@tokb=\expandafter{#2}%
\fi
\edef#2{\the\t@pgfplots@tokb\the\t@pgfplots@toka}%
}
% Adds '#1' to the GLOBAL list '#2'.
\long\def\pgfplotslistpushbackglobal#1\to#2{%
\t@pgfplots@toka={\pgfpl@@{#1}}%
\ifx#2\pgfutil@empty
\t@pgfplots@tokb={}%
\else
\t@pgfplots@tokb=\expandafter{#2}%
\fi
\xdef#2{\the\t@pgfplots@tokb\the\t@pgfplots@toka}%
}
% Concatenates two lists #2 and #3 into #1
% Example:
% \pgfplotslistconcat\result=\foolist&\bar
\long\def\pgfplotslistconcat#1=#2{%
\t@pgfplots@toka=\expandafter{#2}%
\t@pgfplots@tokb=\expandafter{#3}%
\edef#1{\the\t@pgfplots@toka\the\t@pgfplots@tokb}%
}
% implements #2 := pop_front(#1)
% Example:
% \pgfplotslistpopfront\foolist\to\poppedfirstelem
\long\def\pgfplotslistpopfront#1\to#2{%
\pgfplotslistcheckempty#1\relax
\ifpgfplotslistempty
\pgfplotsthrow{no such element}{#1}{\string\pgfplotslistpopfront\ from \string#1\ although list is EMPTY}\pgfeov%
\else
\expandafter\pgfplotslistpopfront@impl#1\pgfplotslistpopfront@macronames#1#2%
\fi
}
\long\def\pgfplotslistfront#1\to#2{%
\pgfplotslistcheckempty#1\relax
\ifpgfplotslistempty
\pgfplotsthrow{no such element}{#2}{\string\pgfplotslistfront\ from \string#1\ although list is EMPTY}\pgfeov%
\else
\expandafter\pgfplotslistfront@impl#1\pgfplotslistpopfront@macronames#2%
\fi
}
% implementation helper for listpopfront
\long\def\pgfplotslistpopfront@impl\pgfpl@@#1#2\pgfplotslistpopfront@macronames#3#4{%
\def#4{#1}%
\def#3{#2}%
}
\long\def\pgfplotslistfront@impl\pgfpl@@#1#2\pgfplotslistpopfront@macronames#3{%
\def#3{#1}%
}
% Counts the number of elements in list #1, storing it into the count
% register #2.
% Example:
% \pgfplotslistsize\foo\to{\count0}%
% \the\count0
\long\def\pgfplotslistsize#1\to#2{%
#2=0%
\long\def\pgfpl@@##1{\advance#2 by 1 }%
#1%
}
% Returns the #1th element of list #2 into macro #3
% Arguments:
% #1: a count 0,...,N-1 where N is the list size.
% You may specify a number of a count.
% #2: a list
% #3: a macro name
% Example:
% Element 0:
% \pgfplotslistselect0\of\foo\to\elem
% \elem
% Element \count1:
% \pgfplotslistselect\count1\of\foo\to\elem
\long\def\pgfplotslistselect#1\of#2\to#3{%
\global\def\pgfplotslistselect@tmp{\pgfplotsthrow{no such element}{#3}{The requested list entry with index #1 of \string#2 is too large; this list has not enough elements.}\pgfeov}%
\pgfplotslistselect@{#1}\of{#2}\to{#3}%
}
\long\def\pgfplotslistselect@#1\of#2\to#3{%
\begingroup
\count0=#1\relax
\long\def\pgfpl@@##1{%
\advance\count0 by-1\relax
\ifnum\count0=-1\relax
\global\def\pgfplotslistselect@tmp{\def#3{##1}}%
\fi%
}%
#2%
\endgroup
\pgfplotslistselect@tmp
}
% Selects a list entry. If it does not exist, '#' will be empty.
\long\def\pgfplotslistselectorempty#1\of#2\to#3{%
\global\def\pgfplotslistselect@tmp{\def#3{}}%
\pgfplotslistselect@{#1}\of{#2}\to{#3}%
}
% Changes the element at index '#1' of list '#2' to the content '#3'.
%
% This operation has quadratic (!) time in the worst case.
\long\def\pgfplotslistset#1\of#2\to#3{%
\ifcase#1\relax
% change first:
\def\pgfplotslistset@\pgfpl@@##1##2\relax{\def#2{\pgfpl@@{#3}##2}}%
\expandafter\pgfplotslistset@#2\relax
\or
% change second:
\def\pgfplotslistset@\pgfpl@@##1\pgfpl@@##2##3\relax{\def#2{\pgfpl@@{##1}\pgfpl@@{#3}##2}}%
\expandafter\pgfplotslistset@#2\relax
\or
\def\pgfplotslistset@\pgfpl@@##1\pgfpl@@##2\pgfpl@@##3##4\relax{\def#2{\pgfpl@@{##1}\pgfpl@@{##2}\pgfpl@@{#3}##3}}%
\expandafter\pgfplotslistset@#2\relax
\or
\def\pgfplotslistset@\pgfpl@@##1\pgfpl@@##2\pgfpl@@##3\pgfpl@@##4##5\relax{\def#2{\pgfpl@@{##1}\pgfpl@@{##2}\pgfpl@@{##3}\pgfpl@@{#3}##4}}%
\expandafter\pgfplotslistset@#2\relax
\else
\begingroup
\global\pgfplotslistnewempty\pgfplotslistnewempty\pgfplotslist@glob@TMPa
\let\pgfpl@@=\pgfutil@empty % make sure it is not \relax.
\count0=#1\relax
\count1=0
\def\pgfplotslistset@newelem{#3}%
\expandafter\pgfplotslistset@loop#2\relax
\ifnum\count1 =\count0
\else
\pgfplotsthrow{no such element}{\pgfplots@loc@TMPa}{\string\pgfplotslistset{\the\count0} failed because there are only \the\count1\space elements in the list. Use pushback to resize it.}\pgfeov%
\global\let\pgfplotslist@glob@TMPa=\pgfplots@loc@TMPa
\fi
\endgroup
\let#3=\pgfplotslist@glob@TMPa
\global\let\pgfplotslist@glob@TMPa=\relax
\fi
}%
\def\pgfplotslistset@loop{%
\pgfutil@ifnextchar\relax{%
\pgfplotslistset@loop@break
}{%
\pgfplotslistset@loop@next
}%
}
\def\pgfplotslistset@loop@break#1\relax{%
% re-append remaining elements:
\expandafter\gdef\expandafter\pgfplotslist@glob@TMPa\expandafter{\pgfplotslist@glob@TMPa#1}
}%
\def\pgfplotslistset@loop@next\pgfpl@@#1{%
\ifnum\count1 =\count0
% Ah - we found the element to replace!
\expandafter\pgfplotslistpushbackglobal\expandafter{\pgfplotslistset@newelem}\to\pgfplotslist@glob@TMPa
\expandafter\pgfplotslistset@loop@break
\else
\pgfplotslistpushbackglobal{#1}\to\pgfplotslist@glob@TMPa
\advance\count1 by1
\expandafter\pgfplotslistset@loop
\fi
}%
% Sets the boolean \ifpgfplotslistempty depending on whether list #1 is empty
% or not.
% Example:
%
% \pgfplotslistcheckempty\foolist
% \ifpgfplotslistempty
% List foolist is empty!
% \else
% List is not empty.
% \fi
\def\pgfplotslistcheckempty#1{%
\ifx#1\pgfutil@empty
\pgfplotslistemptytrue
\else
\ifx#1\relax
\pgfplots@warning{WARNING: possible logic error in script code: the command \string\pgfplotslistcheckempty{\string#1} encountered an undefined argument.}%
\pgfplotslistemptytrue
\else
\pgfplotslistemptyfalse
\fi
\fi
}
% Iterates through each list element, names it #2 and calls code #3.
% Example:
% \pgfplotslistnew\foolist{Eins\\Zwei\\Drei\\}%
% \pgfplotslistforeach\foolist\as\foo{Element \foo\par}%
% results in
% Element Eins
% Element Zwei
% Element Drei
% Each single element will be grouped with TeX groups.
\long\def\pgfplotslistforeach#1\as#2#3{%
\begingroup
\long\def\pgfpl@@##1{%
\t@pgfplots@tokc={##1}% this allows '#' inside of '##1'
\edef#2{\the\t@pgfplots@tokc}%
\begingroup #3\endgroup}%
#1\relax
\endgroup
}
% The same but without groups around #3.
%
% The list can be nested.
\long\def\pgfplotslistforeachungrouped#1\as#2#3{%
\t@pgfplots@tokb={{#2}{#3}}%
\t@pgfplots@tokc=\expandafter{#1}%
\edef\pgfplotslist@loc@TMPa{%
\noexpand\pgfplotslistforeachungrouped@
\the\t@pgfplots@tokb%
\the\t@pgfplots@tokc
\noexpand\pgfpl@@\noexpand\pgfplotslistforeachungrouped@EOI
}%
\pgfplotslist@loc@TMPa
}%
% Technical helper method which performs the loop.
% ASSUMPTION:
% \pgfplotslistforeachungrouped@
% {}
% {}
% \pgfpl@@{}\pgfpl@@{}\pgfpl@@{}\pgfpl@@\pgfplotslistforeachungrouped@EOI
%
% -> iterate through argument until \pgfplotslistforeachungrouped@EOI
% comes.
\long\def\pgfplotslistforeachungrouped@#1#2\pgfpl@@#3{%
\t@pgfplots@tokc={#3}% this allows '#' inside of '#3'
\edef\pgfplotslist@loc@TMPa{\the\t@pgfplots@tokc}%
\ifx\pgfplotslist@loc@TMPa\pgfplotslistforeachungrouped@EOI
% ok, terminate loop.
\let\pgfplotslistforeachungrouped@next=\relax
\else
% perform loop iteration ...
\let#1=\pgfplotslist@loc@TMPa
#2\relax
% and continue iterating.
\def\pgfplotslistforeachungrouped@next{\pgfplotslistforeachungrouped@{#1}{#2}}%
\fi
\pgfplotslistforeachungrouped@next
}%
\def\pgfplotslistforeachungrouped@EOI{\pgfplotslistforeachungrouped@EOI}% equals only itself in \ifx