frunes.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
------------------------->  GNU Sather - sourcefile  <-------------------------
-- Copyright (C) 2000 by K Hopper, University of Waikato, New Zealand        --
-- This file is part of the GNU Sather library. It is free software; you may --
-- redistribute  and/or modify it under the terms of the GNU Library General --
-- Public  License (LGPL)  as published  by the  Free  Software  Foundation; --
-- either version 2 of the license, or (at your option) any later version.   --
-- This  library  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 Doc/LGPL for more details.       --
-- The license text is also available from:  Free Software Foundation, Inc., --
-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA                     --
-------------->  Please email comments to <bug-sather@gnu.org>  <--------------


class FRUNES < $FTEXT_STRING{RUNE,RUNES,FRUNES}

class FRUNES < $FTEXT_STRING{RUNE,RUNES,FRUNES} is -- This class implements the concept of a fast (mutable) text string - -- in this case of runes (potentially variable width characters). -- Version 1.0 Apr 99. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 12 Apr 99 kh Original for Version 8 of text classes include FTEXT_STRING{RUNE,RUNES} plus -> raw_plus ; include FTEXT_INCL{RUNE} oct_acopy -> oct_acopy, ind! -> ; private const Default_Size : CARD := 16 ; -- character codes -- not runes! private attr indices : FLIST{CARD} ; -- of rune initial code indices create( sz : CARD, lib : LIBCHARS ) : SAME pre ~void(lib) post ~void(result) is -- This routine creates a new buffer for the given code count. if sz = 0 then return void end ; me : SAME := raw_create(sz * lib.my_size) ; me.priv_lib := REP_LIB_LIST::index(lib) ; me.indices := FLIST{CARD}::create ; return me end ; create( sz : CARD ) : SAME is -- This routine creates a new buffer of the given storage size. return create(sz,LIBCHARS::default) end ; create( lib : LIBCHARS ) : SAME is -- This routine creates a new buffer of the given storage size. return create(Default_Size,lib) end ; create : SAME is -- This routine returns a new buffer. return create(Default_Size,LIBCHARS::default) end ; create( src : RUNES ) : SAME is -- This routine creates and fills a buffer from src. if (src.size = 0) then return create -- just produce a default buffer else res : SAME := create(src.asize,src.index_lib) ; res.acopy(src) ; res.loc := src.asize ; res.buffer_scan ; return res end end ; nil : SAME is -- This routine returns a new nil (empty but not void) string. return create end ; binstr : BINSTR pre ~void(self) and (loc > 0) post (result.size = loc) is -- This routine returns the text string as a binary string. res : BINSTR := BINSTR::create(loc) ; loop index : CARD := 0.upto!(loc - 1) ; res.aset!(oct_aget(index)) end ; return res end ; size : CARD pre true post ((void(self) or (loc = 0)) and (result = 0)) or (result = indices.size) is -- This routine returns the number of runes in self or, if self is -- void, then zero. if void(self) or (loc = 0) then return 0 else return indices.size end end ; push( elem : RUNE ) : SAME pre void(self) or (index_lib = elem.lib) post (result.size = (initial(size) + 1)) is -- This routine appends a new element to the end of self and returns it. -- If self is void, create a new list. res : SAME ; loc_size : CARD := size ; -- which may, of course, be zero! if void(self) then res := create(2 * elem.asize,elem.lib) ; res.loc := 0 elsif (loc < (asize - elem.asize)) then res := self else res := create(2 * (asize + elem.asize),index_lib) ; -- Amortised doubling res.loc := loc ; res.acopy(self) ; SYS::destroy(self) -- old one shouldn't be used now. end ; res.aset(loc_size,elem) ; res.buffer_scan ; return res end ; plus( elem : RUNE ) : SAME pre true post ~void(result) and ((void(self) and (result.loc = 1)) or (result.loc = initial(self.loc) + 1)) is -- This routine appends elem to self and returns it. return self.push(elem) end ; plus( fstr : SAME ) : SAME pre (index_lib = fstr.index_lib) post ~void(result) and ((void(self) and (result.loc = str.size)) or (result.loc = initial(self.loc) + str.size)) is -- This routine appends the rune string fstr to self and returns it. res : SAME := raw_plus(fstr) ; res.buffer_scan ; return res end ; plus( str : RUNES ) : SAME pre ~void(self) and (index_lib = str.index_lib) post ~void(result) and ((void(self) and (result.loc = str.size)) or (result.loc = initial(self.loc) + str.size)) is -- This routine appends the string str to self and returns the resulting -- string. res : SAME := raw_plus(str) ; res.buffer_scan ; return res end ; aget( index : CARD ) : RUNE pre ~void(self) and (index < indices.size) post true is -- This routine is the 'array' indexing facility for runes in a string -- of runes, returning the rune indexed. loc_stop : CARD ; if index < (indices.size - 1) then loc_stop := indices[index + 1] else loc_stop := loc end ; loc_res : BINSTR := BINSTR::create ; loop loc_index : CARD := indices[index].upto!(loc_stop - 1) ; loc_res := loc_res + oct_aget(loc_index) end ; return RUNE::build(loc_res.cursor,index_lib) end ; aset( index : CARD, elem : RUNE ) pre ~void(self) and ~void(elem) and (index <= size) post true is -- This routine is the 'array' indexing facility for a rune string which -- is only applicable if it is known that either the element to be set is at -- the end of the current contents and there is space for the element or that -- the size of the element to be inserted is identical to the size of that -- being replaced. if index = indices.size then indices := indices.push(loc) ; loc := loc + elem.asize end ; loop loc_index : CARD := indices[index].up! ; aset(loc_index,elem.aelt!) end end ; vset( index : CARD, elem : RUNE ) : SAME pre ~void(self) and (index <= (indices.size - 1)) post true is -- This routine is the 'array' indexing facility for the case where -- the number of codes in elem is different from the number currently at that -- index position in the string. A new rune string has to be produced if the -- resulting length is different from that currently allocated. if index = (indices.size - 1) and (indices[index] + elem.size) < asize then aset(index,elem) ; return self else return head(index - 1) + elem + tail((indices.size - 1) - index) end end ; buffer_scan pre ~void(self) and (loc > 0) post (indices.size = size) is -- This routine scans the buffer and sets up a new index list from -- the actual contents. loc_bin : BINSTR := binstr ; loc_index : CARD := 0 ; indices := FLIST{CARD}::create ; -- a new empty list! loop loc_elem : BINSTR := loc_bin.chunk!(index_lib.my_size) ; if ~(CHAR_CODE::create(loc_elem,index_lib)).is_combining then indices := indices.push(loc_index) end ; loc_index := loc_index + index_lib.my_size end end ; append_file( name : STR ) : SAME pre true post (result = self) -- if file couldn't be found or (result.size > initial(size)) -- and contains the file contents is -- This routine attempts to open the file which has the given name. If -- successful then the contents of the file are appended to self which is -- returned after closing the file. -- -- NOTE If there is a file reading error then an exception is raised! fyle : TEXT_FILE := TEXT_FILE::open_for_read(name) ; if void(fyle) then return self end ; loc_buff : SAME := fyle.frunes ; fyle.close ; res : SAME ; if void(self) then res := loc_buff ; res.priv_lib := REP_LIB_LIST::index(LIBCHARS::default) else loc_buff.priv_lib := priv_lib ; res := self + loc_buff end ; res.buffer_scan ; return res end ; append_file_range( name : STR, start, size : CARD ) : SAME pre true post (result = self) -- if file couldn't be found or (result.size > initial(size)) -- and contains the file contents is -- This routine attempts to open the named file and append the contents -- (starting at start for size octets) to self. If the file cannot be opened -- then nothing is done. fyle : REFERENCE := FILE_SYS::open(name,FILE_MODES::Read_Text) ; if void(fyle) then return self end ; file_size : CARD ; if ~FILE_SYS::size(fyle,out file_size) then return self end ; if file_size = 0 then return self end ; actual_size : CARD := (file_size - start).min(size) ; -- in octets res : SAME ; buffer_start : CARD ; if void(self) then res := create(actual_size,LIBCHARS::default) ; buffer_start := 0 ; res.loc := actual_size elsif actual_size <= (actual_size - loc) then res := self ; buffer_start := loc ; res.loc := loc + actual_size else res := create((2 * asize).max(loc + actual_size),index_lib) ; res.acopy(self) ; buffer_start := loc ; res.loc := loc + actual_size end ; -- NOTE This reading routine starts to store data at -- the buffer_start position, not necessarily its beginning. if ~FILE_SYS::file_read(res,actual_size,inout buffer_start,start,fyle) then SYS_ERROR::create.error(self,SYS_EXCEPT::Access_Error,name) end ; FILE_SYS::close(fyle) ; res.buffer_scan ; -- set up index list! return res end ; separate!( str : RUNES ) : RUNES pre ~void(str) and ~void(self) and (index_lib = str.index_lib) post (result.str = str.str) or (result.str = self.str + str.str) is -- On the first iteration this iter yields the string str. On successive -- iterations it yields self followed by str. Created for use in forming -- lists whose elements are separated by self. yield str ; loc_fstr : SAME := create(index_lib) + str ; loop num : CARD := (loc + str.asize) / index_lib.my_size ; fstr : SAME := create(num,index_lib) ; fstr.loc := num ; fstr.acopy(self) ; fstr.acopy(loc,loc_fstr) ; yield fstr.runes end end ; runes : RUNES pre ~void(self) post ~void(result) -- |||recursive||| create(result) = self is -- This routine returns a text string version of self. return RUNES::from_frunes(self) ; end ; end ; -- FRUNES