* Initial check-in of stl

git-svn-id: trunk@17233 -
This commit is contained in:
michael 2011-04-03 09:15:56 +00:00
parent 736071e716
commit a33e5eb0eb
46 changed files with 5834 additions and 0 deletions

45
.gitattributes vendored
View File

@ -2295,6 +2295,51 @@ packages/fcl-res/xml/versionconsts.xml svneol=native#text/plain
packages/fcl-res/xml/versionresource.xml svneol=native#text/plain
packages/fcl-res/xml/versiontypes.xml svneol=native#text/plain
packages/fcl-res/xml/winpeimagereader.xml svneol=native#text/plain
packages/fcl-stl/Makefile svneol=native#text/plain
packages/fcl-stl/Makefile.fpc svneol=native#text/plain
packages/fcl-stl/doc/arrayutils.tex svneol=native#text/plain
packages/fcl-stl/doc/deque.tex svneol=native#text/plain
packages/fcl-stl/doc/dequeexample.pp svneol=native#text/plain
packages/fcl-stl/doc/main.tex svneol=native#text/plain
packages/fcl-stl/doc/makra.tex svneol=native#text/plain
packages/fcl-stl/doc/map.tex svneol=native#text/plain
packages/fcl-stl/doc/mapexample.pp svneol=native#text/plain
packages/fcl-stl/doc/priorityqueue.tex svneol=native#text/plain
packages/fcl-stl/doc/priorityqueueexample.pp svneol=native#text/plain
packages/fcl-stl/doc/queue.tex svneol=native#text/plain
packages/fcl-stl/doc/queueexample.pp svneol=native#text/plain
packages/fcl-stl/doc/set.tex svneol=native#text/plain
packages/fcl-stl/doc/setexample.pp svneol=native#text/plain
packages/fcl-stl/doc/sortingexample.pp svneol=native#text/plain
packages/fcl-stl/doc/stack.tex svneol=native#text/plain
packages/fcl-stl/doc/stackexample.pp svneol=native#text/plain
packages/fcl-stl/doc/util.tex svneol=native#text/plain
packages/fcl-stl/doc/vector.tex svneol=native#text/plain
packages/fcl-stl/doc/vectorexample.pp svneol=native#text/plain
packages/fcl-stl/src/garrayutils.pp svneol=native#text/plain
packages/fcl-stl/src/gdeque.pp svneol=native#text/plain
packages/fcl-stl/src/ghashset.pp svneol=native#text/plain
packages/fcl-stl/src/gmap.pp svneol=native#text/plain
packages/fcl-stl/src/gpriorityqueue.pp svneol=native#text/plain
packages/fcl-stl/src/gqueue.pp svneol=native#text/plain
packages/fcl-stl/src/gset.pp svneol=native#text/plain
packages/fcl-stl/src/gstack.pp svneol=native#text/plain
packages/fcl-stl/src/gutil.pp svneol=native#text/plain
packages/fcl-stl/src/gvector.pp svneol=native#text/plain
packages/fcl-stl/tests/clean svneol=native#text/plain
packages/fcl-stl/tests/gdequetest.pp svneol=native#text/plain
packages/fcl-stl/tests/gmaptest.pp svneol=native#text/plain
packages/fcl-stl/tests/gmaptestzal.pp svneol=native#text/plain
packages/fcl-stl/tests/gpriorityqueuetest.pp svneol=native#text/plain
packages/fcl-stl/tests/gqueuetest.pp svneol=native#text/plain
packages/fcl-stl/tests/gsetrefcounttest.pp svneol=native#text/plain
packages/fcl-stl/tests/gsettest.pp svneol=native#text/plain
packages/fcl-stl/tests/gsorttest.pp svneol=native#text/plain
packages/fcl-stl/tests/gstacktest.pp svneol=native#text/plain
packages/fcl-stl/tests/gvectortest.pp svneol=native#text/plain
packages/fcl-stl/tests/run-all-tests svneol=native#text/plain
packages/fcl-stl/tests/suiteconfig.pp svneol=native#text/plain
packages/fcl-stl/tests/testrunner.pp svneol=native#text/plain
packages/fcl-web/Makefile svneol=native#text/plain
packages/fcl-web/Makefile.fpc svneol=native#text/plain
packages/fcl-web/Makefile.org svneol=native#text/plain

2427
packages/fcl-stl/Makefile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
#
# Makefile.fpc for Free Component Library
#
[package]
name=fcl-stl
version=2.5.1
[target]
units=garrayutils gdeque gmap gpriorityqueue gqueue gset gstack gutil gvector
[install]
fpcpackage=y
[default]
fpcdir=../..
[compiler]
options=-S2h
sourcedir=src
[rules]
.NOTPARALLEL:

View File

@ -0,0 +1,47 @@
\chapter{TArrayUtils}
Set of utilities for manipulating arrays data.
Takes 3 arguements for specialization. First one is type of array (can be anything, which is
accesible by [] operator, e. g. ordinary array, vector, ...), second one is type of array element.
%Usage example for sorting:
%\lstinputlisting[language=Pascal]{sortingexample.pp}
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!procedure RandomShuffle(arr: TArr, size:SizeUint)! &
O(N)\\ \hline
\multicolumn{2}{|m{15cm}|}{Shuffles elements in array in random way} \\\hline\hline
\end{longtable}\chapter{TOrderingArrayUtils}
Set of utilities for manipulating arrays data.
Takes 3 arguements for specialization. First one is type of array (can be anything, which is
accesible by [] operator, e. g. ordinary array, vector, ...), second one is type of array element,
third one is comparator class (see TPriorityQueue for definition of comparator class).
Usage example for sorting:
\lstinputlisting[language=Pascal]{sortingexample.pp}
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!procedure Sort(arr: TArr, size:SizeUint)! &
O(N log N) average and worst case. Uses QuickSort, backed up by HeapSort, when QuickSort ends up in
using too much recursion.\\ \hline
\multicolumn{2}{|m{15cm}|}{Sort array arr, with specified size. Array indexing should be 0 based.} \\\hline\hline
\end{longtable}

View File

@ -0,0 +1,81 @@
\chapter{TDeque}
Implements selfresizing array. Indexing is 0-based.
Also implement constant time insertion from front.
Usage example:
\lstinputlisting[language=Pascal]{dequeexample.pp}
Memory complexity:
Uses at most 3times bigger memory than maximal array size (this is only case during reallocation).
Normal consumption is at most twice as maximal array size.
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!Create! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Constructor. Creates empty array.} \\ \hline\hline
\verb!function Size(): SizeUInt! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns size of array.} \\\hline\hline
\verb!procedure PushBack(value: T)! & Amortized
O(1), some operations might take O(N) time, when array needs to be reallocated, but sequence of N
operations takes O(N) time. \\ \hline
\multicolumn{2}{|m{15cm}|}{Inserts at the end of array (increases size by 1)} \\\hline\hline
\verb!procedure PopBack()! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Removes element from the end of array (decreases size by 1). When array
is empty, does nothing.} \\\hline\hline
\verb!procedure PushFront(value: T)! & Same as PushBack. \\ \hline
\multicolumn{2}{|m{15cm}|}{Inserts at the beginning of array (increases size by 1)} \\\hline\hline
\verb!procedure PopFront()! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Removes element from the beginning of array (decreases size by 1). When array
is empty, does nothing.} \\\hline\hline
\verb!function IsEmpty(): boolean! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns true when array is empty} \\\hline\hline
\verb!procedure Insert(position: SizeUInt; value: T)! & O(N) \\\hline
\multicolumn{2}{|m{15cm}|}{Inserts value at position. When position is greater than size, puts value
at the end of array.} \\\hline\hline
\verb!procedure Erase(positine: SizeUInt; value: T)! & O(N) \\\hline
\multicolumn{2}{|m{15cm}|}{Erases element from position. When position is outside of array does
nothing.} \\\hline\hline
\verb!procedure Clear! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Clears array (set size to zero). But doesn't free memory used by array.}
\\\hline\hline
\verb!function Front: T! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns first element from array.} \\\hline\hline
\verb!function Back: T! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns last element from array.} \\\hline\hline
\verb!procedure Resize(num: SizeUInt)! & O(N) \\\hline
\multicolumn{2}{|m{15cm}|}{Changes size of array to num. Doesn't guarantte anything about value of
newly alocated elements.} \\\hline\hline
\verb!procedure Reserve(num: SizeUInt)! & O(N) \\\hline
\multicolumn{2}{|m{15cm}|}{Alocates at least num elements for array. Usefull when you want to
pushback big number of elements and want to avoid frequent reallocation.} \\\hline\hline
\verb!property item[i: SizeUInt]: T; default;! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Property for accessing i-th element in array. Can be used just by square
brackets (its default property).} \\\hline\hline
\verb!property mutable[i: SizeUInt]: T;! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns pointer to i-th element in array. Usefull when you store records.} \\\hline
\end{longtable}

View File

@ -0,0 +1,24 @@
uses gdeque;
type TDequelli = specialize TDeque<longint>;
var Buffer:TDequelli; i:longint;
begin
Buffer := TDequelli.Create;
{Push 5 elements at the end of array}
for i:=1 to 5 do
Buffer.PushBack(i);
{change 3rd element to 47}
Buffer[2] := 47;
{pop last element}
Buffer.PopBack;
{push 3 element to front}
for i:=1 to 3 do
Buffer.PushFront(i*10);
{print all elements}
for i:=0 to Buffer.Size-1 do
writeln(Buffer[i]);
Buffer.Destroy;
end.

View File

