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