converter.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 CODE_CONVERTER < $CODE_CONVERTER
class CODE_CONVERTER < $CODE_CONVERTER is
-- This class defines an object which provides code conversion services
-- to and from any registered character encoding. It consists of conversion
-- routines based around a map from code kinds to code mappers.
-- The routines provided merely dispatch to the appropriate code
-- mapper. If the mapper is not loaded then the first attempt to map loads
-- it from file before carrying out the mapping.
-- Version 1.1 Mar 99. Copyright K Hopper, U of Waikato
-- Development History
-- -------------------
-- Date Who By Detail
-- ---- ------ ------
-- 30 Oct 98 kh Original after a Perl script
-- 26 Mar 99 kh Revised for V8 of text classes
private shared mappings : FMAP{CODE_KINDS,CODE_MAPPER} ;
private init is
-- This routine initialises the shared components of the class as
-- required. Note that this is only done once.
if void(mappings) then
mappings := FMAP{CODE_KINDS,CODE_MAPPER}::create
end
end ;
insert(
kind : CODE_KINDS,
map : CODE_MAPPER
)
pre ~void(map)
and ~void(kind)
post true
is
-- This routine is provided to insert a new map for the corresponding
-- code kind.
init ;
mappings := mappings.insert(kind,map)
end ;
map(
kind : CODE_KINDS
) : CODE_MAPPER
pre ~void(kind)
post true
is
-- This routine returns the mapper for the given code kind - which may,
-- of course, be void if no mapping has been done using that mapper.
return mappings.get(kind)
end ;
private check_for_map(
kind : CODE_KINDS
)
pre ~void(kind)
and ~(kind = CODE_KINDS::Unicode)
post ~void(mappings.get(kind)) -- or an exception has been raised
is
-- This routine is called before any mapping action involving an actual
-- map look-up to ensure that the mapper is available. If either the file
-- path is not found or is invalid or the file is inaccessible then an
-- exception is raised.
init ;
if ~mappings.test(kind) then
loc_res : CODE_MAPPER ;
if (kind = CODE_KINDS::UCS2)
or (kind = CODE_KINDS::UCS4) then
loc_res := CODE_MAPPER::create(kind)
else
raiser : SYS_ERROR := SYS_ERROR::create ;
loc_path : FILE_PATH := MAP_FILE::path(kind) ;
if void(loc_path) then -- Arrrrggh! Fatal error!!
raiser.error(self,SYS_EXCEPT::Bad_Name,kind.str)
end ;
loc_res := CODE_MAPPER::create(kind,loc_path)
end ;
mappings := mappings.insert(kind,loc_res)
end
end ;
char(
kind : CODE_KINDS,
val : RUNE
) : CHAR
pre ~void(kind)
and ~void(val)
and (val.lib.has_combining)
post true -- although if 'null' is not a valid char!
is
-- This routine attempts to convert the rune value given into its
-- code equivalent in the given character code.
check_for_map(kind) ;
return CHAR::create(map(kind).from_unicode(val.code))
end ;
char(
kind : CODE_KINDS,
val : CHAR_CODE
) : CHAR
pre ~void(kind)
and ~void(val)
and (val.lib.has_combining)
post true -- although if 'null' is not a valid char!
is
-- This routine attempts to convert the rune value given into its
-- code equivalent in the given character code.
check_for_map(kind) ;
return CHAR::create(map(kind).from_unicode(val))
end ;
code(
lib : LIBCHARS,
val : CHAR
) : CHAR_CODE
pre ~void(lib)
and ~void(val)
and ~lib.has_combining
post true -- although if 'null' is not a valid char!
is
-- This routine attempts to convert the character value given (assumed
-- to be in the given encoding) into its unicode equivalent.
loc_kind : CODE_KINDS := lib.culture.kind ;
check_for_map(loc_kind) ;
return map(loc_kind).to_unicode(CHAR_CODE::create(val,lib))
end ;
code(
to : LIBCHARS,
val : RUNE
) : CHAR_CODE
pre ~void(to)
and ~void(val)
and val.lib.has_combining
and ~to.has_combining
post true -- although if 'null' is not a valid char!
is
-- This routine attempts to convert the rune value given into its
-- code equivalent in the first character code in the rune.
loc_kind : CODE_KINDS := to.culture.kind ;
check_for_map(loc_kind) ;
return map(loc_kind).from_unicode(val.code)
end ;
code(
kind : CODE_KINDS,
val : CHAR_CODE
) : CHAR_CODE
pre ~void(kind)
and ~void(val)
and (val.lib.has_combining
or (kind = CODE_KINDS::Unicode)
or (kind = CODE_KINDS::UCS2)
or (kind = CODE_KINDS::UCS4))
post true -- although if 'null' is not a valid char!
is
-- This routine attempts to convert the code value given into its
-- code equivalent in the code kind given.
if kind = val.lib.culture.kind then -- nothing to do!
return val
elsif ~val.lib.has_combining then
check_for_map(val.lib.culture.kind) ;
return map(val.lib.culture.kind).to_unicode(val)
else
check_for_map(kind) ;
return map(kind).from_unicode(val)
end
end ;
rune(from : LIBCHARS, val : CHAR) : RUNE
pre ~void(from) and ~(from.culture.kind = CODE_KINDS::Unicode)
post ~void(result)
is
-- This routine returns the rune encoding (Unicode) given the character
-- value in the indicated encoding.
loc_kind : CODE_KINDS := from.culture.kind ;
check_for_map(loc_kind) ;
return RUNE::create(map(loc_kind).to_unicode(CHAR_CODE::create(val,from)))
end ;
rune(
val : CHAR_CODE
) : RUNE
pre ~void(val)
and ~val.lib.has_combining
post ~void(result)
is
-- This routine returns the rune encoding (Unicode) given the value
-- character in the indicated encoding.
check_for_map(val.lib.culture.kind) ;
return RUNE::create(map(val.lib.culture.kind).to_unicode(val))
end ;
rune(
to_code : CODE_KINDS,
val : RUNE
) : RUNE
pre ~void(to_code)
and val.lib.has_combining
and ~((to_code = CODE_KINDS::Unicode)
or (to_code = CODE_KINDS::UCS2)
or (to_code = CODE_KINDS::UCS4))
and (val.size = 1)
post ~void(result)
is
-- This routine returns the rune encoding (Unicode) given the character
-- value in the indicated encoding.
check_for_map(to_code) ;
return RUNE::create(map(to_code).from_unicode(val.code))
end ;
runes(
from : LIBCHARS,
val : CHAR
) : RUNES
pre ~void(from)
and ~from.has_combining
post ~void(result)
is
-- This routine returns the rune encoding (Unicode) given the character
-- value in the indicated encoding.
loc_kind : CODE_KINDS := from.culture.kind ;
check_for_map(loc_kind) ;
return RUNES::create(RUNE::create(map(loc_kind).to_unicode(
CHAR_CODE::create(val,from))))
end ;
runes(
val : STR
) : RUNES
pre ~void(val)
and ~(val.index_lib.has_combining)
post (result.size = val.size)
is
-- This routine returns the rune (Unicode code value) string which
-- corresponds to val which is indicated to be of the given code kind.
loc_kind : CODE_KINDS := val.index_lib.culture.kind ;
check_for_map(loc_kind) ;
loc_map : CODE_MAPPER := map(loc_kind) ;
test : CHAR_CODE := loc_map.to_unicode(val[0].code) ;
res : RUNES := RUNES::create(test.lib) ;
loop
in_code : CHAR_CODE := val.elt!.code ;
out_code : CHAR_CODE := loc_map.to_unicode(in_code) ;
loc_rn : RUNE := out_code.rune ;
res := res + loc_rn
end ;
return res
end ;
runes(
val : CODE_STR
) : RUNES
pre ~void(val)
and ~val.lib.has_combining
post (result.size = val.size)
is
-- This routine returns the rune (Unicode code value) string which
-- corresponds to val which is indicated to be of the given code kind.
loc_kind : CODE_KINDS := val.lib.culture.kind ;
check_for_map(loc_kind) ;
loc_map : CODE_MAPPER := map(loc_kind) ;
test : CHAR_CODE := loc_map.to_unicode(val[0]) ;
res : RUNES := RUNES::create(test.lib) ;
loop
res := res + map(loc_kind).to_unicode(val.elt!).rune
end ;
return res
end ;
runes(
lib : LIBCHARS,
val : RUNES
) : RUNES
pre ~void(val)
and ~void(lib)
and (lib.has_combining
or val.index_lib.has_combining)
and ~(lib.has_combining
and val.index_lib.has_combining)
post (result.size = val.size)
is
-- This routine returns the rune string which corresponds to val which
-- may be of any kind. If it is a Unicode representation then the result is
-- of the given code kind (which may not be a Unicode form) or vice versa.
res : RUNES := RUNES::create(val.index_lib) ;
if val.index_lib.has_combining then
check_for_map(val.index_lib.culture.kind) ;
loop
loc_ch : CHAR_CODE := map(
val.index_lib.culture.kind).to_unicode(val.code!) ;
if void(loc_ch) then
return void
end ;
res := res + RUNE::create(loc_ch)
end
else -- it is already unicode
check_for_map(lib.culture.kind) ;
loop
loc_ch : CHAR_CODE := map(
lib.culture.kind).from_unicode(val.code!) ;
if void(loc_ch) then
return void
end ;
res := res + RUNE::create(loc_ch)
end
end ;
return res
end ;
str(
to_lib : LIBCHARS,
val : RUNES
) : STR
pre ~void(val)
and ~void(to_lib)
and val.index_lib.has_combining
post result.size = val.size
is
-- This routine returns the character string of the given code kind
-- which corresponds to the val (Unicode encoded) argument. If one or more
-- elements cannot be mapped then a 'null' code is inserted.
check_for_map(to_lib.culture.kind) ;
res : STR := STR::create(to_lib) ;
loop
loc_ch : CHAR := CHAR::create(map(to_lib.culture.kind).from_unicode(
val.elt!.code)) ;
res := res + loc_ch
end ;
return res
end ;
codes(
to_lib : LIBCHARS,
val : RUNES
) : CODE_STR
pre ~void(val)
and ~void(to_lib)
and (to_lib.has_combining
or val.index_lib.has_combining)
and ~(to_lib.has_combining
and val.index_lib.has_combining)
post (result.size >= val.size)
is
-- This routine returns the character code string of the given code kind
-- which corresponds to the val argument. If one or more elements cannot
-- be mapped then void is inserted.
res : CODE_STR := CODE_STR::create(val.index_lib) ;
if (to_lib.culture.kind = CODE_KINDS::Unicode) then
check_for_map(val.index_lib.culture.kind) ;
loop
loc_rune : RUNE := val.elt! ;
loop
loc_ch : CHAR_CODE := map(val.index_lib.culture.kind
).to_unicode(loc_rune.code!) ;
res := res + loc_ch
end
end
else -- it is already unicode
check_for_map(to_lib.culture.kind) ;
loop
loc_rune : RUNE := val.elt! ;
loop
loc_ch : CHAR_CODE := map(
to_lib.culture.kind).from_unicode(loc_rune.code!) ;
res := res + loc_ch
end
end
end ;
return res
end ;
end ; -- CODE_CONVERTER