@ -0,0 +1,63 @@
%% Template by Michal Forisek
\documentclass[a4paper]{report}
\usepackage[utf8]{inputenc}
\usepackage{a4wide}
\usepackage{tabularx}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{amsmath}
\usepackage{epsfig}
\usepackage{color}
\usepackage{mathrsfs}
\usepackage{verbatim}
\usepackage{hyperref}
\usepackage{subfigure}
\usepackage{float}
\usepackage{listings}
\usepackage{longtable}
\input{makra.tex}
\renewcommand{\chaptername}{}
\renewcommand{\thechapter}{}
\begin{document}
\thispagestyle{empty}
\vfill
\vfill
\begin{center}
\begin{minipage}{0.8\textwidth}
\hrule
\bigskip\bigskip
\centerline{\LARGE\sc FreePascal generic container library}
\smallskip
\centerline{(manual)}
\smallskip
\centerline{\url{http://code.google.com/p/stlpascal}}
\bigskip
\bigskip
\bigskip\bigskip
\hrule
\end{minipage}
\end{center}
\vfill
{~}
\hfill version 1.0
\eject % EOP i
\tableofcontents
\input{vector.tex}
\input{stack.tex}
\input{deque.tex}
\input{queue.tex}
\input{util.tex}
\input{priorityqueue.tex}
\input{arrayutils.tex}
\input{set.tex}
\input{map.tex}
\end{document}

View File

@ -0,0 +1,263 @@
% vim: set fdm=marker:
%% Original by Michal Forisek
%% zakladne definicie
\newcommand{\quoteme}[1]{\clqq#1\crqq}
\def\todo#1{[{\color{red} TODO:} {\bf #1}]}
\def\fixme#1{[{\color{red} FIXME:} {\bf #1}]}
\def\verify#1{\todo{verify: #1}}
\def\xor{\oplus}
\def\concat{\|}
%\def\inr{\in_{R}}
\def\toa #1 {\overset{#1}{\rightarrow}}
\def\inr{\overset{\$}{\leftarrow}}
\def\assign{\leftarrow}
\def\send{\rightarrow}
\def\isomorph{\cong}
\def\nsd{NSD}
\def\union{\cup}
\newcommand{\unit}[1]{\ensuremath{\, \mathrm{#1}}}
\DeclareMathOperator{\dlog}{dlog}
\def\compactlist{
\setlength{\itemsep}{1pt}
\setlength{\parskip}{0pt}
\setlength{\parsep}{0pt}
}
\def\mod{\,{\rm mod}\,}
%%% original od Misofa:
%% {{{
\catcode`\@=11
\def\R{{\cal R}}
\def\cent{{c\kern-0.3em|\kern0.1em}}
\def\N{{N}} % FIXME FIXME
\let\eps=\varepsilon
\def\relupdown#1#2#3{\mathrel{\mathop{#1}\limits^{#2}_{#3}} }
\let\then=\Rightarrow
\let\neht=\Leftarrow
\def\krok#1{\relupdown{\Longrightarrow}{}{#1}}
\def\thenrm{\relupdown{\Longrightarrow}{}{rm}}
\def\bicik{\upharpoonright}
\def\B{{\mathbf B}}
\def\kodTS#1{{\tt <}#1{\tt >}}
\newtheorem{definicia}{Definícia}[section]
\newtheorem{HLPpoznamka}{Poznámka}[section]
\newtheorem{HLPpriklad}{Príklad}[section]
\newtheorem{HLPcvicenie}[HLPpriklad]{Cvičenie}
\newtheorem{zadanie}{Úloha}[section]
\newenvironment{poznamka}{\begin{HLPpoznamka}\rm}{\end{HLPpoznamka}}
\newenvironment{priklad}{\begin{HLPpriklad}\rm}{\end{HLPpriklad}}
\newenvironment{cvicenie}{\begin{HLPcvicenie}\rm}{\end{HLPcvicenie}}
\newtheorem{veta}{Veta}[section]
\newtheorem{lema}[veta]{Lema}
\newtheorem{dosledok}[veta]{Dôsledok}
\newtheorem{teza}[veta]{Téza}
% \newtheorem{dokaz}{Dôkaz}[section]
\long\def\odsadene#1{
\leftskip=\parindent
\parindent=0pt
\vskip-5pt
\parskip=5pt
#1
\parskip=0pt
\parindent=\leftskip
\leftskip=0pt
} % end \odsadene
%%%%%%%%%%% PROSTREDIE PRE PISANIE KOMENTAROV
%\newenvironment{komentar}{%
%\vskip\baselineskip
%\tabularx{0.95\textwidth}{|X|}
%\sl
%}
%{\endtabularx
%\vskip\baselineskip
%}
\newenvironment{komentar}{%
\vskip\baselineskip\noindent
\tabularx{\textwidth}{>{\hsize=.2\hsize}X>{\hsize=1.8\hsize}X}
\sl ~ & \sl
}
{\endtabularx
\vskip\baselineskip
}
%\newenvironment{komentar}{%
%\vskip\baselineskip
%\trivlist\vspace{-4pt}\raggedleft\item\relax\tabularx{0.9\textwidth}{X}\sl}
%{\endtabularx\vspace{-4pt}\endtrivlist
%\vskip\baselineskip
%}
\newenvironment{dokaz}{\trivlist
\item[\hskip \labelsep{\bfseries Dôkaz.}]}{\endtrivlist}
%\newenvironment{dokaz}{%
%\vskip\baselineskip\noindent
%\tabularx{\textwidth}{||X||}
%\sl
%}
%{\endtabularx
%\vskip\baselineskip
%}
%%%%%%%%%%% PROSTREDIE PRE MOJE ITEMIZE
\newenvironment{myitemize}{%
\begin{itemize}
\itemsep-3pt
}
{\end{itemize}
}
%%%%%%%%%%% MATICKE MAKRA
\font\tenrm=csr10
\def\eps{\varepsilon}
% \def\R{{\mathbb R}}
\def\lvec#1{\overrightarrow{#1}}
\def\uhol{{\measuredangle}}
\def\then{\Rightarrow}
% \def\lg{{\rm lg}}
\def\lg{\log_2}
%\def\div{\mathbin{\rm div}}
\def\div{{\rm div}}
%%%%%%%%%%% PDF
\newif\ifpdf
\ifx\pdfoutput\undefined
\pdffalse
\else
\pdfoutput=1 \pdftrue
\fi
%%%%%%%%%%% OBRAZKY
\newcommand{\myincludegraphics}[2][]{\includegraphics[#1]{images/#2}}
%%%%%%%%%%% SLOVNICEK
\openout2=\jobname.slo
\newcommand{\definuj}[3][]{%
\def\tmpvoid{}\def\tmpfirst{#1}%
\ifx\tmpvoid\tmpfirst%
{\sl #2}\label{definicia:#2}\write2{#2 & #3 & \pageref{definicia:#2} \cr}%
\else%
{\sl #2}\label{definicia:#2}\write2{#1 & #3 & \pageref{definicia:#2} \cr}%
\fi}
\newcommand{\definujsilent}[2]{%
\label{definicia:#1}\write2{#1 & #2 & \pageref{definicia:#1} \cr}%
}
\newcommand\myglossary{
\immediate\closeout2
%\if@twocolumn\@restonecoltrue\onecolumn\else\@restonecolfalse\fi
\chapter{Slovníček pojmov}
\begin{tabular}{|l|l|r|}
\hline
{\bfseries slovenský pojem} & {\bfseries anglický preklad} & {\bfseries str.} \\
\hline
\InputIfFileExists{\jobname.srs}{}{~ & ~ & ~ \\}
\hline
\end{tabular}
%\if@restonecol\twocolumn\fi
}
%%%%%%%%%%% UVODZOVKY
\catcode`\"=13
\def "{\begingroup\clqq\def "{\endgroup\crqq}}
\def\dospecials{\do\ \do\\\do\{\do\}\do\$\do\&%
\do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~\do\"}
%%%%%%%%%%% DANGER BENDS
\font\manual=manfnt % font used for the METAFONT logo, etc.
\def\dbend{{\manual\char127}} % dangerous bend sign
\newlength{\bendwidth} \settowidth{\bendwidth}{\dbend} \newlength{\hangwidth}
\def\hangone{%
\hangwidth=\bendwidth%
\advance\hangwidth 5pt%
\hangindent\hangwidth%
}
\def\hangtwo{%
\hangwidth=\bendwidth%
\multiply\hangwidth 2%
\advance\hangwidth 6pt%
\hangindent\hangwidth%
}
\def\medbreak{\par\ifdim\lastskip<\medskipamount \removelastskip\penalty-100\medskip\fi}
\let\endgraf=\par
\def\d@nger{\medbreak\begingroup\clubpenalty=10000
%\def\d@nger{\begingroup\clubpenalty=10000
% \def\par{\endgraf\endgroup\medbreak} \noindent\hangone\hangafter=-2
\def\par{\endgraf\endgroup} \noindent\hangone\hangafter=-2
\hbox to0pt{\hskip-\hangindent\dbend\hfill}}
\outer\def\danger{\d@nger}
\def\dd@nger{\medbreak\begingroup\clubpenalty=10000
% \def\par{\endgraf\endgroup\medbreak} \noindent\hangtwo\hangafter=-2
\def\par{\endgraf\endgroup} \noindent\hangtwo\hangafter=-2
\hbox to0pt{\hskip-\hangindent\dbend\kern1pt\dbend\hfill}}
\outer\def\ddanger{\dd@nger}
\def\enddanger{\endgraf\endgroup} % omits the \medbreak
\def\enddangerhop{\endgraf\endgroup\medbreak}
\def\@nakedcite#1#2{{#1\if@tempswa , #2\fi}}
\DeclareRobustCommand\nakedcite{%
\@ifnextchar [{\@tempswatrue\@nakedcitex}{\@tempswafalse\@nakedcitex[]}}
\def\@nakedcitex[#1]#2{%
\let\@citea\@empty
\@nakedcite{\@for\@citeb:=#2\do
{\@citea\def\@citea{,\penalty\@m\ }%
\edef\@citeb{\expandafter\@firstofone\@citeb\@empty}%
\if@filesw\immediate\write\@auxout{\string\citation{\@citeb}}\fi
\@ifundefined{b@\@citeb}{\mbox{\reset@font\bfseries ?}%
\G@refundefinedtrue
\@latex@warning
{Citation `\@citeb' on page \thepage \space undefined}}%
{\hbox{\csname b@\@citeb\endcsname}} }}{#1}}
\long\def\FIXME#1{
\begin{center}
\begin{minipage}{0.8\textwidth}
{\bf FIXME:~}\sl #1
\end{minipage}
\end{center}
}
\catcode`\@=12
%% }}}

View File

@ -0,0 +1,87 @@
\chapter{TMap}
Implements container for ordered associative array with unique keys.
Takes 3 arguments for specialization, first one is type of keys, second one is type of values, third
one is comparator class for keys.
Usage example:
\lstinputlisting[language=Pascal]{mapexample.pp}
Some methods return type TMSet.PNode. Usefull fields are Data.Key, Data.Value, for retrieving
actual Key and Value from node. This node can be also used for navigation between elements by methods of set class.
You can also change value in node (but not key).
(But don't do anything else with it, you can lose data integrity.)
Memory complexity:
Size of stored base + constant overhead for each stored element (3 pointers + one boolean).
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!Create! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Constructor. Creates empty map.} \\ \hline\hline
\verb!function Size(): SizeUInt! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns number of elements in map.} \\\hline\hline
\verb!procedure Insert(key: TKey; value: TValue)! &
O(lg N), N is number of elements in map \\ \hline
\multicolumn{2}{|m{15cm}|}{Inserts key value pair into map. If key was already there, it will have
new value assigned.} \\\hline\hline
\verb!procedure Delete(key: TKey)! &
O(lg N) \\ \hline
\multicolumn{2}{|m{15cm}|}{Deletes key (and associated value) from map. If element is not in map, nothing happens.} \\\hline\hline
\verb!function Find(key: T):TMSet.PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for key in map. If value is not there returns nil. Otherwise
returns pointer to tree node (type TMSet.PNode), which can be used for retrieving data from map.} \\\hline\hline
\verb!function FindLess(key: T):TMSet.PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for greatest element less than key in map. If such element is not there returns nil. Otherwise
returns pointer to tree node (type TMSet.PNode), which can be used for retrieving data from map.} \\\hline\hline
\verb!function FindLessEqual(key: T):TMSet.PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for greatest element less or equal than key in map. If such element is not there returns nil. Otherwise
returns pointer to tree node (type TMSet.PNode), which can be used for retrieving data from map.} \\\hline\hline
\verb!function FindGreater(key: T):TMSet.PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for smallest element greater than key in map. If such element is not there returns nil. Otherwise
returns pointer to tree node (type TMSet.PNode), which can be used for retrieving data from map.} \\\hline\hline
\verb!function FindGreaterEqual(key: T):TMSet.PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for smallest element greater or equal than key in map. If such element is not there returns nil. Otherwise
returns pointer to tree node (type TMSet.PNode), which can be used for retrieving data from map.} \\\hline\hline
\verb!function Min:TMSet.PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns node containing smallest key of map. If map is empty returns
nil.} \\\hline\hline
\verb!function Max:TMSet.PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns node containing largest key of map. If map is empty returns
nil.} \\\hline\hline
\verb!function Next(x:TMSet.PNode):TMSet.PNode! & O(lg N) worst case, but traversal from smallest element to
largest takes O(N) time \\\hline
\multicolumn{2}{|m{15cm}|}{Returns successor of x. If x is largest key of map, returns nil.} \\\hline\hline
\verb!function Prev(x:TMSet.PNode):TMSet.PNode! & O(lg N) worst case, but traversal from largest element to
smallest takes O(N) time \\\hline
\multicolumn{2}{|m{15cm}|}{Returns predecessor of x. If x is smallest key of map, returns nil.} \\\hline\hline
\verb!function IsEmpty(): boolean! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns true when map is empty.} \\\hline
\verb!function GetValue(key:TKey):TValue! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns value associated with key. Is key isn't in map crashes.} \\\hline
\verb!property item[i: Key]: TValue; default;! & O(ln N) \\\hline
\multicolumn{2}{|m{15cm}|}{Property for accessing key i in map. Can be used just by square
brackets (its default property).} \\\hline\hline
\end{longtable}

View File

@ -0,0 +1,24 @@
uses gmap, gutil;
type lesslli=specialize TLess<longint>;
maplli=specialize TMap<longint, longint, lesslli>;
var data:maplli; i:longint; iterator:maplli.TMSet.PNode;
begin
data:=maplli.Create;
for i:=0 to 10 do
data[i]:=10*i;
{Iteration through elements}
iterator:=data.Min;
while iterator<>nil do begin
writeln(iterator^.Data.Key, ' ', iterator^.Data.Value);
iterator:=data.next(iterator);
end;
writeln(data.FindLess(7)^.Data.Value);
data.Destroy;
end.

View File

@ -0,0 +1,44 @@
\chapter{TPriorityQueue}
Implements priority queue. It's container which allow insertions of elements and then retrieval of
the biggest one.
For specialization it needs two arguements. First is the type T of stored element. Second one is type
comparator class, which should have class function \verb!c(a,b: T):boolean! which return true, when
a is stricly less then b (or in other words, a should be poped out after b).
Usage example:
\lstinputlisting[language=Pascal]{priorityqueueexample.pp}
Memory complexity:
Since underlaying structure is TVector, memory complexity is same.
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!Create! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Constructor. Creates empty priority queue.} \\ \hline\hline
\verb!function Size(): SizeUInt! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns number of elements in priority queue.} \\\hline\hline
\verb!procedure Push(value: T)! & Amortized
O(lg N), some operations might take O(N) time, when underlaying array needs to be reallocated, but sequence of N
operations takes O(N lg N) time. \\ \hline
\multicolumn{2}{|m{15cm}|}{Inserts element at the back of queue.} \\\hline\hline
\verb!procedure Pop()! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Removes the biggest element from queue. If queue is empty does nothing.} \\\hline\hline
\verb!function IsEmpty(): boolean! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns true when queue is empty.} \\\hline\hline
\verb!function Top: T! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns the biggest element from queue.} \\\hline
\end{longtable}

