\input ptb-utils
\_checkloaded{arrays}
\input pdfData/ptb-stack

\def\createarray#1{%
    \_xp\currdef\csname arr@#1\endcsname{}%
    \_xp\currdef\csname arr@#1@len\endcsname{0}%
}

\def\arrayexists#1{%
    \ifcsname arr@#1\endcsname%
        \let\@return@value=\True%
    \else%
        \let\@return@value=\False%
    \fi%
}

\def\ensurearray#1{%
    \unless\ifcsname arr@#1\endcsname%
        \createarray{#1}%
    \fi%
}

\def\localizearray#1{%
    \_xp\localize\csname arr@#1\endcsname%
    \_xp\localize\csname arr@#1@len\endcsname%
}

\long\def\appendarray#1#2{%
    \def\_uregA{\_xp\currdef\csname arr@#1\endcsname}%
    \_xp\_xp\_xp\_uregA\_xp\_xp\_xp{\csname arr@#1\endcsname\_arr_index{#2}}%
    \_xp\curredef\csname arr@#1@len\endcsname{\the\numexpr\csname arr@#1@len\endcsname+1\relax}%
}

\long\def\prependarray#1#2{%
    \def\_uregA{\_xp\currdef\csname arr@#1\endcsname}%
    \def\_uregB{\_arr_index{#2}}%
    \_xp\_xp\_xp\_xp\_xp\_xp\_xp\_uregA\_xp\_xp\_xp\_xp\_xp\_xp\_xp{\_xp\_xp\_xp\_uregB\csname arr@#1\endcsname}%
    \_xp\curredef\csname arr@#1@len\endcsname{\the\numexpr\csname arr@#1@len\endcsname+1\relax}%
}

\long\def\appendarraymany#1#2{%
    \map{\appendarray{#1}}{#2}%
}

\long\def\_appendarrayvalue#1#2#3{\appendarray{#1}{{#3}{#2}}}
\long\def\appendarraymanyvalued#1#2#3{\map{\_appendarrayvalue{#1}{#2}}{#3}}

\def\arraylen#1{%
    \csname arr@#1@len\endcsname%
}

\def\getarraylen#1#2{%
    \_xp\let\_xp#2\csname arr@#1@len\endcsname%
}

\def\executearray#1{\csname arr@#1\endcsname}

\def\arraymap#1#2{%
    \def\_mac_arr_cnt{0}%
    \beginscope%
    \localize\_arr_index%
    \long\def\_arr_index##1{%
        \beginscope%
        \localize\_mac_arr_cnt%
        #2{##1}{\_mac_arr_cnt}%
        \edef\_mac_arr_cnt{\the\numexpr\_mac_arr_cnt+1\relax}%
        \endscope%
    }%
    \csname arr@#1\endcsname%
    \endscope%
}

\newcount\_arr_cnt
\newcount\_arr_cntB
\def\indexarray#1#2#3{%
    \let#3=\_nul%
    \long\def\_arr_index##1{%
        \ifnum\_arr_cnt=#2 %
            \def#3{##1}
        \fi%
        \advance\_arr_cnt by 1 %
    }
    \csname arr@#1\endcsname%
}

\def\removearray#1#2#3{%
    \_arr_cnt=0 %
    \let#3=\_nul%
    \_xp\let\_xp\_regA\csname arr@#1\endcsname%
    \createarray{#1}%
    \def\_arr_index##1{%
        \ifnum\_arr_cnt=#2 %
            \def#3{##1}%
        \else%
            \appendarray{#1}{##1}%
        \fi
        \advance\_arr_cnt by 1 %
    }%
    \_regA%
}

