utf8u tag proposal

William Spitzak <[email protected]>
Newsgroups gmane.text.yaml.general
Message-ID <[email protected]>
Okay I tried to type up a formal proposal for the !!utf8u tag. I based 
this on a !!binary proposal I found.

Sorry about the plain text but I figured this would make it easier for 
somebody to put it in a wiki.

Comments/changes please!

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july

_______________________________________________
Yaml-core mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/yaml-core
utfu_draft (text/plain, 7.7 KB)
Invalid UTF Type for YAML Version 0.1

Draft of proposal.

Author:
Bill Spitzak
<[email protected]>

Copyright 2009...

This document may be freely copied provided it is not modified.

STATUS

This specification is a draft reflecting consensus reached by members
of the yaml-core mailing list. Any questions regarding this draft
should be raised on this list.

----------------------------------------------------------------

URI:
        tag:yaml.org.2009:utf8u

Shorthand:
        !!utf8u

Kind:
        Scalar

Canonical:
        (%[0-9a-f][0-9a-f])*

Regexp:
        .* (any string is accepted!)

Definition:
        A sequence of zero or more bytes (8-bit values).

        The sequence "%xx" where x are hex digits (0-9,A-F,a-f)
        represents a single byte with the value equal to the hex
        number. "%20" is a single byte with value 0x20.

        A '%' not followed by two hex digits represents a single
        0x25 byte (the ASCII/UTF-8 value of '%') and parsing continues
        with the next byte ("%%20" is a 0x25 followed by a 0x20).

        All other characters are converted into their one to four
        byte UTF-8 representation.

Examples (these are all the same string):

        - !!utf8u A-acute is Á in Unicode
        - !!utf8u "A-acute is \xC1 in Unicode"
        - !!utf8u A-acute is %C3%81 in Unicode
        - !!utf8u
           "%41%2d%61%63%75%74%65%20%69%73%20%c3\
            %81%20%69%6e%20%55%6e%69%63%6f%64%65"

----------------------------------------------------------------

RATIONALE:

Many systems process UTF-encoded Unicode but ignore errors in the
encoding until display. This is often far easier and more reliable and
avoids security problems and/or DOS attacks. It also allows
conversions during display that are useful for the end user but would
be dangerous at any earlier stage (such as using a different
encoding).

Examples are Unix UTF-8 filenames, Windows UTF-16 in almost all apis
including filenames, %-encoded sequences in URLs, and many HTML
documents marked as UTF-8.

Experience has shown that if the storage damages *valid* UTF-8 or
makes it difficult to insert in a file, the user's response is usually
to treat the data as being in a different encoding such as
ISO-8859-1. Often this response is so common that interoperability
requires redefining the original data as being this other encoding.

Therefore we require a format that can store an invalid UTF array but
will read and write a *valid* encoding with as few changes as
possible, and utf8u is designed for this.

The format was chosen to match the %-encoding scheme used in URLs, and
is compatible with it. However utf8u also allows strings that are not
valid URLs: it can contain any Unicode character unchanged.

A '%' not followed by two hex digits is literal. This was chosen for the
following reasons:

1. Makes "%%", which is often used to escape a '%' in other systems,
work as a literal.

2. Minimizes the changes to valid strings.

3. Throwing an error when it is obvious and unambiguous what the
string means is not user-friendly.

4. Makes it impossible to "extend" this tag with new %-escapes. This
is a purposely-designed feature.

ENCODING NOTES:

The simples encoder would follow the "canonical" rules and replace
every byte with "%xx", however this will make the string unreadable in
the saved file and this is not recommended. An encoder should instead
do some or all of the following steps so as little of valid UTF-8 is
changed when written:

 1. Write all bytes without the high bit set except '%' unchanged.

 2. Any sequence of bytes that is a valid UTF-8 encoding is written as
the Unicode character (the UTF-8 encodings of U+D800..U+DFFF are *not*
valid and must remain written as three %xx sequences).

 3. If the two characters after a '%' are not hex digits then you do
not need to encode the '%' and can write it literally.

 4. If nothing except '%' needs to be encoded, then don't use the
utf8u tag at all and write the string as a normal YAML scalar.

DECODING NOTES:

You MUST check the two characters after a '%' and leave the '%'
unchanged if they are not a pair of hex digits. A '%' less than two
characters from the end of the string must also be unchanged.

Backslash removal is done by yaml before the decoding. Therefore:

1. "\x25\x32\x30" is a single 0x20 byte (because yaml converts the \x
sequences into "%20"). WRITERS SHOULD NOT RELY ON READERS DOING THIS
CORRECTLY!

2. "%5cx20" is the four bytes '\','x','2','0'. It is not a space
character. This is part of the canonical defintion so you must do it
correctly and writers can assume it.

----------------------------------------------------------------
UTF-16:

Because invalid UTF-16 (and any array of 16-bit words) can be
losslessly converted to "invalid" UTF-8, this may also be used to
store invalid UTF-16.

This may be a good idea rather than making yet another tag for invalid
UTF-16. In particular it means filenames and other text data may use
the same tag on both Unix and Windows (the fact that Unix can store a
superset of strings is irrelevant as programs must already deal with
this due to Unix accepting more punctuation marks).

Programs that wish to avoid dealing with UTF-8 can use these rules to
convert their UTF-16:

ENCODING NOTES:

All words other than the surrogate halves and '%' are encoded unchanged as a
Unicode character.

A '%' can be written as "%25". This is not required if the next two
characters are not hex digits.

A high+low surrogate pair (ie *valid* UTF-16) is encoded as the
matching Unicode character.

Each mismatched surrogate half is encoded as "%nn%nn%nn" where nn are
the hex values of the UTF-8 encoding of that word's value.

If there are no mismatched surrogate halves, the program may wish to
omit the tag and write the value as a normal scalar.

DECODING NOTES:

Decoder can use all characters except '%' unchanged.

It must accumulate up to 6 "%nn" sequences where n is a hex
digit. Decode this into up to 6 values, which I will call "bytes" for
obvious reasons. Notice that non-%-sequences do not need to be merged
in any way.

If the leading 1-4 "bytes" are a valid UTF-8 encoding then replace that
portion with the matching Unicode character, and start again after it.

If the leading 3 "bytes" are the UTF-8 encoding of a low surrogate half
U+DC00..U+DCFF then replace that portion with the surrogate half.

If the leading 3 "bytes" are the UTF-8 encoding of a high surrogate half
U+D800..U+DBFF *and* there are *not* 3 bytes after it that are the valid
encoding of a low surrogate half, then replace that portion with the
surrogate half.

All other byte sequences should trigger an error, of similar severity
as libyaml failing to parse the file. The string could not possibly
have been a UTF-16 array originally. However it may be useful for the
converter to provide access to a "sanitized" converted string after
reporting the error. This sanitized string should contain the
following conversions:

The 6 "byte" sequence of a matching hi+low surrogate pair is converted
to the matching hi+low surrogate pair and thus a single Unicode character.

All other sequences convert the first "byte" to 0xDCxx and then
continue decoding after it.

----------------------------------------------------------------
UTF-32:

It is also possible that this can write invalid UTF-32.

This could be done by extending the definition of UTF-8 to 32 bit
numbers, and then working similar to the UTF-16 description above,
although it is much easier as surrogate halves can always be decoded.

The original UTF-8 was defined up to 31 bit numbers and there are two
possibilities for 32-bit numbers:

1. Use both 0xFE and 0xFF followed by 5 trailing bytes.
2. Use 0xFE followed by 6 trailing bytes (allowing up to 36-bit numbers)

In any case until an actual use case comes up this is probably a minor
consideration.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.