View File

@ -0,0 +1,30 @@
{$mode objfpc}
uses gpriorityqueue;
type
lesslli = class
public
class function c(a,b: longint):boolean;inline;
end;
class function lesslli.c(a,b: longint):boolean;inline;
begin
c:=a<b;
end;
type priorityqueuelli = specialize TPriorityQueue<longint, lesslli>;
var data:priorityqueuelli; i:longint;
begin
data:=priorityqueuelli.Create;
for i:=1 to 10 do
data.Push(random(1000));
while not data.IsEmpty do begin
writeln(data.Top);
data.Pop;
end;
data.Destroy;
end.

View File

@ -0,0 +1,39 @@
\chapter{TQueue}
Implements queue.
Usage example:
\lstinputlisting[language=Pascal]{queueexample.pp}
Memory complexity:
Since underlaying structure is TDeque, memory complexity is same.
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!Create! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Constructor. Creates empty queue.} \\ \hline\hline
\verb!function Size(): SizeUInt! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns number of elements in queue.} \\\hline\hline
\verb!procedure Push(value: T)! & Amortized
O(1), some operations might take O(N) time, when array needs to be reallocated, but sequence of N
operations takes O(N) time \\ \hline
\multicolumn{2}{|m{15cm}|}{Inserts element at the back of queue.} \\\hline\hline
\verb!procedure Pop()! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Removes element from the beginning of queue. If queue is empty does nothing.} \\\hline\hline
\verb!function IsEmpty(): boolean! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns true when queue is empty.} \\\hline\hline
\verb!function Front: T! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns the first element from queue.} \\\hline
\end{longtable}

View File

@ -0,0 +1,17 @@
uses gqueue;
type queuelli = specialize TQueue<longint>;
var data:queuelli; i:longint;
begin
data:=queuelli.Create;
for i:=1 to 10 do
data.Push(10*i);
while not data.IsEmpty do begin
writeln(data.Front);
data.Pop;
end;
data.Destroy;
end.

View File

@ -0,0 +1,76 @@
\chapter{TSet}
Implements container for storing ordered set of unique elements.
Takes 2 arguments for specialization, first one is type of elements, second one is comparator class.
Usage example:
\lstinputlisting[language=Pascal]{setexample.pp}
Some methods return type of PNode. It has field Data, which can be used for retrieving data from
that node. This node can be also used for navigation between elements by methods of set class.
(But don't do anything else with it, you can lose data integrity.)
Memory complexity:
Size of stored base + constant overhead for each stored element (3 pointers + one boolean).
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!Create! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Constructor. Creates empty set.} \\ \hline\hline
\verb!function Size(): SizeUInt! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns number of elements in set.} \\\hline\hline
\verb!procedure Insert(value: T)! &
O(lg N), N is number of elements in set \\ \hline
\multicolumn{2}{|m{15cm}|}{Inserts element into set.} \\\hline\hline
\verb!procedure Delete(value: T)! &
O(lg N), N is number of elements in set \\ \hline
\multicolumn{2}{|m{15cm}|}{Deletes value from set. If element is not in set, nothing happens.} \\\hline\hline
\verb!function Find(value: T):PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for value in set. If value is not there returns nil. Otherwise
returns pointer to tree node (type PNode), which can be used for retrieving data from set.} \\\hline\hline
\verb!function FindLess(value: T):PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for greatest element less than value in set. If such element is not there returns nil. Otherwise
returns pointer to tree node (type PNode), which can be used for retrieving data from set.} \\\hline\hline
\verb!function FindLessEqual(value: T):PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for greatest element less or equal than value in set. If such element is not there returns nil. Otherwise
returns pointer to tree node (type PNode), which can be used for retrieving data from set.} \\\hline\hline
\verb!function FindGreater(value: T):PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for smallest element greater than value in set. If such element is not there returns nil. Otherwise
returns pointer to tree node (type PNode), which can be used for retrieving data from set.} \\\hline\hline
\verb!function FindGreaterEqual(value: T):PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Searches for smallest element greater or equal than value in set. If such element is not there returns nil. Otherwise
returns pointer to tree node (type PNode), which can be used for retrieving data from set.} \\\hline\hline
\verb!function Min:PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns node containing smallest element of set. If set is empty returns
nil.} \\\hline\hline
\verb!function Max:PNode! & O(lg N) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns node containing largest element of set. If set is empty returns
nil.} \\\hline\hline
\verb!function Next(x:PNode):PNode! & O(lg N) worst case, but traversal from smallest element to
largest takes O(N) time \\\hline
\multicolumn{2}{|m{15cm}|}{Returns successor of x. If x is largest element of set, returns nil.} \\\hline\hline
\verb!function Prev(x:PNode):PNode! & O(lg N) worst case, but traversal from largest element to
smallest takes O(N) time \\\hline
\multicolumn{2}{|m{15cm}|}{Returns predecessor of x. If x is smallest element of set, returns nil.} \\\hline\hline
\verb!function IsEmpty(): boolean! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns true when set is empty.} \\\hline
\end{longtable}

View File

@ -0,0 +1,24 @@
uses gset, gutil;
type lesslli=specialize TLess<longint>;
setlli=specialize TSet<longint, lesslli>;
var data:setlli; i:longint; iterator:setlli.PNode;
begin
data:=setlli.Create;
for i:=0 to 10 do
data.insert(i);
{Iteration through elements}
iterator:=data.Min;
while iterator<>nil do begin
writeln(iterator^.Data);
iterator:=data.next(iterator);
end;
writeln(data.FindLess(7)^.Data);
data.Destroy;
end.

View File

@ -0,0 +1,20 @@
uses garrayutils, gutil, gvector;
type vectorlli = specialize TVector<longint>;
lesslli = specialize TLess<longint>;
sortlli = specialize TOrderingArrayUtils<vectorlli, longint, lesslli>;
var data:vectorlli; n,i:longint;
begin
randomize;
data:=vectorlli.Create;
read(n);
for i:=1 to n do
data.pushback(random(1000000000));
sortlli.sort(data, data.size());
for i:=1 to n do
writeln(data[i-1]);
data.Destroy;
end.

View File

@ -0,0 +1,39 @@
\chapter{TStack}
Implements stack.
Usage example:
\lstinputlisting[language=Pascal]{stackexample.pp}
Memory complexity:
Since underlaying structure is TVector, memory complexity is same.
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!Create! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Constructor. Creates empty stack.} \\ \hline\hline
\verb!function Size(): SizeUInt! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns number of elements in stack.} \\\hline\hline
\verb!procedure Push(value: T)! & Amortized
O(1), some operations might take O(N) time, when array needs to be reallocated, but sequence of N
operations takes O(N) time \\ \hline
\multicolumn{2}{|m{15cm}|}{Inserts element on the top of stack.} \\\hline\hline
\verb!procedure Pop()! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Removes element from the top of stack. If stack is empty does nothing.} \\\hline\hline
\verb!function IsEmpty(): boolean! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns true when stack is empty} \\\hline\hline
\verb!function Top: T! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns top element from stack.} \\\hline
\end{longtable}

View File

@ -0,0 +1,17 @@
uses gstack;
type stacklli = specialize TStack<longint>;
var data:stacklli; i:longint;
begin
data:=stacklli.Create;
for i:=1 to 10 do
data.Push(10*i);
while not data.IsEmpty do begin
writeln(data.Top);
data.Pop;
end;
data.Destroy;
end.

View File

@ -0,0 +1,9 @@
\chapter{TLess, TGreater}
Comparators classes. Can be used in PriorityQueue and Sorting as comparator functions.
TLess is used for ordering from smallest element to largest, TGreater is used for oposite ordering.
%Usage example:
%\lstinputlisting[language=Pascal]{queueexample.pp}

View File

@ -0,0 +1,73 @@
\chapter{TVector}
Implements selfresizing array. Indexing is 0-based.
Usage example:
\lstinputlisting[language=Pascal]{vectorexample.pp}
Memory complexity:
Uses at most 3times bigger memory than maximal array size (this is only case during reallocation).
Normal consumption is at most twice as maximal array size.
Members list:
\begin{longtable}{|m{10cm}|m{5cm}|}
\hline
Method & Complexity guarantees \\ \hline
\multicolumn{2}{|m{15cm}|}{Description} \\ \hline\hline
\verb!Create! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Constructor. Creates empty array.} \\ \hline\hline
\verb!function Size(): SizeUInt! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns size of array.} \\\hline\hline
\verb!procedure PushBack(value: T)! & Amortized
O(1), some operations might take O(N) time, when array needs to be reallocated, but sequence of N
operations takes O(N) time \\ \hline
\multicolumn{2}{|m{15cm}|}{Inserts at the end of array (increases size by 1)} \\\hline\hline
\verb!procedure PopBack()! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Removes element from the end of array (decreases size by 1). When array
is empty, does nothing.} \\\hline\hline
\verb!function IsEmpty(): boolean! & O(1) \\ \hline
\multicolumn{2}{|m{15cm}|}{Returns true when array is empty} \\\hline\hline
\verb!procedure Insert(position: SizeUInt; value: T)! & O(N) \\\hline
\multicolumn{2}{|m{15cm}|}{Inserts value at position. When position is greater than size, puts value
at the end of array.} \\\hline\hline
\verb!procedure Erase(positine: SizeUInt; value: T)! & O(N) \\\hline
\multicolumn{2}{|m{15cm}|}{Erases element from position. When position is outside of array does
nothing.} \\\hline\hline
\verb!procedure Clear! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Clears array (set size to zero). But doesn't free memory used by array.}
\\\hline\hline
\verb!function Front: T! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns first element from array.} \\\hline\hline
\verb!function Back: T! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns last element from array.} \\\hline\hline
\verb!procedure Resize(num: SizeUInt)! & O(N) \\\hline
\multicolumn{2}{|m{15cm}|}{Changes size of array to num. Doesn't guarantte anything about value of
newly alocated elements.} \\\hline\hline
\verb!procedure Reserve(num: SizeUInt)! & O(N) \\\hline
\multicolumn{2}{|m{15cm}|}{Alocates at least num elements for array. Usefull when you want to
pushback big number of elements and want to avoid frequent reallocation.} \\\hline\hline
\verb!property item[i: SizeUInt]: T; default;! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Property for accessing i-th element in array. Can be used just by square
brackets (its default property).} \\\hline\hline
\verb!property mutable[i: SizeUInt]: T;! & O(1) \\\hline
\multicolumn{2}{|m{15cm}|}{Returns pointer to i-th element in array. Usefull when you store records.} \\\hline
\end{longtable}

