Converting UC_STRING to/from C pointer to UTF8 octet sequences

Paul Cohen <[email protected]> Mon, 18 May 2009 12:51:31 +0200
Newsgroups gmane.comp.lang.eiffel.gobo.devel
Message-ID <[email protected]>
Hi all,

I need some advice/feedback on how to convert/create a UC_STRING from
a C pointer to a UTF8 byte sequence (and vice versa). I can't find any
routines or examples in the Gobo unicode library for doing it. The
need for this arises when writing Eiffel shared libraries (with
C-style API:s).

This is my current appach:

    uc_string_from_utf8_pointer (p: POINTER): UC_STRING is
            -- New UC_STRING object from UTF8 octet sequence pointed to by `p'.
        require
            p_not_default_pointer: p /= default_pointer
        local
            utf8: STRING_8
        do
            create utf8.make_from_c (p)
            create Result.make_from_utf8 (utf8)
        ensure
            result_not_void: Result /= Void
        end

It is unfortunate that I have to create two "string objects" to
perform the "conversion".

Returning a pointer to a UTF8 octet sequence is trickier. An initial
approach could be:

    utf8_pointer_from_uc_string (s: UC_STRING): POINTER is
            -- A pointer to the UTF8 octet sequence of `s'.
        require
            s_not_void: s /= Void
        local
            utf8: STRING_8
            a: ANY
        do
            utf8 := s.to_utf8
            a := utf8.to_c
            Result := $a
        ensure
            result_not_default_pointer: Result /= default_pointer
        end

This is not a good solution since 'utf8' and its memory area may not
be available any longer when the client tries to access the octet
sequence (they are on the stack). Many C API:s are written so that the
caller must supply a memory buffer that the API implementation uses
for returning the result, leaving the caller responsable for memory
management. So a better approach would maybe be something like:

    fill_utf8_buffer_from_uc_string (s: UC_STRING; buffer: STRING_8) is
            -- Fill the buffer with the UTF8 octet sequence of `s'.
        require
            s_not_void: s /= Void
            buffer_not_void: buffer /= Void
            buffer_large_enough: s.to_utf8.count <= buffer.count
        local
            utf8: STRING_8
            a: ANY
            p_buffer, p_utf8: POINTER
        do
            utf8 := s.to_utf8
            a := buffer.to_c
            p_buffer := $buffer
            a := utf8.to_c
            p_utf8 := $a
            p_buffer.memory_copy (p_utf8, utf8.count)
        end

Yet another approach would be for the Eiffel class that implements the
API to maintain a buffer of memory where the returned result is put.
However then one will run into multprogramming problems with accessing
shared data.

Any feedback on this issue would be welcome!

/Paul

-- 
Paul Cohen
www.seibostudios.se
mobile: +46 730 787 035
e-mail: [email protected]

------------------------------------------------------------------------------
Crystal Reports - New Free Runtime and 30 Day Trial
Check out the new simplified licensing option that enables 
unlimited royalty-free distribution of the report engine 
for externally facing server and web deployment. 
http://p.sf.net/sfu/businessobjects