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