\def\removeitemarray#1#2{%
    \def\_temp{#2}%
    \_xp\let\_xp\_regA\csname arr@#1\endcsname%
    \createarray{#1}%
    \def\_arr_index##1{%
        \def\_tempA{##1}%
        \unless\ifx\_temp\_tempA%
            \appendarray{#1}{##1}%
        \fi%
    }%
    \_regA%
}

\long\def\__printarray#1#2#3{%
    #1{#2}%
    \unless\ifnum\_arr_cnt=\_temp%
        ,
    \fi%
}

\def\_printarray#1[#2]{%
    \getarraylen{#1}\_temp%
    \edef\_temp{\the\numexpr \_temp-1\relax}%
    \arraymap{#1}{\__printarray{#2}}%
}

\def\printarray#1{\_ifnextchar[ {\_printarray{#1}}{\_printarray{#1}[\relax]}}

\def\copyarray#1#2{%
    \def\_temp{\csname arr@#2\endcsname}%
    \_xp\_xp\_xp\_xp\_xp\_xp\_xp\let\_xp\_temp\csname arr@#1\endcsname%
    \def\_temp{\csname arr@#2@len\endcsname}%
    \_xp\_xp\_xp\_xp\_xp\_xp\_xp\let\_xp\_temp\csname arr@#1@len\endcsname%
}

\def\_concatenatearray#1#2#3#4#5{%
    \_xp\currdef\csname arr@#5\endcsname{#1#2}%
    \_xp\curredef\csname arr@#5@len\endcsname{\the\numexpr\csname arr@#3@len\endcsname + \csname arr@#4@len\endcsname\relax}%
}

\def\concatenatearrays#1#2#3{%
    \def\_temp{\csname arr@#1\endcsname}%
    \_xp\_xp\_xp\_concatenatearray\_xp\_xp\_xp{\_xp\_temp\_xp}\_xp{\csname arr@#2\endcsname}{#1}{#2}{#3}%
}

\def\createmarray#1{\_xp\currdef\csname marr@#1@len\endcsname{0}}

\def\localizemarray#1{%
    \_xp\localize\csname marr@#1@len\endcsname%
    \_arr_cnt=0 %
    \loop\ifnum\_arr_cnt < \csname marr@#1@len\endcsname %
        \_xp\localize\csname marr@#1@idx@\the\_arr_cnt\endcsname%
        \advance\_arr_cnt by 1 %
    \repeat%
}

\def\appendmarray#1#2{%
    \_xp\currdef\csname marr@#1@idx@\csname marr@#1@len\endcsname\endcsname{#2}%
    \_xp\curredef\csname marr@#1@len\endcsname{\the\numexpr\csname marr@#1@len\endcsname + 1\relax}%
}

\def\_rappendmarray#1#2{\appendmarray{#2}{#1}}
\def\_rappendarray#1#2{\appendarray{#2}{#1}}

\def\printmarray#1{%
    \_arr_cnt=0 %
    \loop\ifnum\_arr_cnt < \csname marr@#1@len\endcsname %
        (\csname marr@#1@idx@\the\_arr_cnt\endcsname)%
        \advance\_arr_cnt by 1 %
        \ifnum\_arr_cnt < \csname marr@#1@len\endcsname %
            , %
        \fi%
    \repeat%
}

\def\convertarray#1#2{%
    \createmarray{#2}%
    \_xp\curredef\csname marr@#2@len\endcsname{\csname arr@#1@len\endcsname}%
    \_arr_cnt=0 %
    \def\_arr_index##1{%
        \_xp\currdef\csname marr@#2@idx@\the\_arr_cnt\endcsname{##1}%
        \advance\_arr_cnt by 1 %
    }%
    \csname arr@#1\endcsname%
}

\def\convertmarray#1#2{%
    \createarray{#2}%
    %\_xp\edef\csname arr@#2@len\endcsname{\csname marr@#1@len\endcsname}%
    \_arr_cnt=0 %
    \loop\ifnum\_arr_cnt < \csname marr@#1@len\endcsname %
        \_xp\_rappendarray\_xp{\csname marr@#1@idx@\the\_arr_cnt\endcsname}{#2}%
        \advance\_arr_cnt by 1 %
    \repeat%
}

\def\copymarray#1#2{%
    \createmarray{#2}%
    \_arr_cnt=0 %
    \loop\ifnum\_arr_cnt < \csname marr@#1@len\endcsname %
        \_xp\_xp\_xp\_rappendmarray\_xp\_xp\_xp{\csname marr@#1@idx@\the\_arr_cnt\endcsname}{#2}%
        \advance\_arr_cnt by 1 %
    \repeat%
}

%   #1: name of array
%   #2: text to initialize array to
%   #3: macro for creating array
%   #4: macro for appending to array
\def\_init_array#1#2#3#4{%
    #3{#1}%
    \commap{#4{#1}}{#2}%
}

\def\initarray#1#2{%
    \_init_array{#1}{#2}\createarray\appendarray%
}

\def\initmarray#1#2{%
    \_init_array{#1}{#2}\createmarray\appendmarray%
}

\def\findarray#1#2{%
    \def\_regA{#2}%
    \let\@return@value=\False%
    \def\_arr_index##1{%
        \def\_regB{##1}%
        \ifx\_regA\_regB%
            \let\@return@value=\True%
        \fi%
    }%
    \csname arr@#1\endcsname%
}

\def\uniqueappendarray#1#2{%
    \findarray{#1}{#2}%
    \ifx\@return@value\False%
        \appendarray{#1}{#2}%
    \fi%
}

\def\findmarray#1#2#3{%
    \def\_regA{#2}
    \let\@return@value=\False%
    \_arr_cnt=0 %
    \loop\ifnum\_arr_cnt < \csname arr@#1@len\endcsname %
        \ifx\_regA\csname arr@#1@idx@\the\_arr_cnt\endcsname%
            \let\@return@value=\True%
            \_xp\let\_xp#3\csname arr@#1@idx@\the\_arr_cnt\endcsname%
        \fi%
        \advance\_arr_cnt by 1 %
    \repeat%
}