View File

@ -0,0 +1,21 @@
uses gvector;
type TVectorlli = specialize TVector<longint>;
var Buffer:TVectorlli; i:longint;
begin
Buffer := TVectorlli.Create;
{Push 5 elements at the end of array}
for i:=1 to 5 do
Buffer.PushBack(i);
{change 3rd element to 47}
Buffer[2] := 47;
{pop last element}
Buffer.PopBack;
{print all elements}
for i:=0 to Buffer.Size-1 do
writeln(Buffer[i]);
Buffer.Destroy;
end.

View File

@ -0,0 +1,215 @@
{$mode objfpc}
unit garrayutils;
interface
const MaxDepth=60;
const InsertSortThreshold=16;
{TCompare is comparing class, which should have class method c(a,b:TValue):boolean, which returns true if a is less than b}
type
generic TOrderingArrayUtils<TArr, Tvalue, TCompare>=class
private
class procedure Sortrange(var Arr:TArr; Start,Fin,d:SizeUInt);
class procedure HeapSort(var Arr:TArr; Start,Fin:SizeUInt);
class procedure InsertSort(var Arr:TArr; Start,Fin:SizeUInt);
class function Left(a:SizeUInt):SizeUInt;inline;
class function Right(a:SizeUInt):SizeUInt;inline;
class procedure Heapify(var Arr: TArr; Position:SizeUInt; Start,Fin:SizeUInt);
class function Parent(a:SizeUInt):SizeUInt;inline;
public
class procedure Sort(var Arr: TArr; size:SizeUInt);
end;
generic TArrayUtils<TArr, Tvalue>=class
public
class procedure RandomShuffle(Arr: TArr; size: SizeUInt);
end;
implementation
class function TOrderingArrayUtils.Left(a:SizeUInt):SizeUInt;inline;
begin
Left:=((a+1)shl 1)-1;
end;
class function TOrderingArrayUtils.Right(a:SizeUInt):SizeUInt;inline;
begin
Right:=(a+1) shl 1;
end;
class function TOrderingArrayUtils.Parent(a:SizeUInt):SizeUInt;inline;
begin
Parent:=(a-1)shr 1;
end;
class procedure TOrderingArrayUtils.Heapify(var Arr: TArr; Position:SizeUInt; Start,Fin:SizeUInt);
var mpos,l,r:SizeUInt; temp:TValue;
begin
while(true) do
begin
mpos:=Position;
l:=Left(Position-Start)+Start;
r:=Right(Position-Start)+Start;
if (l<Fin) AND (TCompare.c(Arr[mpos],Arr[l])) then
mpos:=l;
if (r<Fin) AND (TCompare.c(Arr[mpos],Arr[r])) then
mpos:=r;
if mpos = Position then break;
temp:=Arr[Position];
Arr[Position]:=Arr[mpos];
Arr[mpos]:=temp;
Position:=mpos;
end;
end;
class procedure TOrderingArrayUtils.Sort(var Arr:TArr; size:SizeUInt);inline;
begin
Sortrange(Arr,0,size,0);
InsertSort(Arr,0,size);
end;
class procedure TOrderingArrayUtils.Sortrange(var Arr:TArr; Start,Fin,d:SizeUInt);
var pivot,temp:Tvalue; i,j,k,l:SizeUInt;
begin
if (Fin-Start) <= InsertSortThreshold then
begin
InsertSort(Arr,Start,Fin);
exit;
end;
if d>=maxdepth then
begin
HeapSort(Arr, Start, Fin);
exit;
end;
{median of 3}
j:=Start;
k:=Fin-1;
l:=(Start+Fin)div 2;
if(TCompare.c(Arr[j],Arr[k])) and (TCompare.c(Arr[j],Arr[l])) then
begin
if(TCompare.c(Arr[k],Arr[l])) then
begin
temp:=Arr[k];
Arr[k]:=Arr[j];
Arr[j]:=temp;
end else
begin
temp:=Arr[l];
Arr[l]:=Arr[j];
Arr[j]:=temp;
end;
end
else if(TCompare.c(Arr[k],Arr[j])) and (TCompare.c(Arr[l],Arr[j])) then
begin
if(TCompare.c(Arr[l],Arr[k])) then
begin
temp:=Arr[k];
Arr[k]:=Arr[j];
Arr[j]:=temp;
end else
begin
temp:=Arr[l];
Arr[l]:=Arr[j];
Arr[j]:=temp;
end;
end;
{partition}
pivot:=Arr[Start];
i:=Start-1;
j:=Fin;
repeat
repeat
dec(j);
until (not (TCompare.c(pivot,Arr[j])));
repeat
inc(i);
until (not (TCompare.c(Arr[i],pivot)));
if(i < j) then
begin
temp:=Arr[i];
Arr[i]:=Arr[j];
Arr[j]:=temp;
end;
until (i>=j);
Sortrange(Arr, Start, j+1, d+1);
Sortrange(Arr, j+1, Fin, d+1);
end;
class procedure TOrderingArrayUtils.InsertSort(var Arr:TArr; Start,Fin:SizeUInt);inline;
var i,j:SizeUInt; temp:Tvalue;
begin
for i:=Start+1 to Fin-1 do
begin
j:=i;
temp:=Arr[i];
while (j>0) and (TCompare.c(temp,Arr[j-1])) do
begin
Arr[j]:=Arr[j-1];
dec(j);
end;
Arr[j]:=temp;
end;
end;
class procedure TOrderingArrayUtils.HeapSort(var Arr: TArr; Start,Fin:SizeUInt);
var i,cur,next,l,r,size:SizeUInt; temp:Tvalue;
begin
{buildHeap}
size:=Fin-Start;
for i:=((size div 2)-1) downto 0 do
Heapify(Arr, i+Start, Start, Fin);
{bottomup HeapSort}
for i:=size-1 downto 1 do
begin
Fin:=Fin-1;
cur:=Start;
temp:=Arr[Start];
while(true) do
begin
l:=Left(cur-Start)+Start;
if l>=Fin then
break;
next:=l;
r:=Right(cur-Start)+Start;
if (r<Fin) AND (TCompare.c(Arr[l],Arr[r])) then
next:=r;
Arr[cur]:=Arr[next];
cur:=next;
end;
Arr[cur]:=temp;
temp:=Arr[i+Start];
Arr[i+Start]:=Arr[cur];
Arr[cur]:=temp;
l:=Parent(cur-Start)+Start;
while (cur <> 0) AND (TCompare.c(Arr[l],Arr[cur])) do
begin
temp:=Arr[cur];
Arr[cur]:=Arr[l];
Arr[l]:=temp;
cur:=l;
l:=Parent(cur-Start)+Start;
end;
end;
end;
class procedure TArrayUtils.RandomShuffle(Arr: TArr; size: SizeUInt);
var i,r:SizeUInt; temp:Tvalue;
begin
for i:=size-1 downto 1 do begin
r:=random(Int64(i));
temp:=Arr[r];
Arr[r]:=Arr[i];
Arr[i]:=temp;
end;
end;
end.

View File

@ -0,0 +1,192 @@
{$mode objfpc}
unit gdeque;
interface
type
generic TDeque<T>=class
private
type
PT=^T;
TArr=array of T;
var
FData:TArr;
FDataSize:SizeUInt;
FCapacity:SizeUInt;
FStart:SizeUInt;
procedure SetValue(position:SizeUInt; value:T);inline;
function GetValue(position:SizeUInt):T;inline;
function GetMutable(position:SizeUInt):PT;inline;
procedure IncreaseCapacity();inline;
public
function Size():SizeUInt;inline;
constructor Create();
procedure PushBack(value:T);inline;
procedure PushFront(value:T);inline;
procedure PopBack();inline;
procedure PopFront();inline;
function Front():T;inline;
function Back():T;inline;
function IsEmpty():boolean;inline;
procedure Reserve(cap:SizeUInt);inline;
procedure Resize(cap:SizeUInt);inline;
procedure Insert(Position:SizeUInt; Value:T);inline;
procedure Erase(Position:SIzeUInt);inline;
property Items[i : SizeUInt]: T read GetValue write SetValue; default;
property Mutable[i : SizeUInt]:PT read GetMutable;
end;
implementation
constructor TDeque.Create();
begin
FDataSize:=0;
FCapacity:=0;
FStart:=0;
end;
function TDeque.Size():SizeUInt;inline;
begin
Size:=FDataSize;
end;
function TDeque.IsEmpty():boolean;inline;
begin
if Size()=0 then
IsEmpty:=true
else
IsEmpty:=false;
end;
procedure TDeque.PushBack(value:T);inline;
begin
if(FDataSize=FCapacity) then
IncreaseCapacity;
FData[(FStart+FDataSize)mod FCapacity]:=value;
inc(FDataSize);
end;
procedure TDeque.PopFront();inline;
begin
if(FDataSize>0) then
begin
inc(FStart);
dec(FDataSize);
if(FStart=FCapacity) then
FStart:=0;
end;
end;
procedure TDeque.PopBack();inline;
begin
if(FDataSize>0) then
dec(FDataSize);
end;
procedure TDeque.PushFront(value:T);inline;
begin
if(FDataSize=FCapacity) then
IncreaseCapacity;
if(FStart=0) then
FStart:=FCapacity-1
else
dec(FStart);
FData[FStart]:=value;
inc(FDataSize);
end;
function TDeque.Front():T;inline;
begin
Assert(size > 0, 'Accessing empty deque');
Front:=FData[FStart];
end;
function TDeque.Back():T;inline;
begin
Assert(size > 0, 'Accessing empty deque');
Back:=FData[(FStart+FDataSize-1)mod FCapacity];
end;
procedure TDeque.SetValue(position:SizeUInt; value:T);inline;
begin
Assert(position < size, 'Deque access out of range');
FData[(FStart+position)mod FCapacity]:=value;
end;
function TDeque.GetValue(position:SizeUInt):T;inline;
begin
Assert(position < size, 'Deque access out of range');
GetValue:=FData[(FStart+position) mod FCapacity];
end;
function TDeque.GetMutable(position:SizeUInt):PT;inline;
begin
Assert(position < size, 'Deque access out of range');
GetMutable:=@FData[(FStart+position) mod FCapacity];
end;
procedure TDeque.IncreaseCapacity;inline;
var i,OldEnd:SizeUInt;
begin
OldEnd:=FCapacity;
if(FCapacity=0) then
FCapacity:=1
else
FCapacity:=FCapacity*2;
SetLength(FData, FCapacity);
if (FStart>0) then
for i:=0 to FStart-1 do
FData[OldEnd+i]:=FData[i];
end;
procedure TDeque.Reserve(cap:SizeUInt);inline;
var i,OldEnd:SizeUInt;
begin
if(cap<FCapacity) then
exit
else if(cap<=2*FCapacity) then
IncreaseCapacity
else
begin
OldEnd:=FCapacity;
FCapacity:=cap;
SetLength(FData, FCapacity);
if FStart > 0 then
for i:=0 to FStart-1 do
FData[OldEnd+i]:=FData[i];
end;
end;
procedure TDeque.Resize(cap:SizeUInt);inline;
begin
Reserve(cap);
FDataSize:=cap;
end;
procedure TDeque.Insert(Position:SizeUInt; Value: T);inline;
var i:SizeUInt;
begin
pushBack(Value);
for i:=Size-1 downto Position+1 do
begin
Items[i]:=Items[i-1];
end;
Items[Position]:=Value;
end;
procedure TDeque.Erase(Position:SizeUInt);inline;
var i:SizeUInt;
begin
if Position <= Size then
begin
for i:=Position to Size-2 do
begin
Items[i]:=Items[i+1];
end;
popBack();
end;
end;
end.

