/* *********************************************************************
This source file is a part of the standard library of Scol
For the latest info, see http://www.scolring.org
Copyright (c) 2014 Stephane Bisaro aka Iri.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free Software
Foundation; either version 2 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt
********************************************************************* */
/*
* Standard functions for Scol
* See http://redmine.scolring.org/projects/tutorials/wiki/Scol_usage
* for more informations
*/
/*! \file iteration.pkg
* \author Scol team
* \version 0.1
* \copyright GNU Lesser General Public License 2.0 or later
* \brief Scol Iteration Library API
*
* lib/std/stdlib.pkg and lib/std/string.pkg are required and should be loaded before this package.
**/
fun STD_IT_FROMBEGIN ()= 0;;
fun STD_IT_FROMCURRENT ()= 1;;
fun STD_IT_FROMEND ()= 2;;
fun std_itcheckflagpos (flag)=
std_clamp flag STD_IT_FROMBEGIN STD_IT_FROMEND;;
typedef Std_TypIteration =
Std_TypIterationI I
| Std_TypIterationF F
| Std_TypIterationS S
| Std_TypIterationFile File
| Std_TypIterationTab tab Std_TypIteration
| Std_TypIterationO;;
struct StdIteration = [
stditeration_type : Std_TypIteration,
stditeration_fileS : S,
stditeration_chn : Chn,
stditeration_curpos : I,
stditeration_len : I,
stditeration_beginpos : I,
stditeration_endpos : I,
stditeration_sep : I, // separator (char)
stditeration_includesep : I,
stditeration_cbbegin : fun [StdIteration] I,
stditeration_cbend : fun [StdIteration] I,
stditeration_cb : fun [StdIteration S] I
] mkStdIteration;;
fun std_itinit ()=
mkStdIteration [
nil nil _channel
0 0 0 0
nil 0
nil nil nil
];;
fun std_itendpos (it)=
match it.stditeration_type with
(Std_TypIterationS s -> strlen s)
| (Std_TypIterationFile pf -> _FILESize pf)
| (Std_TypIterationTab tab -> sizetab tab)
| (_ -> nil);;
fun std_itsetposbegin (it, pos)=
set pos = if pos < 0 then it.stditeration_endpos + pos else pos;
set it.stditeration_beginpos = std_clamp pos 0 it.stditeration_endpos;
it;;
fun std_itsetposend (it, pos)=
set pos = if pos < 0 then it.stditeration_endpos + pos else pos;
set it.stditeration_endpos = std_clamp pos 0 std_itendpos it;
it;;
fun std_itupdatecurpos (it)=
let it.stditeration_curpos + it.stditeration_len -> d in
if it.stditeration_len < 0 then
set it.stditeration_curpos = if d > it.stditeration_beginpos then d else it.stditeration_beginpos
else if it.stditeration_len > 0 then
set it.stditeration_curpos = if d > it.stditeration_endpos then it.stditeration_endpos else d
else
0;
if it.stditeration_curpos == it.stditeration_endpos then
exec it.stditeration_cbend with [it]
else
nil;;
fun std_itupdatepos (it, pos, flag)=
if flag == STD_IT_FROMBEGIN then
set it.stditeration_curpos = pos
else if flag == STD_IT_FROMCURRENT then
set it.stditeration_curpos = it.stditeration_curpos + pos
else if flag == STD_IT_FROMEND then
set it.stditeration_curpos = it.stditeration_endpos + pos
else
0;
std_clamp it.stditeration_curpos it.stditeration_beginpos it.stditeration_endpos;
match it.stditeration_type with
(Std_TypIterationFile pf -> (_FILESeek pf it.stditeration_curpos 0; it))
| (_ -> it);;
/*fun std_itgetcontenttab (it, tab, t)=
let std_clamp
if it.stditeration_len < 0 then
it.stditeration_curpos + it.stditeration_len
else
it.stditeration_curpos
it.stditeration_beginpos
it.stditeration_endpos
-> posStart in
let posStart + it.stditeration_len -> a in
let if a >= it.stditeration_endpos then it.stditeration_endpos - posStart else a -> len in
let len-1 -> i in
let nil -> t in
(
// set posStart = std_clamp posStart it.stditeration_beginpos it.stditeration_endpos;
while i >= 0 do
let posStart + i -> k in
match tab.k with
(Std_TypIterationS s -> (
set t = mktab i nil;
while i >=0 do
let posStart + i -> k in
(
set t.i = s;
set i = i+1
);
))
| (Std_TypIterationI int -> (
set t = mktab i nil;
while i >=0 do
let posStart + i -> k in
(
set t.i = int;
set i = i+1
);
))
| (Std_TypIterationF f -> (
set t = mktab i nil;
while i >=0 do
let posStart + i -> k in
(
set t.i = f;
set i = i+1
);
))
| (Std_TypIterationFile pf -> (
set t = mktab i nil;
while i >=0 do
let posStart + i -> k in
(
set t.i = pf;
set i = i+1
);
))
| (Std_TypIterationTab table -> (
set t = mktab i nil;
while i >=0 do
let posStart + i -> k in
(
set t.i = table;
set i = i+1
);
))
| (_ -> nil);
std_itupdatecurpos it;
t
);;
*/
/*
while i >=0 do
(
let posStart + i -> k in
match tab.k with
(Std_TypIterationS s -> (set t.i = s; 0))
| (Std_TypIterationFile pf -> (set t.i = pf; 0))
| (Std_TypIterationI int -> (set t.i = int; 0))
| (Std_TypIterationF f -> (set t.i = f; 0))
| (Std_TypIterationTab table -> (set t.i = table; 0))
| (_ -> (set t.i = /*Std_TypIterationO*/ nil; 0));
//set t.i = tab.k;
set i = i+1
);
std_itupdatecurpos it;
t
);;*/
fun std_itgetcontentfile (it, pf)=
let _FILERead pf it.stditeration_len -> szRes in
(
std_itupdatecurpos it; // set it.stditeration_curpos = it.stditeration_curpos + it.stditeration_len;
_FILESeek pf it.stditeration_len 1;
exec it.stditeration_cb with [it szRes];
szRes
);;
fun std_itgetcontentstring (it, szFull)=
let if it.stditeration_len < 0 then it.stditeration_curpos + it.stditeration_len else it.stditeration_curpos -> posStart in
let substr szFull posStart /*it.stditeration_curpos*/ abs it.stditeration_len -> szRes in
(
std_itupdatecurpos it; // set it.stditeration_curpos = it.stditeration_curpos + it.stditeration_len;
exec it.stditeration_cb with [it szRes];
szRes
);;
// read
fun std_itgetcontent (it, len)=
set it.stditeration_len = len;
match it.stditeration_type with
(Std_TypIterationS s -> std_itgetcontentstring it s)
| (Std_TypIterationFile pf -> std_itgetcontentfile it pf)
//| (Std_TypIterationTab tab -> std_itgetcontenttab it tab)
| (_ -> nil);;
// read2 (tab)
/*fun std_itgetcontent2 (it, len)=
set it.stditeration_len = len;
match it.stditeration_type with
(Std_TypIterationTab tab -> std_itgetcontenttab it tab)
| (_ -> nil);;*/
fun std_itgetnext (it)=
std_itgetcontent it 1;;
fun std_itgetnextcharstring (it, s)=
let "" -> szOut in
let 0 -> i in
(
set it.stditeration_len = 1;
while (!i) && (it.stditeration_curpos < it.stditeration_endpos) do
let nth_char s it.stditeration_curpos -> c in
if c == it.stditeration_sep then
(
if it.stditeration_includesep then
set szOut = strcat szOut ctoa c
else
nil;
std_itupdatecurpos it;
set i = 1
)
else
(
set szOut = strcat szOut ctoa c;
std_itupdatecurpos it;
);
exec it.stditeration_cb with [it szOut];
szOut
);;
fun std_itgetnextcharfile (it, pf)=
let "" -> szOut in
let 0 -> i in
(
set it.stditeration_len = 1;
while (!i) && (it.stditeration_curpos < it.stditeration_endpos) do
let nth_char _FILERead pf 1 0 -> c in
if c == it.stditeration_sep then
(
if it.stditeration_includesep then
set szOut = strcat szOut ctoa c
else
nil;
std_itupdatecurpos it;
set i = 1
)
else
(
set szOut = strcat szOut ctoa c;
it.stditeration_curpos;
std_itupdatecurpos it;
0
);
exec it.stditeration_cb with [it szOut];
szOut
);;
fun std_itgetnextchar (it)=
if std_szIsEmpty ctoa it.stditeration_sep then
nil
else
match it.stditeration_type with
(Std_TypIterationS s -> std_itgetnextcharstring it s)
| (Std_TypIterationFile pf -> std_itgetnextcharfile it pf)
| (_ -> nil);;
fun std_itget (it)=
match it.stditeration_type with
(Std_TypIterationS s -> s)
| (Std_TypIterationFile pf -> it.stditeration_fileS)
| (_ -> nil);;
fun std_itaddstring (it, s, string)=
let substr s 0 it.stditeration_curpos -> begin in
let substr s it.stditeration_curpos+1 strlen s -> end in
set it.stditeration_type = Std_TypIterationS strcat
strcat
begin string
end;
0;;
fun std_itaddfile (it, pf, string)=
_FILESeek pf 0 0;
let _FILERead pf _FILESize pf -> s in
let substr s 0 it.stditeration_curpos -> begin in
let substr s it.stditeration_curpos+1 strlen s -> end in
let strcat strcat begin string end -> news in
/* let _fooS strcat "---->>>> " news -> _ in
let _fooId _getmodifypack it.stditeration_fileS -> _ in
_fooId */_createpack news _getmodifypack it.stditeration_fileS;
_FILESeek pf it.stditeration_curpos 0;
0;;
fun std_itadd (it, string)=
match it.stditeration_type with
(Std_TypIterationS s -> std_itaddstring it s string)
| (Std_TypIterationFile pf -> std_itaddfile it pf string)
| (_ -> nil);
it;;
/*! \brief Create a new StdIteration object from a string
*
* \ingroup std_iteration
* Prototype : fun [S] StdIteration
*
* The current cursor position is put at 0.
*
* \param S : an inital string to iterate
* \return StdIteration : the new StdIteration object
*
* \see std_itUpdatePos to change the position
**/
fun std_itNewS (szValue)=
if std_objIsNil szValue then
nil
else
let std_itinit -> it in
(
set it.stditeration_type = Std_TypIterationS szValue;
set it.stditeration_chn = _channel;
set it.stditeration_beginpos = 0;
set it.stditeration_endpos = std_itendpos it;
it
);;
/*! \brief Create a new StdIteration object from a File object
*
* \ingroup std_iteration
* Prototype : fun [Chn P] StdIteration
*
* The current cursor position is put at 0.
*
* \param Chn : a channel, like the current channel (_channel)
* \param P : a read file reference to iterate
* \return StdIteration : the new StdIteration object
*
* \see std_itUpdatePos to change the position
**/
fun std_itNewFile (chn, pFile)=
if (std_objIsNil pFile) || (std_objIsNil chn) then
nil
else
let std_itinit -> it in
(
set it.stditeration_type = Std_TypIterationFile _FILEOpen chn pFile;
set it.stditeration_fileS = _PtoScol pFile;
set it.stditeration_chn = chn;
set it.stditeration_beginpos = 0;
set it.stditeration_endpos = std_itendpos it;
it
);;
/*! \brief Create a new StdIteration object from a tab (array) object
*
* \ingroup std_iteration
* Prototype : fun [tab u0] StdIteration
*
* The current cursor position is put at 0.
*
* \param tab u0 : a table (array) to iterate
* \return StdIteration : the new StdIteration object
*
* \see std_itUpdatePos to change the position
* \warning Removed !
**/
fun std_itNewTab (tab)=0;;
/* if std_objIsNil tab then
nil
else
let std_itinit -> it in
(
set it.stditeration_type = Std_TypIterationTab tab;
set it.stditeration_chn = _channel;
set it.stditeration_beginpos = 0;
set it.stditeration_endpos = std_itendpos it;
it
);;*/
/*fun std_itSetPosBegin (oIt, iPosBegin)=
set oIt.stditeration_beginpos = iPosBegin;
oIt;;
fun std_itSetPosEnd (oIt, iPosEnd)=
set oIt.stditeration_endpos = iPosEnd;
oIt;;*/
/*! \brief Read the subcontent of a StdIteration object from the current
* cursor position and the given lenght (like the fread C-function). Next,
* the position will be updated (current position + lenght)
*
* \ingroup std_iteration
* Prototype : fun [StdIteration I] S
*
* \param StdIteration : a StdIteration object to iterate
* \param I : a lenght (can be a negative or positive integer)
*
* \return S : the subcontent or nil if an error occurs
* \see std_itSetCb
* \see std_itReadTab
**/
fun std_itRead (oIt, iLength)=
if (std_objIsNil oIt) || (std_objIsNil iLength) then
nil
else
std_itgetcontent oIt iLength;;
/*! \brief Read the subcontent of a StdIteration object from the current
* cursor position to one unit (byte, char or other) (like the fread C-function).
* Next, the position will be updated (current position + 1)
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] S
*
* \param StdIteration : a StdIteration object to iterate
*
* \return S : the subcontent or nil if an error occurs
* \see std_itRead
**/
fun std_itReadNext (oIt)=
if std_objIsNil oIt then
nil
else
std_itgetnext oIt;;
/*! \brief Read the subcontent of a StdIteration tab (array) object from the current
* cursor position and the given lenght (like the fread C-function). Next,
* the position will be updated (current position + lenght)
*
* \ingroup std_iteration
* Prototype : fun [StdIteration I] tab u0
*
* \param StdIteration : a StdIteration object to iterate
* \param I : a lenght (can be a negative or positive integer)
*
* \return tab u0 : a new tab (its size is the given length) or nil if an error occurs
* \see std_itRead
* \Warning Removed !
**/
/*fun std_itReadTab (oIt, iLength)=
if (std_objIsNil oIt) || (std_objIsNil iLength) then
nil
else
std_itgetcontent2 oIt iLength;;*/
/*! \brief Update the cursor position.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration I I] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param I : a new position (if negative, the new position will be 0, if
* too long, the new position will be truncated.
* \param I : a flag :
* - STD_IT_FROMBEGIN : position given from beginning of the object
* - STD_IT_FROMCURRENT : position given from the current cursor position of the object
* - STD_IT_FROMEND : position given from end of the object
*
* \return StdIteration : the same StdIteration object or nil if an error occurs
**/
fun std_itUpdatePos (oIt, iPos, iFlag)=
if std_objIsNil oIt then
nil
else
std_itupdatepos oIt iPos std_itcheckflagpos iFlag;;
/*! \brief Set the minimum cursor position. By default it is 0.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration I] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param I : a new minimum position (can be negative, the new position will
* be from the maximum).
*
* \return StdIteration : the same StdIteration object or nil if an error occurs
* \see std_itSetPosEnd
**/
fun std_itSetPosBegin (oIt, iPosBegin)=
if std_objIsNil oIt then
nil
else
std_itsetposbegin oIt iPosBegin;;
/*! \brief Set themaximum cursor position. By default it is the lenght of
* the object.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration I I] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param I : a new maximum position (can be negative, the new position will
* be from the old maximum).
*
* \return StdIteration : the same StdIteration object or nil if an error occurs
* \see std_itSetPosBegin
**/
fun std_itSetPosEnd (oIt, iPosEnd)=
if std_objIsNil oIt then
nil
else
std_itsetposend oIt iPosEnd;;
/*! \brief Get the minimum cursor position.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] I
*
* \param StdIteration : a StdIteration object to iterate
*
* \return I : the minimum position
**/
fun std_itGetPosBegin (oIt)=
oIt.stditeration_beginpos;;
/*! \brief Get the maximum cursor position.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] I
*
* \param StdIteration : a StdIteration object to iterate
*
* \return I : the maximum position
**/
fun std_itGetPosEnd (oIt)=
oIt.stditeration_endpos;;
/*! \brief Get the length of a StdIteration object.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] I
*
* \param StdIteration : a StdIteration object to iterate
*
* \return I : this length or nil if error / not supported
**/
fun std_itGetLength (oIt)=
std_itendpos oIt;;
/*! \brief Get the current cursor position of a StdIteration object.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] I
*
* \param StdIteration : a StdIteration object to iterate
*
* \return I : the current position or nil if error
**/
fun std_itGetPos (oIt)=
oIt.stditeration_curpos;;
/*! \brief Get the last given length for read.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] I
*
* \param StdIteration : a StdIteration object to iterate
*
* \return I : this last length or nil if error
**/
fun std_itGetLastLength (oIt)=
oIt.stditeration_len;;
/*! \brief Return the initial object
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] S
*
* \param StdIteration : a StdIteration object to iterate
*
* \return S : the object : a string, a path name, ... or nil if error
**/
fun std_itGet (oIt)=
std_itget oIt;;
fun std_itSetCbBegin (oIt, cbfun)=
set oIt.stditeration_cbbegin = cbfun;
oIt;;
/*! \brief Set the function called when the ioterator comes to the end.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration fun [StdIteration] I] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param fun [StdIteration] I : the callback (the argument is the StdIteration object itself)
*
* \return StdIteration : the same StdIteration object or nil if an error occurs
*/
fun std_itSetCbEnd (oIt, cbfun)=
set oIt.stditeration_cbend = cbfun;
oIt;;
/*! \brief Set the function called for each iteration.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration fun [StdIteration S] I] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param fun [StdIteration S] I : the callback. The arguments are :
* - the StdIteration object itself
* - the sub-content
*
* \return StdIteration : the same StdIteration object or nil if an error occurs
* \see std_itRead
*/
fun std_itSetCb (oIt, cbfun)=
set oIt.stditeration_cb = cbfun;
oIt;;
/*! \brief Add the substring to a StdIteration object from the current
* cursor position. The cursor position keeps unchanged.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration S] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param S : a string to add (to include)
* \return StdIteration : the same StdIteration object or nil if an error occurs
**/
fun std_itAdd (oIt, szToAdd)=
std_itadd oIt szToAdd;;
/*! \brief Define a separator for a StdIteration object.
*
* A separator is an ascii value.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration I] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param I : an ascii value
* \return StdIteration : the same StdIteration object or nil if an error occurs
* \see std_itSetSepFromS
**/
fun std_itSetSep (oIt, iSep)=
set oIt.stditeration_sep = iSep;
oIt;;
/*! \brief Define a separator for a StdIteration object.
*
* A separator is an ascii value.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration S] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param S : a string. The first char will take off only, others are ignored.
* This function is a convenience to avoid to give the ascii value directly.
* \return StdIteration : the same StdIteration object or nil if an error occurs
* \see std_itSetSep
**/
fun std_itSetSepFromS (oIt, szSep)=
set oIt.stditeration_sep = nth_char szSep 0;
oIt;;
/*! \brief Get the current defined seperator.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] I
*
* \param StdIteration : a StdIteration object to iterate
* \return I : the ascii value of the current separator (nil if undefined)
**/
fun std_itGetSep (oIt)=
oIt.stditeration_sep;;
/*! \brief Set if the separator is included in the return or not.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration I] StdIteration
*
* \param StdIteration : a StdIteration object to iterate
* \param I : 1 to include, 0 to not include (default)
* \return StdIteration : the same StdIteration object or nil if an error occurs
* \see std_itReadSep
**/
fun std_itSepIncluded (oIt, iFlag)=
set oIt.stditeration_includesep = std_clamp iFlag 0 1;
oIt;;
/*! \brief Get if the current defined seperator is included (or not in the return.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] I
*
* \param StdIteration : a StdIteration object to iterate
* \return I : 1 if included else 0
* \see std_itReadSep
**/
fun std_itGepIncluded (oIt)=
oIt.stditeration_includesep;;
/*! \brief Read the subcontent of a StdIteration object from the current
* cursor position until the next separator found.
*
* If the separator is not found, th ewhole subcontent from the current
* sursor position until the end position is returned.
* Next, the cursor position will be updated.
*
* \ingroup std_iteration
* Prototype : fun [StdIteration] S
*
* \param StdIteration : a StdIteration object to iterate
*
* \return S : the subcontent or nil if an error occurs
* \see std_itSepIncluded
* \see std_itSetSep
* \see std_itRead
* \see std_itSetPosEnd to define the end position (otherwise, it is the end of the object)
**/
fun std_itReadSep (oIt)=
std_itgetnextchar oIt;;
/*
fun std_itNew (o)=
let std_itinit -> it in
match o with
(Std_TypIterationS s -> (set it.stditeration_type = Std_TypIterationS s; it))
| (Std_TypIterationFile f -> (set it.stditeration_type = Std_TypIterationFile f; it))
| (_ -> nil);;*/
/*fun std_itSetInteger (oIt, iInt)=
set oIt.stditeration_type = Std_TypIterationI iInt;
oIt;;
fun std_itSetFloat (oIt, fFloat)=
set oIt.stditeration_type = Std_TypIterationF fFloat;
oIt;;*/
fun main ()=
_showconsole;
//_setActivePartition "./Partition_LockedApp" 1;
let std_itNewS "_string_ is a string" -> it in
let std_itNewFile _channel _checkpack "lib/tests/loadpkg2.pkg" -> it2 in
(
std_itSetSepFromS it2 "@";
_fooS std_itReadSep it2;
_fooS std_itReadSep it2;
_fooS std_itReadSep it2;
_fooS std_itReadSep it2;
_fooS std_itReadSep it2;
/*_fooS std_itRead it 3;
_fooS std_itRead it 2;
_fooS std_itRead it (-4);
_fooS "-----";
_fooS std_itRead it2 3;
std_itAdd it2 "__o__";
_fooS _getpack _checkpack std_itGet it2;
std_itUpdatePos it2 (-4) STD_IT_FROMEND;
_fooS std_itRead it2 4;
_fooS std_itRead it2 (-4);
_fooS "-----";*/
/*let 0 -> i in
while i < 10 do
(
_fooS std_itReadNext it;
set i = i+1;
);*/
0
);;