str.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 STR < $TEXT_STRING{CHAR,FSTR,STR}, $OPTION, $EXTERNAL_REF, $ANCHORED_FMT

class STR < $TEXT_STRING{CHAR,FSTR,STR}, $OPTION, $EXTERNAL_REF, $ANCHORED_FMT is -- This class provides a string implementation in which each character -- has a single encoding. The strings are provided with immutable semantics. -- Any literal strings used in the program text are of this class. -- -- NOTE 1. Where the local environment encoding differs from that in the -- compilation environment then literal text strings are unlikely to be -- meaningful - except by happenstance! -- -- 2. This class may be used for any encoding for which there are no -- combining characters. However, it is primarily intended for -- characters as known in the program execution environment. The -- classes OCT_STR, HEX_STR and QUAD_STR are available for other string -- manipulations as required - although they do not embody value -- conversions to or from text representations. -- Version 1.4 Apr 99. Copyright K Hopper, U of Waikato -- Development History -- ------------------- -- Date Who By Detail -- ---- ------ ------ -- 11 May 96 kh Original from Sather STR class -- 8 Nov 96 kh Now uses generic base class. -- 5 Apr 97 kh Modified for INT to CARD -- 13 Oct 98 kh Revised and added pre/post conditions -- 13 Apr 99 kh Completely re-written for V8 of text classes include TEXT_STRING{CHAR,FSTR} ; include STR_STR ; readonly attr width : CARD ; -- the width as determined from OS raw_create(length : CARD) : SAME is -- This routine must NOT be used outside the required library where it -- has a special function in determining the local character sizes. me : SAME := new(length) ; me.priv_lib := CARD::nil ; -- out of range! me.width := 0 ; return me end ; create(sz : CARD, lib : LIBCHARS) : SAME is -- This routine is the 'general' creation one which is called by all of -- the others in which the size is expected to be the number of character codes! me : SAME := new(sz * lib.my_size) ; me.priv_lib := REP_LIB_LIST::index(lib) ; me.width := lib.my_size ; return me end ; create(lib : LIBCHARS) : SAME is -- This routine returns an empty character string. return create(0,lib) end ; create(sz : CARD) : SAME is -- This routine is the version of creation which assumes the default -- cultural repertoire and environment. return create(sz,LIBCHARS::default) end ; create : SAME is -- This routine returns an empty character string. return create(0,LIBCHARS::default) end ; create(ch : CHAR, lib : LIBCHARS) : SAME is -- This routine creates and then returns a single element character string. me : SAME := create(1,lib) ; me[0] := ch ; return me end ; create(ch : CHAR) : SAME is -- This routine creates and then returns a single element character string. return create(ch,LIBCHARS::default) end ; create(ch_code : CHAR_CODE) : SAME is -- This routine creates a new single character string from the argument. return create(ch_code.char,ch_code.lib) end ; create(rns : RUNES) : SAME pre ~void(rns) and (rns.index_lib = index_lib) post (result.size = rns.size) is -- This routine attempts to create a new character string from the given -- rune string, using the same repertoire and encoding - provided that there -- are no combining codes detected during creation. In this case void is -- returned. lgth : CARD := rns.size ; -- NO combining codes! res : SAME := create(rns.size,rns.index_lib) ; index : CARD := 0 ; loop loc_ch : RUNE := rns.elt! ; if loc_ch.size > 1 then -- it has combining codes! return void else res.aset(index,CHAR::create(loc_ch.code)) ; index := index + 1 end end ; return res end ; create_from_external_string(str_ref : REFERENCE, lib : LIBCHARS) : SAME pre ~void(str_ref) and ~void(lib) post ~void(result) is -- This routine creates a new string in the default repertoire and -- encoding from the external string indicated by str_ref. length : CARD := SATHER_ENGINE::strlen(str_ref) ; res : SAME := create(length,lib) ; dummy : REFERENCE := SATHER_ENGINE::memcpy(res.array_ptr,str_ref,length) ; return res end ; create_from_external_string(str_ref : REFERENCE) : SAME pre ~void(str_ref) post ~void(result) is -- This routine creates a new string in the default repertoire and -- encoding from the external string indicated by str_ref. return create_from_external_string(str_ref,LIBCHARS::default) end ; from_fstr(fstr : FSTR) : SAME pre ~void(fstr) post (result.size = fstr.size) is -- This routine converts the given fast character string into the normal -- string form (which has immutable semantics). res : SAME := create(fstr.size,fstr.index_lib) ; res.acopyn(fstr,fstr.loc) ; return res end ; cursor : STR_CURSOR pre ~void(self) post ~void(result) is -- This routine returns a cursor object corresponding to the contents of self. priv_lib := REP_LIB_LIST::index(index_lib) ; return STR_CURSOR::create(self) end ; private buffer_scan is -- This is a do-nothing dummy to satisfy some of the common TEXT_STRING requirements end ; size : CARD pre true post (void(self)and (result = 0)) or (result = asize / width) is -- This routine returns the number of characters in self, or zero if self is void. if void(self) then return 0 else if void(width) then -- a native string! priv_lib := REP_LIB_LIST::index(LIBCHARS::default) ; width := LIBCHARS::default.my_size end ; return asize / width end end ; private store_index(elem_index : CARD) : CARD pre (elem_index < size) post (result = (elem_index * width)) is -- This routine returns the store index corresponding to the given -- element_index for use where they may be different). return elem_index * width end ; aget(index : CARD) : CHAR pre ~void(self)and (index < size) post true is -- This routine is the 'array' indexing facility for accessing -- individual characters in the string, returning the value accessed. builtin STR_AGET_CARD end ; aset(index : CARD, elem : CHAR) pre ~void(self) and (index <= size) post true is -- This routine implements the facility to set the value of -- a character at the given position. builtin STR_ASET_CARD_CHAR end ; char(index : CARD) : CHAR pre (index < asize) post result = [index] is -- This routine returns the value of the character at the given index. -- It is a synonym for aget. return [index] end ; binstr : BINSTR pre ~void(self) post ~void(result) is -- This routine just returns a copy of self. It is provided for cases -- where it is necessary to put a text string into a binary stream of some kind. res : FBINSTR := FBINSTR::create ; loop res := res + aelt!; end ; return res.binstr; end ; convert(lib : LIBCHARS) : SAME pre ~void(lib) and ~lib.has_combining post true is -- This routine converts self to be in the given encoding and repertoire. -- If any character has no corresponding code then void is returned. if index_lib = lib then return copy else loc_res : RUNES := CODE_CONVERTER::runes(self) ; return CODE_CONVERTER::str(lib,loc_res) end end ; default_lib : SAME pre ~void(self) and ((priv_lib = CARD::nil) or (index_lib = LIBCHARS::default)) post true is -- This routine returns self (which must either be a literal - with -- invalid value (CARD::nil) - produced by the compiler OR already -- a string with the default repertoire and encoding!), using the same -- bit-pattern and setting the default library. if priv_lib = CARD::nil then return create_from_external_string(self.array_ptr,LIBCHARS::default) else return self end end ; private do_replace(old_ch, new_ch : CHAR) : SAME is -- This routine returns a copy of self which has had every occurrence of -- old_ch replaced by new_ch. loc_res : CODE_STR := CODE_STR::create(index_lib) ; loop ch : CHAR := elt! ; if ch = old_ch then ch := new_ch; end ; loc_res := loc_res + ch.code end ; return loc_res.tgt_str end ; replace(set : SAME, new_ch : CHAR) : SAME pre ~void(set) and ~void(self) and (set.priv_lib = priv_lib) post (result.size = self.size) is -- This routine returns a copy of self in which all occurrences of -- characters in set are replaced by new_ch. Self may be void. loc_res : CODE_STR := CODE_STR::create(index_lib) ; loop ch : CHAR := elt! ; if set.contains(ch) then ch := new_ch; end ; loc_res := loc_res + ch.code end ; return loc_res.tgt_str end ; escape(esc : CHAR, elist : SAME) : SAME pre ~void(self) and ~void(elist) and (priv_lib = elist.priv_lib) post (result.contains(esc) or (result = self)) is -- This routine returns a copy of self in which all characters occurring -- in elist and the character esc itself are preceded by the escape character. -- This is done in situ using a fast string. buf : FSTR := FSTR::create(width,index_lib) ; loop loc_ch : CHAR := elt! ; if elist.contains(loc_ch) or (loc_ch = esc) then buf := buf + esc end ; buf := buf + loc_ch end ; return from_fstr(buf) end ; split!(once ch : CHAR) : SAME pre true post (result.size >= 0) -- may be zero if two adjacent characters found is -- This iter yields successive substrings of self which are separated -- by the single character. The separating characters are omitted and the -- string yielded starts after the previous separating character up to and -- NOT including the next (or the end of self if not found). if void(self) then quit; end ; curr_loc : CARD := 0 ; -- Start of next string loop next_loc : CARD := search(ch,curr_loc) ; if next_loc /= CARD::nil then -- The character was found yield substring(curr_loc,next_loc - curr_loc) ; curr_loc := next_loc + 1 else -- not found so use rest of string yield substring(curr_loc,size - curr_loc) ; quit end end end ; separate!(str : SAME) : SAME pre ~void(str) and ~void(self) and (str.priv_lib = priv_lib) post (result = initial(str)) or (result = self + initial(str)) is -- On the first iteration just outputs str, on successive iterations it -- outputs self followed by str. Useful for forming lists, eg -- loop -- #OUT + comma.separate!(a.elt!) -- end ; yield str ; loop yield self + str; end; end ; pretty : STR pre ~void(self) post result.size >= (size + 2) -- the two quotation marks! is -- "self" -- This routine returns a copy of self surrounded by quotation marks -- in which all control codes are replaced by an octal string -- preceded by an escape character. -- This escape character is conventionally a reverse solidus. -- Should a quotation mark occur in the string this is also -- replaced by an octal string preceded by the escape character. buf : FSTR := FSTR::create(index_lib) ; buf := buf + index_lib.Quotation_Mark.char ; -- opening quote! loop ch : CHAR := elt! ; if ch.is_print then if ch = index_lib.Quotation_Mark.char or ch = index_lib.Escape.char then buf := buf + index_lib.Escape.char + ch.code(index_lib).card.oct_str else buf := buf + ch end else buf := buf + index_lib.Escape.char + ch.code(index_lib).card.oct_str end end ; buf := buf + index_lib.Quotation_Mark.char ; return buf.str end ; as_literal : STR pre ~void(self) and (size >= 2) and (void(index_lib) or (([0] = index_lib.Quotation_Mark.char) and ([size - 1] = index_lib.Quotation_Mark.char))) post result.pretty = self is -- This routine returns a string to the form it would have had before -- applying pretty to it. Thus -- -- str = str.pretty.as_literal -- -- If self is not in correct string literal format then void is returned. buf : FSTR := FSTR::create(index_lib) ; loc_cursor : STR_CURSOR := self.cursor ; loc_cursor.advance ; -- over the initial quotation mark loop ch : CHAR := loc_cursor.get_item ; if ch = index_lib.Escape.char then -- handle escaped material if loc_cursor.item.is_octal_digit then loc_val : CARD := CARD::build_based(loc_cursor,8) ; buf := buf.push(CHAR::create(CHAR_CODE::create(loc_val,index_lib))) else buf := buf.push(loc_cursor.get_item) end elsif ch = index_lib.Quotation_Mark.char then -- start or finish! if loc_cursor.is_done then -- 'tis the end! break! else -- mal-formed quoted string! return void end else buf := buf.push(ch) end end ; return buf.str end ; end ; -- STR