View File

@ -0,0 +1,72 @@
{$mode objfpc}
{unit ghashset;
interface}
uses gvector;
const baseSize = 8;
{Thash should have one class function hash(a:T, n:longint):longint which return uniformly distributed
value in range <0,n-1> base only on arguments}
type
generic hashset<T, Thash>=class
private type TContainer = specialize vector<T>;
type TTable = specialize vector<TContainer>;
var data:TTable;
public constructor create;
procedure insert(value:T);inline;
function find(value:T):boolean;inline;
end;
{implementation}
constructor hashset.create;
var i:longint;
begin
data:=TTable.create;
data.resize(8);
for i:=0 to 7 do
data[i]:=TContainer.create;
end;
function hashset.find(value:T):boolean;inline;
var i,h,bs:longint;
begin
h:=Thash.hash(value,data.size);
bs:=data.getValue(h).size;
for i:=0 to bs-1 do begin
if (data.getvalue(h).getvalue(i)=value) then exit(true);
end;
exit(false);
end;
procedure hashset.insert(value:T);inline;
begin
if (find(value)) then exit;
(data[Thash.hash(value,data.size)]).pushback(value);
end;
type hint=class
class function hash(a,n:longint):longint;
end;
class function hint.hash(a,n:longint):longint;
begin
hash:= a mod n;
end;
type hsli = specialize hashset<longint, hint>;
var data:hsli; i,n:longint;
begin
data:=hsli.create;
for i:=0 to 10 do
data.insert(i);
for i:=0 to 13 do
writeln(data.find(i));
end.

View File

@ -0,0 +1,151 @@
{$mode objfpc}
unit gmap;
interface
uses gset;
type
generic TMapCompare<TPair, TKeyCompare>=class
class function c(a,b :TPair):boolean;
end;
generic TMap<TKey, TValue, TCompare>=class
public
type
TPair=record
Key:TKey;
Value:TValue;
end;
TMCompare = specialize TMapCompare<TPair, TCompare>;
TMSet = specialize TSet<TPair, TMCompare>;
PTValue = ^TValue;
PTPair = ^TPair;
var
private
FSet:TMSet;
public
function Find(key:TKey):TMSet.PNode;inline;
function FindLess(key:TKey):TMSet.PNode;inline;
function FindLessEqual(key:TKey):TMSet.PNode;inline;
function FindGreater(key:TKey):TMSet.PNode;inline;
function FindGreaterEqual(key:TKey):TMSet.PNode;inline;
function GetValue(key:TKey):TValue;inline;
procedure Insert(key:TKey; value:TValue);inline;
function Min:TMSet.PNode;inline;
function Max:TMSet.PNode;inline;
function Next(x:TMSet.PNode):TMSet.PNode;inline;
function Prev(x:TMSet.PNode):TMSet.PNode;inline;
procedure Delete(key:TKey);inline;
function Size:SizeUInt;inline;
function IsEmpty:boolean;inline;
constructor Create;
destructor Destroy;override;
property Items[i : TKey]: TValue read GetValue write Insert; default;
end;
implementation
class function TMapCompare.c(a,b: TPair):boolean;
begin
c:= TKeyCompare.c(a.Key, b.Key);
end;
constructor TMap.Create;
begin
FSet:=TMSet.Create;
end;
destructor TMap.Destroy;
begin
FSet.Destroy;
end;
procedure TMap.Delete(key:TKey);inline;
var Pair:TPair;
begin
Pair.Key:=key;
FSet.Delete(Pair);
end;
function TMap.Find(key:TKey):TMSet.PNode;inline;
var Pair:TPair;
begin
Pair.Key:=key;
Find:=FSet.Find(Pair);
end;
function TMap.FindLess(key:TKey):TMSet.PNode;inline;
var Pair:TPair;
begin
Pair.Key:=key;
FindLess:=FSet.FindLess(Pair);
end;
function TMap.FindLessEqual(key:TKey):TMSet.PNode;inline;
var Pair:TPair;
begin
Pair.Key:=key;
FindLessEqual:=FSet.FindLessEqual(Pair);
end;
function TMap.FindGreater(key:TKey):TMSet.PNode;inline;
var Pair:TPair;
begin
Pair.Key:=key;
FindGreater:=FSet.FindGreater(Pair);
end;
function TMap.FindGreaterEqual(key:TKey):TMSet.PNode;inline;
var Pair:TPair;
begin
Pair.Key:=key;
FindGreaterEqual:=FSet.FindGreaterEqual(Pair);
end;
function TMap.GetValue(key:TKey):TValue;inline;
var Pair:TPair;
begin
Pair.Key:=key;
GetValue:=FSet.Find(Pair)^.Data.Value;
end;
procedure TMap.Insert(key:TKey; value:TValue);inline;
var Pair:TPair;
begin
Pair.Key:=key;
FSet.Insert(Pair)^.Data.Value := value;
end;
function TMap.Min:TMSet.PNode;inline;
begin
Min:=FSet.Min;
end;
function TMap.Max:TMSet.PNode;inline;
begin
Max:=FSet.Max;
end;
function TMap.Next(x:TMSet.PNode):TMSet.PNode;inline;
begin
Next:=FSet.Next(x);
end;
function TMap.Prev(x:TMSet.PNode):TMSet.PNode;inline;
begin
Prev:=FSet.Prev(x);
end;
function TMap.Size:SizeUInt;inline;
begin
Size:=FSet.Size;
end;
function TMap.IsEmpty:boolean;inline;
begin
IsEmpty:=FSet.IsEmpty;
end;
end.

View File

@ -0,0 +1,129 @@
{$mode objfpc}
unit gpriorityqueue;
interface
uses gvector;
{TCompare is comparing class, which should have class method c(a,b:T):boolean, which returns true is a is less than b}
type
generic TPriorityQueue<T, TCompare>=class
private
type
TContainer=specialize TVector<T>;
var
FData:TContainer;
procedure PushUp(position:SizeUInt);
function Left(a:SizeUInt):SizeUInt;inline;
function Right(a:SizeUInt):SizeUInt;inline;
procedure Heapify(position:SizeUInt);
function Parent(a:SizeUInt):SizeUInt;inline;
public
constructor Create;
destructor Destroy;override;
function Top:T;inline;
procedure Pop;inline;
procedure Push(value:T);inline;
function Size:SizeUInt;inline;
function IsEmpty:boolean;inline;
end;
implementation
constructor TPriorityQueue.Create;
begin
FData:=TContainer.Create;
end;
destructor TPriorityQueue.Destroy;
begin;
FData.Destroy;
end;
function TPriorityQueue.Size:SizeUInt;inline;
begin
Size:=FData.Size;
end;
function TPriorityQueue.IsEmpty:boolean;inline;
begin
IsEmpty:=FData.Size=0;
end;
function TPriorityQueue.Top:T;inline;
begin
Top:=FData[0];
end;
procedure TPriorityQueue.Pop;inline;
begin
if not IsEmpty then begin
FData[0]:=FData.back;
FData.PopBack;
Heapify(0);
end;
end;
procedure TPriorityQueue.PushUp(position:SizeUInt);
var np:SizeUInt; temp:T;
begin
while(position>0) do
begin
np := Parent(position);
if(TCompare.c(FData[np],FData[position])) then
begin
temp:=FData[np];
FData[np]:=FData[position];
FData[position]:=temp;
position:=np;
end else
break;
end;
end;
procedure TPriorityQueue.Push(value:T);inline;
begin
FData.PushBack(value);
PushUp(FData.Size-1);
end;
function TPriorityQueue.Left(a:SizeUInt):SizeUInt;inline;
begin
Left:=((a+1)shl 1)-1;
end;
function TPriorityQueue.Right(a:SizeUInt):SizeUInt;inline;
begin
Right:=(a+1) shl 1;
end;
function TPriorityQueue.Parent(a:SizeUInt):SizeUInt;inline;
begin
Parent:=(a-1)shr 1;
end;
procedure TPriorityQueue.Heapify(position:SizeUInt);
var mpos,l,r:SizeUInt; temp:T;
begin
while(true) do
begin
mpos:=position;
l:=Left(position);
r:=Right(position);
if (l<FData.Size) AND (TCompare.c(FData[mpos],FData[l])) then
mpos:=l;
if (r<FData.Size) AND (TCompare.c(FData[mpos],FData[r])) then
mpos:=r;
if mpos = position then break;
temp:=FData[position];
FData[position]:=FData[mpos];
FData[mpos]:=temp;
position:=mpos;
end;
end;
end.

View File

@ -0,0 +1,63 @@
{$mode objfpc}
unit gqueue;
interface
uses gdeque;
type
generic TQueue<T>=class
private
type
TContainer = specialize TDeque<T>;
var
FData:TContainer;
public
procedure Push(value:T);inline;
procedure Pop();inline;
function Front():T;inline;
function Size():SizeUInt;inline;
function IsEmpty():boolean;inline;
constructor Create;
destructor Destroy;override;
end;
implementation
constructor TQueue.Create;
begin
FData:=TContainer.Create;
end;
destructor TQueue.Destroy;
begin
FData.Destroy;
end;
procedure TQueue.Push(value:T);inline;
begin
FData.PushBack(value);
end;
procedure TQueue.Pop();inline;
begin
FData.PopFront;
end;
function TQueue.Front:T;inline;
begin
Front:=FData.Front;
end;
function TQueue.Size:SizeUInt;inline;
begin
Size:=FData.Size;
end;
function TQueue.IsEmpty:boolean;inline;
begin
IsEmpty:=FData.IsEmpty;
end;
end.

View File

