Tcl Source Code

Check-in [068401d9ac]
Login
EuroTcl/OpenACS 11 - 12 JULY 2024, VIENNA

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Handle ambiguous ICU encoding name aliases
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apn-icu
Files: files | file ages | folders
SHA3-256: 068401d9acbb5e04a0ea6c371fb831b802d4a9e122b8e8e6bfc7a1324ece2e0f
User & Date: apnadkarni 2024-06-19 03:13:52
Context
2024-06-20
07:42
Add basic tests check-in: 0562381402 user: apnadkarni tags: apn-icu
2024-06-19
03:13
Handle ambiguous ICU encoding name aliases check-in: 068401d9ac user: apnadkarni tags: apn-icu
02:25
Add missing files check-in: 078bef4577 user: apnadkarni tags: apn-icu
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclIcu.c.

19
20
21
22
23
24
25

26
27
28
29
30
31
32
33
 */
typedef enum UBreakIteratorTypex {
	  UBRK_CHARACTERX = 0,
	  UBRK_WORDX = 1
} UBreakIteratorTypex;

typedef enum UErrorCodex {

    U_ZERO_ERRORZ              =  0     /**< No error, no warning. */
} UErrorCodex;

#define U_SUCCESS(x) ((x)<=U_ZERO_ERRORZ)
#define U_FAILURE(x) ((x)>U_ZERO_ERRORZ)

struct UEnumeration;
typedef struct UEnumeration UEnumeration;







>
|







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 */
typedef enum UBreakIteratorTypex {
	  UBRK_CHARACTERX = 0,
	  UBRK_WORDX = 1
} UBreakIteratorTypex;

typedef enum UErrorCodex {
    U_AMBIGUOUS_ALIAS_WARNING = -122,
    U_ZERO_ERRORZ              =  0,     /**< No error, no warning. */
} UErrorCodex;

#define U_SUCCESS(x) ((x)<=U_ZERO_ERRORZ)
#define U_FAILURE(x) ((x)>U_ZERO_ERRORZ)

struct UEnumeration;
typedef struct UEnumeration UEnumeration;
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427

