RFC Wide Characters in I/O

Janne Blomqvist blomqvist.janne@gmail.com
Fri May 16 21:48:00 GMT 2008


Jerry DeLisle wrote:
> Modify the front-end in trans-io.c to build a call to a new function 
> called transfer_wide_character. This function is used if we have an 
> ENCODING= specifier or a wide character to transfer. This will retain 
> the existing transfer_character call to maintain compatibility.
> 
> Repeating myself, the new function will be used for kind > 1, while 
> transfer_character is retained for kind=1 and hollerith as is.

This sounds good. As you imply, I agree that it's ok to restrict 
hollerith to plain ASCII, as hollerith was removed before any support 
for non-ASCII was added to the Fortran standard.

> The downstream functions in the library such as list_formatted_read, 
> list_formatted_write, formatted_transfer, unformatted_read, 
> unformatted_write, already accept a kind parameter which 
> transfer_character sets to 1.

Yes. But needless to say, there's probably a number of bugs lurking 
there since so far kind has always been 1.

> If we are given a wide character to transfer as unformatted, we simply 
> transfer all the bytes as is. (I will confirm with the standard on this.)

Yes, I think this is ok.

> If the user has specified an ENCODING="default" [snip]... If kind is greater 
> than 1, I suggest we transfer each byte as is.  So for kind=4, we would 
> transfer 4 bytes.

Like FX said on IRC, I think the sensible thing here would be to convert 
each external byte into a 4-byte internal representation. Anything else 
would be very confusing, IMHO.

> This would enable doing some packed 4x1 byte character 
> stuff.

??

> (Note: It is my understanding, in reading about UTF-8, that it is 
> internally represented by a fixed width 4 byte hexidecimal number which 
> when transfered to an external file, is translated on the fly into a 
> variable width encoding.  When reading back in, it is translated back to 
> the 4 byte code.)

To clarify, Unicode basically is a mapping between integer numbers 
("code points" in unicode jargon) and characters. UTF-8 is a particular 
encoding for Unicode, encoding the code points into a variable number of 
8-bit octets (with the nice property that the first 127 are backwards 
compatible with ASCII). UTF-8 thus has no concept of internal, external, 
in-memory or on-disk formats.

In practice, what we want to do is exactly what you describe. I.e. 
externally data is UTF-8 encoded, and is converted to a fixed width 
4-byte representation in memory for easier handling.

> If the user has specified an ENCODING="UTF-8" and the kind is less than 
> 4, strictly speaking, thats an error, but we can give a warning and 
> assume a truncation. In other words, the upper most bytes of a 4 byte 
> representation are assumed to be zero and we transfer after translating 
> hex-to-utf8 (or likewise utf8-to-hex).  If on reading  we encounter an 
> encoding that will not fit in the given character kind, we throw a 
> runtime error "Character encoding exceeds KIND=2 at %L" or similar.

I think the usual thing is to use a "?" or something like that for a 
non-representable character, rather than a runtime error.

> For kind=4 and ENCODING="UTF-8", we do a complete conforming translation 
> of the 4 byte hex to/from the variable width UTF-8 encoding.

Yeah; there's probably library functions available for doing a lot of 
these conversions back and forth. One problem here might be that wchar_t 
is not 32 bits on all platforms, so perhaps we can't rely on the libc 
wide char functions?

-- 
Janne Blomqvist



More information about the Fortran mailing list