@ -0,0 +1,411 @@
{$mode objfpc}
unit gset;
interface
const RED=true;
const BLACK=false;
type
generic TSet<T, TCompare>=class
public
type
PNode=^Node;
Node=record
Data:T;
Left,Right:PNode;
Parent:PNode;
Color:boolean;
end;
var
private
FBase:PNode;
FSize:SizeUInt;
function CreateNode(Data:T):PNode;inline;
procedure DestroyNodeAndChilds(nod:PNode);
procedure DestroyNode(nod:PNode);
function RotateRight(nod:PNode):PNode;inline;
function RotateLeft(nod:PNode):PNode;inline;
procedure FlipColors(nod:PNode);inline;
function IsRed(nod:PNode):boolean;inline;
function Insert(value:T; nod:PNode; var position:PNode):PNode;
function FixUp(nod:PNode):PNode;inline;
function MoveRedLeft(nod:PNode):PNode;inline;
function MoveRedRight(nod:PNode):PNode;inline;
function DeleteMin(nod:PNode):PNode;
function Delete(value:T; nod:PNode):PNode;
function Min(nod:PNode):PNode;inline;
public
function Find(value:T):PNode;inline;
function FindLess(value:T):PNode;inline;
function FindLessEqual(value:T):PNode;inline;
function FindGreater(value:T):PNode;inline;
function FindGreaterEqual(value:T):PNode;inline;
function Insert(value:T):PNode;inline;
function Min:PNode;inline;
function Max:PNode;inline;
function Next(x:PNode):PNode;inline;
function Prev(x:PNode):PNode;inline;
procedure Delete(value:T);inline;
public constructor Create;
public destructor Destroy;override;
function Size:SizeUInt;
function IsEmpty:boolean;
end;
implementation
constructor TSet.Create;
begin
FBase:=nil;
FSize:=0;
end;
destructor TSet.Destroy;
begin
DestroyNodeAndChilds(FBase);
end;
function TSet.Size:SizeUInt;
begin
Size:=FSize;
end;
function TSet.IsEmpty:boolean;
begin
IsEmpty := FSize=0;
end;
procedure TSet.DestroyNodeAndChilds(nod:PNode);
begin
if nod = nil then exit;
DestroyNodeAndChilds(nod^.left);
DestroyNodeAndChilds(nod^.right);
DestroyNode(nod);
end;
procedure TSet.DestroyNode(nod:PNode);
begin
Finalize(nod^.Data);
dispose(nod);
dec(FSize);
end;
function TSet.CreateNode(Data:T):PNode;inline;
var temp:PNode;
begin
temp:=new(PNode);
Initialize(temp^.Data);
temp^.Data:=Data;
temp^.Left:=nil;
temp^.Right:=nil;
temp^.Parent:=nil;
temp^.Color:=RED;
inc(FSize);
CreateNode:=temp;
end;
function TSet.RotateRight(nod:PNode):PNode;inline;
var temp:PNode;
begin
temp:=nod^.Left;
temp^.Parent:=nod^.Parent;
nod^.Parent:=temp;
nod^.Left:=temp^.Right;
temp^.Right:=nod;
if(nod^.Left<>nil) then nod^.Left^.Parent:=nod;
temp^.Color:=nod^.Color;
nod^.Color:=RED;
exit(temp);
end;
function TSet.RotateLeft(nod:PNode):PNode;inline;
var temp:PNode;
begin
temp:=nod^.Right;
temp^.Parent:=nod^.Parent;
nod^.Parent:=temp;
nod^.Right:=temp^.Left;
temp^.Left:=nod;
if(nod^.Right<>nil) then nod^.Right^.Parent:=nod;
temp^.Color:=nod^.Color;
nod^.Color:=RED;
exit(temp);
end;
procedure TSet.FlipColors(nod:PNode);inline;
begin
nod^.Color:= not nod^.Color;
nod^.Left^.Color := not nod^.Left^.Color;
nod^.Right^.Color := not nod^.Right^.Color;
end;
function TSet.FixUp(nod:PNode):PNode;inline;
begin
if(IsRed(nod^.Right)) and (not IsRed(nod^.Left)) then nod := rotateLeft(nod);
if(IsRed(nod^.Left)) and (IsRed(nod^.Left^.Left)) then nod := rotateRight(nod);
if(IsRed(nod^.Right)) and (IsRed(nod^.Left)) then flipColors(nod);
FixUp:=nod;
end;
function TSet.MoveRedLeft(nod:PNode):PNode;inline;
begin
flipColors(nod);
if (IsRed(nod^.Right^.Left)) then begin
nod^.Right := rotateRight(nod^.Right);
nod := rotateLeft(nod);
flipColors(nod);
end;
MoveRedLeft:=nod;
end;
function TSet.MoveRedRight(nod:PNode):PNode;inline;
begin
flipColors(nod);
if (IsRed(nod^.Left^.Left)) then begin
nod := rotateRight(nod);
flipColors(nod);
end;
MoveRedRight:=nod;
end;
function TSet.DeleteMin(nod:PNode):PNode;
begin
if (nod^.Left = nil) then begin
DestroyNode(nod);
exit(nil);
end;
if ((not IsRed(nod^.Left)) and (not IsRed(nod^.Left^.Left))) then nod := MoveRedLeft(nod);
nod^.Left := DeleteMin(nod^.Left);
exit(FixUp(nod));
end;
function TSet.Delete(value:T; nod:PNode):PNode;
begin
if (TCompare.c(value, nod^.Data)) then begin
if (nod^.Left=nil) then exit(nod);
if ((not IsRed(nod^.Left)) and ( not IsRed(nod^.Left^.Left))) then
nod := MoveRedLeft(nod);
nod^.Left := Delete(value, nod^.Left);
end
else begin
if (IsRed(nod^.Left)) then begin
nod := rotateRight(nod);
end;
if ((not TCompare.c(value,nod^.Data)) and (not TCompare.c(nod^.Data,value)) and (nod^.Right = nil)) then
begin
DestroyNode(nod);
exit(nil);
end;
if (nod^.Right=nil) then exit(nod);
if ((not IsRed(nod^.Right)) and (not IsRed(nod^.Right^.Left))) then nod := MoveRedRight(nod);
if ((not TCompare.c(value,nod^.Data)) and (not TCompare.c(nod^.Data,value))) then begin
nod^.Data := Min(nod^.Right)^.Data;
nod^.Right := DeleteMin(nod^.Right);
end
else nod^.Right := Delete(value, nod^.Right);
end;
exit(FixUp(nod));
end;
procedure TSet.Delete(value:T);inline;
begin
if(FBase<>nil) then FBase:=Delete(value, FBase);
if(FBase<>nil) then FBase^.Color:=BLACK;
end;
function TSet.Find(value:T):PNode;inline;
var x:PNode;
begin
x:=FBase;
while(x <> nil) do begin
if(TCompare.c(value,x^.Data)) then x:=x^.Left
else if(TCompare.c(x^.Data,value)) then x:=x^.Right
else exit(x);
end;
exit(nil);
end;
function TSet.FindLess(value:T):PNode;inline;
var x,cur:PNode;
begin
x:=nil;
cur:=FBase;
while (cur <> nil) do begin
if (TCompare.c(cur^.Data, value)) then
begin
x:=cur;
cur:=cur^.right;
end else
cur:=cur^.left;
end;
FindLess:=x;
end;
function TSet.FindLessEqual(value:T):PNode;inline;
var x,cur:PNode;
begin
x:=nil;
cur:=FBase;
while (cur <> nil) do begin
if (not TCompare.c(value, cur^.data)) then
begin
x:=cur;
cur:=cur^.right;
end else
cur:=cur^.left;
end;
FindLessEqual:=x;
end;
function TSet.FindGreater(value:T):PNode;inline;
var x,cur:PNode;
begin
x:=nil;
cur:=FBase;
while (cur <> nil) do begin
if (TCompare.c(value, cur^.Data)) then
begin
x:=cur;
cur:=cur^.left;
end else
cur:=cur^.right;
end;
FindGreater:=x;
end;
function TSet.FindGreaterEqual(value:T):PNode;inline;
var x,cur:PNode;
begin
x:=nil;
cur:=FBase;
while (cur <> nil) do begin
if (not TCompare.c(cur^.Data, value)) then
begin
x:=cur;
cur:=cur^.left;
end else
cur:=cur^.right;
end;
FindGreaterEqual:=x;
end;
function TSet.Insert(value:T):PNode;inline;
var position:PNode;
begin
FBase:=Insert(value, FBase, position);
FBase^.Color:=BLACK;
Insert:=position;
end;
function TSet.Insert(value:T; nod:PNode; var position:PNode):PNode;
begin
if(nod=nil) then begin
nod:=CreateNode(value);
position:=nod;
exit(nod);
end;
if(TCompare.c(value,nod^.Data)) then begin
nod^.Left:=Insert(value, nod^.Left, position);
nod^.Left^.Parent:=nod;
end
else if TCompare.c(nod^.Data,value) then begin
nod^.Right:=Insert(value, nod^.Right, position);
nod^.Right^.Parent:=nod;
end
else begin
position:=nod;
exit(nod);
end;
if(IsRed(nod^.Right)) and (not IsRed(nod^.Left)) then nod := rotateLeft(nod);
if(IsRed(nod^.Left)) and (IsRed(nod^.Left^.Left)) then nod := rotateRight(nod);
if(IsRed(nod^.Right)) and (IsRed(nod^.Left)) then flipColors(nod);
Insert:=nod;
end;
function TSet.IsRed(nod:PNode):boolean;inline;
begin
if(nod=nil) then exit(false);
exit(nod^.Color);
end;
function TSet.Min(nod:PNode):PNode;inline;
var temp:PNode;
begin
temp:=nod;
while(temp^.Left<>nil) do temp:=temp^.Left;
exit(temp);
end;
function TSet.Min:PNode;inline;
begin
if FBase=nil then exit(nil);
Min:=Min(FBase);
end;
function TSet.Max:PNode;inline;
var temp:PNode;
begin
if FBase=nil then exit(nil);
temp:=FBase;
while(temp^.Right<>nil) do temp:=temp^.Right;
exit(temp);
end;
function TSet.Next(x:PNode):PNode;inline;
var temp:PNode;
begin
if(x=nil) then exit(nil);
if(x^.Right<>nil) then begin
temp:=x^.Right;
while(temp^.Left<>nil) do temp:=temp^.Left;
end
else begin
temp:=x;
while(true) do begin
if(temp^.Parent=nil) then begin temp:=temp^.Parent; break; end;
if(temp^.Parent^.Left=temp) then begin temp:=temp^.Parent; break; end;
temp:=temp^.Parent;
end;
end;
exit(temp);
end;
function TSet.Prev(x:PNode):PNode;inline;
var temp:PNode;
begin
if(x=nil) then exit(nil);
if(x^.Left<>nil) then begin
temp:=x^.Left;
while(temp^.Right<>nil) do temp:=temp^.Right;
end
else begin
temp:=x;
while(true) do begin
if(temp^.Parent=nil) then begin temp:=temp^.Parent; break; end;
if(temp^.Parent^.Right=temp) then begin temp:=temp^.Parent; break; end;
temp:=temp^.Parent;
end;
end;
exit(temp);
end;
end.

View File

@ -0,0 +1,61 @@
{$mode objfpc}
unit gstack;
interface
uses gvector;
type
generic TStack<T>=class
private
type TContainer= specialize TVector<T>;
var FData:TContainer;
public
procedure Push(x:T);inline;
procedure Pop();inline;
function Top():T;inline;
function Size():longint;inline;
function IsEmpty():boolean;inline;
constructor Create;
destructor Destroy;override;
end;
implementation
constructor TStack.Create;
begin
FData:=TContainer.Create;
end;
destructor TStack.Destroy;
begin
FData.Destroy;
end;
procedure TStack.Push(x:T);inline;
begin
FData.PushBack(x);
end;
procedure TStack.Pop;inline;
begin
FData.PopBack;
end;
function TStack.Top:T;inline;
begin
Top:=FData.Back;
end;
function TStack.Size:longint;inline;
begin
Size:=FData.Size;
end;
function TStack.IsEmpty:boolean;inline;
begin
IsEmpty:=FData.IsEmpty;
end;
end.

View File

@ -0,0 +1,27 @@
{$mode objfpc}
unit gutil;
interface
type generic TLess<T>=class
class function c(a,b:T):boolean;inline;
end;
type generic TGreater<T>=class
class function c(a,b:T):boolean;inline;
end;
implementation
class function TLess.c(a,b:T):boolean;inline;
begin
c:=a<b;
end;
class function TGreater.c(a,b:T):boolean;inline;
begin
c:=b<a;
end;
end.

View File