428
429
430
431
432
433
434
435
436
    if (ucnv_countAliases == NULL || ucnv_getAlias == NULL) {
	return FunctionNotAvailableError(interp);
    }

    const char *name = Tcl_GetString(objv[1]);
    UErrorCodex status = U_ZERO_ERRORZ;
    uint16_t count = ucnv_countAliases(name, &status);
    if (U_FAILURE(status)) {
	return IcuError(interp, "Could not get aliases.", status);
    }
    if (count <= 0) {
	return TCL_OK;
    }
    Tcl_Obj *resultObj = Tcl_NewListObj(count, NULL);
    uint16_t i;
    for (i = 0; i < count; ++i) {

	const char *aliasName = ucnv_getAlias(name, i, &status);
        if (U_FAILURE(status)) {
	    status = U_ZERO_ERRORZ; /* Reset error for next iteration */
	    continue;
	}
	if (aliasName) {
	    Tcl_ListObjAppendElement(
		NULL, resultObj, Tcl_NewStringObj(aliasName, -1));
	}







|








>

|







413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
    if (ucnv_countAliases == NULL || ucnv_getAlias == NULL) {
	return FunctionNotAvailableError(interp);
    }

    const char *name = Tcl_GetString(objv[1]);
    UErrorCodex status = U_ZERO_ERRORZ;
    uint16_t count = ucnv_countAliases(name, &status);
    if (status != U_AMBIGUOUS_ALIAS_WARNING && U_FAILURE(status)) {
	return IcuError(interp, "Could not get aliases.", status);
    }
    if (count <= 0) {
	return TCL_OK;
    }
    Tcl_Obj *resultObj = Tcl_NewListObj(count, NULL);
    uint16_t i;
    for (i = 0; i < count; ++i) {
        status = U_ZERO_ERRORZ; /* Reset in case U_AMBIGUOUS_ALIAS_WARNING */
	const char *aliasName = ucnv_getAlias(name, i, &status);
        if (status != U_AMBIGUOUS_ALIAS_WARNING && U_FAILURE(status)) {
	    status = U_ZERO_ERRORZ; /* Reset error for next iteration */
	    continue;
	}
	if (aliasName) {
	    Tcl_ListObjAppendElement(
		NULL, resultObj, Tcl_NewStringObj(aliasName, -1));
	}

Changes to library/icu.tcl.

16
17
18
19
20
21
22




23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42




43
44
45
46
47
48
49
::tcl::unsupported::loadIcu

namespace eval ::tcl::unsupported::icu {
    # Map Tcl encoding names to ICU and back. Note ICU has multiple aliases
    # for the same encoding.
    variable tclToIcu
    variable icuToTcl





    proc Init {} {
        variable tclToIcu
        variable icuToTcl

        # There are some special cases where names do not line up
        # at all. Map Tcl -> ICU
        array set specialCases {
            ebcdic ebcdic-cp-us
            macCentEuro maccentraleurope
            utf16 UTF16_PlatformEndian
            utf-16be UnicodeBig
            utf-16le UnicodeLittle
            utf32 UTF32_PlatformEndian
        }
        # Ignore all errors. Do not want to hold up Tcl
        # if ICU not available
        catch {
            foreach tclName [encoding names] {

                set icuNames [aliases $tclName]




                if {[llength $icuNames] == 0} {
                    # E.g. macGreek -> x-MacGreek
                    set icuNames [aliases x-$tclName]
                    if {[llength $icuNames] == 0} {
                        # Still no joy, check for special cases
                        if {[info exists specialCases($tclName)]} {
                            set icuNames [aliases $specialCases($tclName)]







>
>
>
>




<












|

>
|
>
>
>
>







16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
::tcl::unsupported::loadIcu

namespace eval ::tcl::unsupported::icu {
    # Map Tcl encoding names to ICU and back. Note ICU has multiple aliases
    # for the same encoding.
    variable tclToIcu
    variable icuToTcl

    proc LogError {message} {
        puts stderr $message
    }

    proc Init {} {
        variable tclToIcu
        variable icuToTcl

        # There are some special cases where names do not line up
        # at all. Map Tcl -> ICU
        array set specialCases {
            ebcdic ebcdic-cp-us
            macCentEuro maccentraleurope
            utf16 UTF16_PlatformEndian
            utf-16be UnicodeBig
            utf-16le UnicodeLittle
            utf32 UTF32_PlatformEndian
        }
        # Ignore all errors. Do not want to hold up Tcl
        # if ICU not available
        if {[catch {
            foreach tclName [encoding names] {
                if {[catch {
                    set icuNames [aliases $tclName]
                } erMsg]} {
                    LogError "Could not get aliases for $tclName: $erMsg"
                    continue
                }
                if {[llength $icuNames] == 0} {
                    # E.g. macGreek -> x-MacGreek
                    set icuNames [aliases x-$tclName]
                    if {[llength $icuNames] == 0} {
                        # Still no joy, check for special cases
                        if {[info exists specialCases($tclName)]} {
                            set icuNames [aliases $specialCases($tclName)]
58
59
60
61
62
63
64


65
66
67
68
69
70
71
                } else {
                    set tclToIcu($tclName) $icuNames
                }
                foreach icuName $icuNames {
                    lappend icuToTcl($icuName) $tclName
                }
            }


        }
        array default set tclToIcu ""
        array default set icuToTcl ""

        # Redefine ourselves to no-op.
        proc Init {} {}
    }







>
>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
                } else {
                    set tclToIcu($tclName) $icuNames
                }
                foreach icuName $icuNames {
                    lappend icuToTcl($icuName) $tclName
                }
            }
        } errMsg]} {
            LogError $errMsg
        }
        array default set tclToIcu ""
        array default set icuToTcl ""

        # Redefine ourselves to no-op.
        proc Init {} {}
    }