/* ********************************************************************* 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 );;