@ -0,0 +1,161 @@
{$mode objfpc}
unit gvector;
interface
type
generic TVector<T>=class
private
type
PT=^ T;
TArr=array of T;
var
FCapacity:SizeUInt;
FDataSize:SizeUInt;
FData:TArr;
procedure SetValue(Position:SizeUInt; Value:T);inline;
function GetValue(Position:SizeUInt):T;inline;
function GetMutable(Position:SizeUInt):PT;inline;
procedure IncreaseCapacity;inline;
public
constructor Create;
function Size:SizeUInt;inline;
procedure PushBack(Value:T);inline;
procedure PopBack;inline;
function IsEmpty:boolean;inline;
procedure Insert(Position:SizeUInt; Value:T);inline;
procedure Erase(Position:SizeUInt);inline;
procedure Clear;inline;
function Front:T;inline;
function Back:T;inline;
procedure Reserve(Num:SizeUInt);inline;
procedure Resize(Num:SizeUInt);inline;
property Items[i : SizeUInt]: T read getValue write setValue; default;
property Mutable[i : SizeUInt]: PT read getMutable;
end;
implementation
constructor TVector.Create();
begin
FCapacity:=0;
FDataSize:=0;
end;
procedure TVector.SetValue(Position:SizeUInt; Value:T);inline;
begin
Assert(position < size, 'Vector position out of range');
FData[Position]:=Value;
end;
function TVector.GetValue(Position:SizeUInt):T;inline;
begin
Assert(position < size, 'Vector position out of range');
GetValue:=FData[Position];
end;
function TVector.GetMutable(Position:SizeUInt):PT;inline;
begin
Assert(position < size, 'Vector position out of range');
GetMutable:=@FData[Position];
end;
function TVector.Front():T;inline;
begin
Assert(size > 0, 'Accessing element of empty vector');
Front:=FData[0];
end;
function TVector.Back():T;inline;
begin
Assert(size > 0, 'Accessing element of empty vector');
Back:=FData[FDataSize-1];
end;
function TVector.Size():SizeUInt;inline;
begin
Size:=FDataSize;
end;
function TVector.IsEmpty():boolean;inline;
begin
if Size()=0 then
IsEmpty:=true
else
IsEmpty:=false;
end;
procedure TVector.PushBack(Value:T);inline;
begin
if FDataSize=FCapacity then
IncreaseCapacity;
FData[FDataSize]:=Value;
inc(FDataSize);
end;
procedure TVector.IncreaseCapacity();inline;
begin
if FCapacity=0 then
FCapacity:=1
else
FCapacity:=FCapacity*2;
SetLength(FData, FCapacity);
end;
procedure TVector.PopBack();inline;
begin
if FDataSize>0 then
FDataSize:=FDataSize-1;
end;
procedure TVector.Insert(Position:SizeUInt; Value: T);inline;
var i:SizeUInt;
begin
pushBack(Value);
for i:=Size-1 downto Position+1 do
begin
FData[i]:=FData[i-1];
end;
FData[Position]:=Value;
end;
procedure TVector.Erase(Position:SizeUInt);inline;
var i:SizeUInt;
begin
if Position <= Size then
begin
for i:=Position to Size-2 do
begin
FData[i]:=FData[i+1];
end;
popBack();
end;
end;
procedure TVector.Clear;inline;
begin
FDataSize:=0;
end;
procedure TVector.Reserve(Num:SizeUInt);inline;
begin
if(Num < FCapacity) then
exit
else if(Num <= 2*FCapacity) then
IncreaseCapacity
else begin
SetLength(FData, Num);
FCapacity:=Num;
end;
end;
procedure TVector.Resize(Num:SizeUInt);inline;
begin
Reserve(Num);
FDataSize:=Num;
end;
end.

2
packages/fcl-stl/tests/clean Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
rm *.o *.ppu ../*.o ../*.ppu

View File

@ -0,0 +1,55 @@
{$mode objfpc}
unit gdequetest;
interface
uses fpcunit, testregistry, gdeque;
type dequelli=specialize TDeque<longint>;
type TGDequeTest = class(TTestCase)
Published
procedure BackTest;
procedure PushTest;
public
procedure Setup;override;
private
data:dequelli;
end;
implementation
procedure TGDequeTest.BackTest;
var i:longint;
begin
AssertEquals('Not IsEmpty', true, data.IsEmpty);
for i:=0 to 10 do
data.pushback(i);
for i:=0 to 10 do begin
AssertEquals('Wrong data', 10-i, data.back);
AssertEquals('Wrong size', 11-i, data.size);
data.popback;
end;
AssertEquals('Not IsEmpty', true, data.IsEmpty);
end;
procedure TGDequeTest.PushTest;
var i:longint;
begin
for i:=6 to 10 do
data.pushBack(i);
for i:=5 downto 0 do
data.pushFront(i);
for i:=0 to 10 do
AssertEquals('Wrong data', i, data[i]);
end;
procedure TGDequeTest.Setup;
begin
data:=dequelli.create;
end;
initialization
RegisterTest(TGDequeTest);
end.

View File

@ -0,0 +1,84 @@
{$mode objfpc}
unit gmaptest;
interface
uses fpcunit, testregistry, gmap, gutil;
type lesslli=specialize TLess<longint>;
maplli=specialize TMap<longint,longint, lesslli>;
type TGMapTest = class(TTestCase)
Published
procedure MapTest;
public
procedure Setup;override;
private
data:maplli;
end;
implementation
procedure TGMapTest.MapTest;
var it:maplli.TMSet.pnode;
begin
data[3]:=3;
data[5]:=5;
data[7]:=7;
AssertEquals('Wrong min key', 3, data.min()^.data.key);
AssertEquals('Wrong max key', 7, data.max()^.data.key);
AssertEquals('Wrong min val', 3, data.min()^.data.value);
AssertEquals('Wrong max val', 7, data.max()^.data.value);
AssertEquals('Wrong val', 5, data[5]);
data.delete(3);
AssertEquals('Wrong min key', 5, data.min()^.data.key);
AssertEquals('Wrong max key', 7, data.max()^.data.key);
AssertEquals('Wrong min val', 5, data.min()^.data.value);
AssertEquals('Wrong max val', 7, data.max()^.data.value);
data[3]:=3;
data[3]:=47;
AssertEquals('Wrong val 2', 47, data[3]);
if(data.find(4)<>nil) then
AssertEquals('Found key which not there', 0, 1);
data[17]:=42;
it:=data.min;
AssertEquals('Wrong min', 3, it^.Data.key);
it:=data.next(it);
AssertEquals('Wrong next', 5, it^.Data.key);
it:=data.next(it);
AssertEquals('Wrong next', 7, it^.Data.key);
it:=data.next(it);
AssertEquals('Wrong next', 17, it^.Data.key);
it:=data.next(it);
if(it<>nil) then
AssertEquals('Last not nil', 0, 1);
it:=data.max;
AssertEquals('Wrong max', 17, it^.Data.key);
it:=data.prev(it);
AssertEquals('Wrong prev', 7, it^.Data.key);
it:=data.prev(it);
AssertEquals('Wrong prev', 5, it^.Data.key);
it:=data.prev(it);
AssertEquals('Wrong prev', 3, it^.Data.key);
it:=data.prev(it);
if(it<>nil) then
AssertEquals('First not nil', 0, 1);
end;
procedure TGMapTest.Setup;
begin
data:=maplli.create;
end;
initialization
RegisterTest(TGMapTest);
end.

View File

@ -0,0 +1,84 @@
{$mode objfpc}
unit gmaptest;
interface
uses fpcunit, testregistry, gmap, gutil;
type lesslli=specialize TLess<longint>;
maplli=specialize TMap<longint,longint, lesslli>;
type TGMapTest = class(TTestCase)
Published
procedure MapTest;
public
procedure Setup;override;
private
data:maplli;
end;
implementation
procedure TGMapTest.MapTest;
var it:maplli.TMSet.pnode;
begin
data[3]:=3;
data[5]:=5;
data[7]:=7;
AssertEquals('Wrong min key', 3, data.min()^.key);
AssertEquals('Wrong max key', 7, data.max()^.key);
AssertEquals('Wrong min val', 3, data.min()^.value);
AssertEquals('Wrong max val', 7, data.max()^.value);
AssertEquals('Wrong val', 5, data[5]);
data.delete(3);
AssertEquals('Wrong min key', 5, data.min()^.key);
AssertEquals('Wrong max key', 7, data.max()^.key);
AssertEquals('Wrong min val', 5, data.min()^.value);
AssertEquals('Wrong max val', 7, data.max()^.value);
data[3]:=3;
data[3]:=47;
AssertEquals('Wrong val 2', 47, data[3]);
if(data.find(4)<>nil) then
AssertEquals('Found key which not there', 0, 1);
data[17]:=42;
it:=data.min;
AssertEquals('Wrong min', 3, it^.key);
it:=data.next(it);
AssertEquals('Wrong next', 5, it^.key);
it:=data.next(it);
AssertEquals('Wrong next', 7, it^.key);
it:=data.next(it);
AssertEquals('Wrong next', 17, it^.key);
it:=data.next(it);
if(it<>nil) then
AssertEquals('Last not nil', 0, 1);
it:=data.max;
AssertEquals('Wrong max', 17, it^.key);
it:=data.prev(it);
AssertEquals('Wrong prev', 7, it^.key);
it:=data.prev(it);
AssertEquals('Wrong prev', 5, it^.key);
it:=data.prev(it);
AssertEquals('Wrong prev', 3, it^.key);
it:=data.prev(it);
if(it<>nil) then
AssertEquals('First not nil', 0, 1);
end;
procedure TGMapTest.Setup;
begin
data:=maplli.create;
end;
initialization
RegisterTest(TGMapTest);
end.

View File

@ -0,0 +1,47 @@
{$mode objfpc}
unit gpriorityqueuetest;
interface
uses fpcunit, testregistry, gpriorityqueue, gutil;
type lesslli=specialize TLess<longint>;
queuelli=specialize TPriorityQueue<longint,lesslli>;
type TGPQueueTest = class(TTestCase)
Published
procedure QueueTest;
public
procedure Setup;override;
private
data:queuelli;
end;
implementation
procedure TGPQueueTest.QueueTest;
var i,last:longint;
begin
AssertEquals('Not IsEmpty', true, data.IsEmpty);
for i:=0 to 10 do
data.push(random(10000));
last:=data.top;
data.pop;
for i:=0 to 9 do begin
AssertEquals('Wrong order', true, data.top<last);
AssertEquals('Wrong size', 10-i, data.size);
last:=data.top;
data.pop;
end;
AssertEquals('Not IsEmpty', true, data.IsEmpty);
end;
procedure TGPQueueTest.Setup;
begin
data:=queuelli.create;
end;
initialization
RegisterTest(TGPQueueTest);
end.

View File

@ -0,0 +1,43 @@
{$mode objfpc}
unit gqueuetest;
interface
uses fpcunit, testregistry, gqueue;
type TQueuelli=specialize TQueue<longint>;
type TGTQueueTest = class(TTestCase)
Published
procedure TQueueTest;
public
procedure Setup;override;
private
data:TQueuelli;
end;
implementation
procedure TGTQueueTest.TQueueTest;
var i:longint;
begin
AssertEquals('Not IsEmpty', true, data.IsEmpty);
for i:=0 to 10 do
data.push(i);
for i:=0 to 10 do begin
AssertEquals('Wrong data', i, data.front);
AssertEquals('Wrong size', 11-i, data.size);
data.pop;
end;
AssertEquals('Not IsEmpty', true, data.IsEmpty);
end;
procedure TGTQueueTest.Setup;
begin
data:=TQueuelli.create;
end;
initialization
RegisterTest(TGTQueueTest);
end.

View File

@ -0,0 +1,59 @@
{$mode objfpc}
unit gsetrefcounttest;
interface
uses fpcunit, testregistry, gset, gutil;
type
arr = class
a:longint;
end;
lll=class
class function c(a,b: arr):boolean;
end;
type setlli=specialize RBSet<arr,lll>;
type TGSetRefCountTest = class(TTestCase)
Published
procedure SetTest;
public
procedure Setup;override;
private
data:setlli;
end;
implementation
class function lll.c(a,b: arr):boolean;
begin
c:=a.a<b.a;
end;
procedure TGSetRefCountTest.SetTest;
var x:arr; i:longint;
it:setlli.pnode;
begin
for i:=0 to 20000 do begin
x:=arr.create;
x.a:=i;
{code should crash on this insert}
data.insert(x);
end;
it:=data.min;
while it<>nil do begin
writeln(it^.data.a);
it:=data.next(it);
end;
end;
procedure TGSetRefCountTest.Setup;
begin
data:=setlli.create;
end;
initialization
RegisterTest(TGSetRefCountTest);
end.

View File

@ -0,0 +1,110 @@
{$mode objfpc}
unit gsettest;
interface
uses fpcunit, testregistry, gset, gutil;
type lesslli=specialize TLess<longint>;
setlli=specialize TSet<longint,lesslli>;
type TGSetTest = class(TTestCase)
Published
procedure SetTest;
public
procedure Setup;override;
private
data:setlli;
end;
implementation
procedure TGSetTest.SetTest;
var it:setlli.pnode;
begin
data.insert(3);
data.insert(5);
data.insert(7);
AssertEquals('Wrong min', 3, data.min()^.data);
AssertEquals('Wrong max', 7, data.max()^.data);
data.delete(3);
AssertEquals('Wrong size', 2, data.size);
AssertEquals('Wrong min', 5, data.min()^.data);
data.insert(3);
data.insert(3);
data.insert(3);
AssertEquals('Wrong size', 3, data.size);
AssertEquals('Wrong min', 3, data.min()^.data);
if(data.find(4)<>nil) then
Fail('Found key which not there');
if(data.find(5)=nil) then
Fail('Not found key which was there');
if(data.FindLess(8)^.data<>7) then
Fail('Wrong less than 8');
if(data.FindLess(7)^.data<>5) then
Fail('Wrong less than 7');
if(data.FindLess(3)<>nil) then
Fail('Wrong less than 3');
if(data.FindLessEqual(8)^.data<>7) then
Fail('Wrong less equal than 8');
if(data.FindLessEqual(7)^.data<>7) then
Fail('Wrong less equal than 7');
if(data.FindLessEqual(6)^.data<>5) then
Fail('Wrong less equal than 6');
if(data.FindLessEqual(2)<>nil) then
Fail('Wrong less equal than 2');
if(data.FindGreater(2)^.data<>3) then
Fail('Wrong greater than 2');
if(data.Findgreater(3)^.data<>5) then
Fail('Wrong greater than 3');
if(data.Findgreater(7)<>nil) then
Fail('Wrong greater than 7');
if(data.FindGreaterEqual(2)^.data<>3) then
Fail('Wrong greater equal than 2');
if(data.FindGreaterEqual(3)^.data<>3) then
Fail('Wrong greater equal than 3');
if(data.FindGreaterEqual(4)^.data<>5) then
Fail('Wrong greater equal than 4');
if(data.FindGreaterEqual(8)<>nil) then
Fail('Wrong greater equal than 8');
data.insert(17);
it:=data.min;
AssertEquals('Wrong min', 3, it^.data);
it:=data.next(it);
AssertEquals('Wrong next', 5, it^.data);
it:=data.next(it);
AssertEquals('Wrong next', 7, it^.data);
it:=data.next(it);
AssertEquals('Wrong next', 17, it^.data);
it:=data.next(it);
if(it<>nil) then
AssertEquals('Last not nil', 0, 1);
it:=data.max;
AssertEquals('Wrong max', 17, it^.data);
it:=data.prev(it);
AssertEquals('Wrong prev', 7, it^.data);
it:=data.prev(it);
AssertEquals('Wrong prev', 5, it^.data);
it:=data.prev(it);
AssertEquals('Wrong prev', 3, it^.data);
it:=data.prev(it);
if(it<>nil) then
AssertEquals('First not nil', 0, 1);
end;
procedure TGSetTest.Setup;
begin
data:=setlli.create;
end;
initialization
RegisterTest(TGSetTest);
end.

View File

@ -0,0 +1,52 @@
{$mode objfpc}
unit gsorttest;
interface
uses fpcunit, testregistry, gvector, garrayutils, gutil;
type vectorlli=specialize TVector<longint>;
lesslli=specialize TLess<longint>;
sortlli=specialize TOrderingArrayUtils<vectorlli, longint, lesslli>;
type TGSortTest = class(TTestCase)
Published
procedure SortRandomTest;
procedure SortZeroOneTest;
public
procedure Setup;override;
private
data:vectorlli;
end;
implementation
procedure TGSortTest.SortRandomTest;
var i:longint;
begin
for i:=0 to 5000 do
data.pushBack(random(10000));
sortlli.sort(data, 5001);
for i:=0 to 4999 do
AssertEquals('Wrong order', false, data[i+1]<data[i]);
end;
procedure TGSortTest.SortZeroOneTest;
var i:longint;
begin
for i:=0 to 5000 do
data.pushBack(random(2));
sortlli.sort(data, 5001);
for i:=0 to 4999 do
AssertEquals('Wrong order', false, data[i+1]<data[i]);
end;
procedure TGSortTest.Setup;
begin
data:=vectorlli.create;
end;
initialization
RegisterTest(TGSortTest);
end.

View File

@ -0,0 +1,43 @@
{$mode objfpc}
unit gstacktest;
interface
uses fpcunit, testregistry, gstack;
type TStacklli=specialize TStack<longint>;
type TGTStackTest = class(TTestCase)
Published
procedure TStackTest;
public
procedure Setup;override;
private
data:TStacklli;
end;
implementation
procedure TGTStackTest.TStackTest;
var i:longint;
begin
AssertEquals('Not IsEmpty', true, data.IsEmpty);
for i:=0 to 10 do
data.push(i);
for i:=0 to 10 do begin
AssertEquals('Wrong data', 10-i, data.top);
AssertEquals('Wrong size', 11-i, data.size);
data.pop;
end;
AssertEquals('Not IsEmpty', true, data.IsEmpty);
end;
procedure TGTStackTest.Setup;
begin
data:=TStacklli.create;
end;
initialization
RegisterTest(TGTStackTest);
end.

View File

@ -0,0 +1,111 @@
{$mode objfpc}
unit gvectortest;
interface
uses fpcunit, testregistry, gvector;
type vectorlli=specialize TVector<longint>;
rec=record
a,b:longint;
end;
vectorrec=specialize TVector<rec>;
type TGVectorTest = class(TTestCase)
Published
procedure PushBackTest;
procedure ResizeTest;
procedure PopbackTest;
procedure InsertEraseTest;
procedure MutableTest;
public
procedure Setup;override;
private
data:vectorlli;
end;
implementation
procedure TGVectorTest.PushBackTest;
var i:longint;
begin
AssertEquals('Not IsEmpty', true, data.IsEmpty);
for i:=0 to 10 do
data.pushBack(i);
for i:=0 to 10 do
AssertEquals('Wrong data', i, data[i]);
AssertEquals('Wrong size', 11, data.size);
AssertEquals('IsEmpty', false, data.IsEmpty);
end;
procedure TGVectorTest.ResizeTest;
var i:longint;
begin
AssertEquals('Not IsEmpty', true, data.IsEmpty);
data.resize(50);
AssertEquals('IsEmpty', false, data.IsEmpty);
for i:=0 to 49 do
data[i]:=3*i;
for i:=0 to 49 do
AssertEquals('Wrong data', 3*i, data[i]);
AssertEquals('Wrong size', 50, data.size);
end;
procedure TGVectorTest.PopbackTest;
var i:longint;
begin
for i:=0 to 49 do begin
data.pushBack(5*i);
AssertEquals('Wrong end', 5*i, data.back);
AssertEquals('Wrong front', 0, data.front);
end;
for i:=1 to 10 do begin
data.popBack;
AssertEquals('Wrong end after popback', 5*(49-i), data.back);
end;
end;
procedure TGVectorTest.InsertEraseTest;
var i:longint;
begin
for i:=0 to 9 do
data.pushBack(i);
data.insert(3,100);
for i:=0 to 2 do
AssertEquals('Wrong data before insert', i, data[i]);
AssertEquals('Wrong data', 100, data[3]);
for i:=4 to 10 do
AssertEquals('Wrong data after insert', i-1, data[i]);
data.erase(4);
for i:=4 to 9 do
AssertEquals('Wrong data after erase', i, data[i]);
AssertEquals('Wrong data before erase', 100, data[3]);
for i:=0 to 2 do
AssertEquals('Wrong data before erase', i, data[i]);
end;
procedure TGVectorTest.MutableTest;
var dat:vectorrec;
begin
dat:=vectorrec.create;
dat.resize(2);
dat.mutable[0]^.a:=5;
dat.mutable[0]^.b:=7;
AssertEquals('Wrong data', 5, dat[0].a);
AssertEquals('Wrong data', 7, dat[0].b);
dat.mutable[0]^.a:=45;
dat.mutable[0]^.b:=47;
AssertEquals('Wrong data', 45, dat[0].a);
AssertEquals('Wrong data', 47, dat[0].b);
end;
procedure TGVectorTest.Setup;
begin
data:=vectorlli.create;
end;
initialization
RegisterTest(TGVectorTest);
end.

View File

@ -0,0 +1,4 @@
#!/bin/bash
rm *.o *.ppu ../*.o ../*.ppu testrunner
fpc -Fu.. -gttt testrunner.pp -Sa
./testrunner --all

View File

@ -0,0 +1,27 @@
{$mode objfpc}
{$h+}
{
This file is part of the Free Component Library (FCL)
Copyright (c) 2004 by Dean Zobec, Michael Van Canneyt
a unit to register the tests to be runned.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
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.
**********************************************************************}
unit suiteconfig;
interface
uses
gvectortest, gstacktest, gqueuetest, gdequetest, gsorttest,
gpriorityqueuetest, gsettest, gmaptest;
implementation
end.

View File

@ -0,0 +1,138 @@
{
This file is part of the Free Component Library (FCL)
Copyright (c) 2004 by Dean Zobec, Michael Van Canneyt
an example of a console test runner of FPCUnit tests.
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
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.
}
program testrunner;
{$mode objfpc}
{$h+}
uses
custapp, Classes, SysUtils, fpcunit, suiteconfig, testreport, testregistry;
const
ShortOpts = 'alh';
Longopts: Array[1..5] of String = (
'all','list','format:','suite:','help');
Version = 'Version 0.2';
type
TTestRunner = Class(TCustomApplication)
private
FXMLResultsWriter: TXMLResultsWriter;
protected
procedure DoRun ; Override;
procedure doTestRun(aTest: TTest); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
constructor TTestRunner.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FXMLResultsWriter := TXMLResultsWriter.Create;
end;
destructor TTestRunner.Destroy;
begin
FXMLResultsWriter.Free;
end;
procedure TTestRunner.doTestRun(aTest: TTest);
var
testResult: TTestResult;
begin
testResult := TTestResult.Create;
try
testResult.AddListener(FXMLResultsWriter);
aTest.Run(testResult);
FXMLResultsWriter.WriteResult(testResult);
finally
testResult.Free;
end;
end;
procedure TTestRunner.DoRun;
var
I : Integer;
S : String;
begin
S:=CheckOptions(ShortOpts,LongOpts);
If (S<>'') then
Writeln(S);
if HasOption('h', 'help') or (ParamCount = 0) then
begin
writeln(Title);
writeln(Version);
writeln('Usage: ');
writeln('-l or --list to show a list of registered tests');
writeln('default format is xml, add --format=latex to output the list as latex source');
writeln('-a or --all to run all the tests and show the results in xml format');
writeln('The results can be redirected to an xml file,');
writeln('for example: ./testrunner --all > results.xml');
writeln('use --suite=MyTestSuiteName to run only the tests in a single test suite class');
end
else;
if HasOption('l', 'list') then
begin
if HasOption('format') then
begin
if GetOptionValue('format') = 'latex' then
writeln(GetSuiteAsLatex(GetTestRegistry))
else
writeln(GetSuiteAsXML(GetTestRegistry));
end
else
writeln(GetSuiteAsXML(GetTestRegistry));
end;
if HasOption('a', 'all') then
begin
doTestRun(GetTestRegistry)
end
else
if HasOption('suite') then
begin
S := '';
S:=GetOptionValue('suite');
if S = '' then
for I := 0 to GetTestRegistry.Tests.count - 1 do
writeln(GetTestRegistry[i].TestName)
else
for I := 0 to GetTestRegistry.Tests.count - 1 do
if GetTestRegistry[i].TestName = S then
begin
doTestRun(GetTestRegistry[i]);
end;
end;
Terminate;
end;
var
App: TTestRunner;
begin
App := TTestRunner.Create(nil);
App.Initialize;
App.Title := 'FPCUnit Console Test Case runner.';
App.Run;
App.Free;
end.