Santhosh Thottingal

My experiments with Freedom

UTF8Decoder
[info]santhoshtr
zabeehkhan was trying to code a Pashto (ps_AF) module for dhvani. And he told me that "it is not saying anything" :). So I took the code and found the problem. Dhvani has a UTF-8 decoder and UTF-16 converter. It was written by Dr. Ramesh Hariharan and was tested only with the unicode range of the languages in India. It was buggy for most of the other languages and there by the language detection logic and text parsing logic was failing. So I did some googling, went through the code tables of gucharmap and got some helpful information from here and here
So here is my new UTF8Decoder and converter
/*
UTF8Decoder.c
This program converts a utf-8 encoded string to utf-16 hexadecimal code sequence

UTF-8 is a variable-width encoding of Unicode.
UTF-16 is a fixed width encoding of two bytes

A UTF-8 decoder must not accept UTF-8 sequences that are longer than necessary to
encode a character. For example, the character U+000A (line feed) must be accepted from
a UTF-8 stream only in the form 0x0A, but not in any of the following five possible overlong forms:

  0xC0 0x8A
  0xE0 0x80 0x8A
  0xF0 0x80 0x80 0x8A
  0xF8 0x80 0x80 0x80 0x8A
  0xFC 0x80 0x80 0x80 0x80 0x8A

Ref: UTF-8 and Unicode FAQ for Unix/Linux http://www.cl.cam.ac.uk/~mgk25/unicode.html

Author: Santhosh Thottingal <santhosh.thottingal at gmail.com>
License: This program is licensed under GPLv3 or later version(at your choice)
*/
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
unsigned short
utf8_to_utf16 (unsigned char *text, int *ptr)
{

  unsigned short c;		/*utf-16 character */
  int i = 0;
  int trailing = 0;
  if (text[*ptr] < 0x80)	/*ascii character till 128 */
    {
      trailing = 0;
      c = text[(*ptr)++];
    }
  else if (text[*ptr] >> 7)
    {
      if (text[*ptr] < 0xE0)
	{
	  c = text[*ptr] & 0x1F;
	  trailing = 1;
	}
      else if (text[*ptr] < 0xF8)
	{
	  c = text[*ptr] & 0x07;
	  trailing = 3;
	}

      for (; trailing; trailing--)
	{
	  if ((((text[++*ptr]) & 0xC0) != 0x80))
	    break;
	  c <<= 6;
	  c |= text[*ptr] & 0x3F;
	}

    }
  return c;

}


/* for testing */
int
main ()
{
  char *instr = "സന്തോഷ് തോട്ടിങ്ങല്‍";	/* my name :) */
  int length = strlen (instr);
  int i = 0;

  for (; i < length;)
    {
      printf ("0x%.4x ", utf8_to_utf16 (instr, &i));
    }
  printf ("\n");
/* output is:
0x0d38 0x0d28 0x0d4d 0x0d24 0x0d4b 0x0d37 0x0d4d 0x0020 0x0d24 0x0d4b 0x0d1f 0x0d4d 0x0d1f 0x0d3f 0x0d19 0x0d4d 0x0d19 0x0d32 0x0d4d 0x200d 
*/

  return 0;
}

There may be already existing libraries for this, but writing a simple one ourself is fun and good learning experience. For example, in python, to get the UTF-16 code sequence for a unicode string, we can use this:
str=u"സന്തോഷ്‌"
print repr(str)

This gives the following output
u'\u0d38\u0d28\u0d4d\u0d24\u0d4b\u0d37\u0d4d'

Canonical Equivalence in Unicode: Some notes
[info]santhoshtr
Some Notes on Canonical Equivalence in Unicode:
Unicode defines canonical equivalence as follows: From UAX #15
Canonical Equivalence
This section describes the relationship of normalization to respecting (or preserving) canonical equivalence. A process (or function) respects canonical equivalence when canonical-equivalent inputs always produce canonical-equivalent outputs. For a function that transforms one string into another, this may also be called preserving canonical equivalence. There are a number of important aspects to this concept:
  1. The outputs are not required to be identical, only canonically equivalent.
  2. Not all processes are required to respect canonical equivalence. For example:
    • A function that collects a set of the General_Category values present in a string will and should produce a different value for < angstrom sign, semicolon > than for < A, combining ring above, greek question mark >, even though they are canonically equivalent.
    • A function that does a binary comparison of strings will also find these two sequences different.
  3. Higher-level processes that transform or compare strings, or that perform other higher-level functions, must respect canonical equivalence or problems will result.
One good example for this is Ά = U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS and its canonical decomposition is defined as U+0391 GREEK CAPITAL LETTER ALPHA + U+0301 COMBINING ACUTE ACCENT = Α + ‍́ Following are the defined canonically equivalent unicode sequences for some Indic Languages
Bengali:
  1. U+09CB BENGALI VOWEL SIGN O = U+09C7 BENGALI VOWEL SIGN E + U+09BE BENGALI VOWEL SIGN AA
  2. U+09CC BENGALI VOWEL SIGN AU = U+09C7 BENGALI VOWEL SIGN E + U+09D7 BENGALI AU LENGTH MARK
  3. U+09DC BENGALI LETTER RRA = U+09A1 BENGALI LETTER DDA + U+09BC BENGALI SIGN NUKTA
  4. U+09DD BENGALI LETTER RHA = U+09A2 BENGALI LETTER DDHA + U+09BC BENGALI SIGN NUKTA
  5. U+09DF BENGALI LETTER YYA = U+09AF BENGALI LETTER YA + U+09BC BENGALI SIGN NUKTA
Devanagari
  1. U+0929 DEVANAGARI LETTER NNNA= U+0928 DEVANAGARI LETTER NA + U+093C DEVANAGARI SIGN NUKTA
  2. U+0931 DEVANAGARI LETTER RRA = U+0930 DEVANAGARI LETTER RA + U+093C DEVANAGARI SIGN NUKTA
  3. U+0934 DEVANAGARI LETTER LLLA = U+0933 DEVANAGARI LETTER LLA + U+093C DEVANAGARI SIGN NUKTA
  4. U+0958 DEVANAGARI LETTER QA = U+0915 DEVANAGARI LETTER KA + U+093C DEVANAGARI SIGN NUKTA
  5. U+0959 DEVANAGARI LETTER KHHA = U+0916 DEVANAGARI LETTER KHA + U+093C DEVANAGARI SIGN NUKTA
  6. U+095A DEVANAGARI LETTER GHHA = U+0917 DEVANAGARI LETTER GA + U+093C DEVANAGARI SIGN NUKTA
  7. U+095B DEVANAGARI LETTER ZA = U+091C DEVANAGARI LETTER JA + U+093C DEVANAGARI SIGN NUKTA
  8. U+095C DEVANAGARI LETTER DDDHA = U+0921 DEVANAGARI LETTER DDA + U+093C DEVANAGARI SIGN NUKTA
  9. U+095D DEVANAGARI LETTER RHA = U+0922 DEVANAGARI LETTER DDHA + U+093C DEVANAGARI SIGN NUKTA
  10. U+095E DEVANAGARI LETTER FA = U+092B DEVANAGARI LETTER PHA + U+093C DEVANAGARI SIGN NUKTA
  11. U+095F DEVANAGARI LETTER YYA = U+092F DEVANAGARI LETTER YA + U+093C DEVANAGARI SIGN NUKTA
(Note: I saw the ॻ U+097B DEVANAGARI LETTER GGA, ॼ U+097C DEVANAGARI LETTER JJA , and ॾ U+097E DEVANAGARI LETTER DDDA in Debanagari. I am not sure where these letters will be used and whether these are related to GHA, JHA and DDHA )

Gujarati:
Gujarati doesnot have any characters with canonically equivalent sequence.

Gurmukhi :
  1. U+0A36 GURMUKHI LETTER SHA = U+0A38 GURMUKHI LETTER SA + U+0A3C GURMUKHI SIGN NUKTA
  2. U+0A59 GURMUKHI LETTER KHHA = U+0A16 GURMUKHI LETTER KHA + U+0A3C GURMUKHI SIGN NUKTA
  3. U+0A5A GURMUKHI LETTER GHHA = U+0A17 GURMUKHI LETTER GA + U+0A3C GURMUKHI SIGN NUKTA
  4. U+0A5B GURMUKHI LETTER ZA = U+0A1C GURMUKHI LETTER JA + U+0A3C GURMUKHI SIGN NUKTA
  5. U+0A5E GURMUKHI LETTER FA = U+0A2B GURMUKHI LETTER PHA + U+0A3C GURMUKHI SIGN NUKTA
Kannada:
  1. U+0CC0 KANNADA VOWEL SIGN II = U+0CBF KANNADA VOWEL SIGN I + U+0CD5 KANNADA LENGTH MARK
  2. U+0CC7 KANNADA VOWEL SIGN EE = U+0CC6 KANNADA VOWEL SIGN E + U+0CD5 KANNADA LENGTH MARK
  3. U+0CC8 KANNADA VOWEL SIGN AI = U+0CC6 KANNADA VOWEL SIGN E + U+0CD6 KANNADA AI LENGTH MARK
  4. U+0CCA KANNADA VOWEL SIGN O = U+0CC6 KANNADA VOWEL SIGN E + U+0CC2 KANNADA VOWEL SIGN UU
  5. U+0CCB KANNADA VOWEL SIGN OO = U+0CC6 KANNADA VOWEL SIGN E + U+0CC2 KANNADA VOWEL SIGN UU + U+0CD5 KANNADA LENGTH MARK
Malayalam :
  1. U+0D4A MALAYALAM VOWEL SIGN O= U+0D46 MALAYALAM VOWEL SIGN E + U+0D3E MALAYALAM VOWEL SIGN AA
  2. U+0D4B MALAYALAM VOWEL SIGN OO = U+0D47 MALAYALAM VOWEL SIGN EE + U+0D3E MALAYALAM VOWEL SIGN AA
  3. U+0D4C MALAYALAM VOWEL SIGN AU = U+0D46 MALAYALAM VOWEL SIGN E + U+0D57 MALAYALAM AU LENGTH MARK
Oriya :
  1. U+0B48 ORIYA VOWEL SIGN AI = U+0B47 ORIYA VOWEL SIGN E + U+0B56 ORIYA AI LENGTH MARK
  2. U+0B4B ORIYA VOWEL SIGN O = U+0B47 ORIYA VOWEL SIGN E + U+0B3E ORIYA VOWEL SIGN AA
  3. U+0B4C ORIYA VOWEL SIGN AU = U+0B47 ORIYA VOWEL SIGN E + U+0B57 ORIYA AU LENGTH MARK
  4. U+0B5C ORIYA LETTER RRA = U+0B21 ORIYA LETTER DDA + U+0B3C ORIYA SIGN NUKTA
  5. U+0B5D ORIYA LETTER RHA = U+0B22 ORIYA LETTER DDHA + U+0B3C ORIYA SIGN NUKTA
Tamil:
  1. U+0B94 TAMIL LETTER AU = U+0B92 TAMIL LETTER O + U+0BD7 TAMIL AU LENGTH MARK
  2. U+0BCA TAMIL VOWEL SIGN O = U+0BC6 TAMIL VOWEL SIGN E + U+0BBE TAMIL VOWEL SIGN AA
  3. U+0BCB TAMIL VOWEL SIGN OO = U+0BC7 TAMIL VOWEL SIGN EE + U+0BBE TAMIL VOWEL SIGN AA
  4. U+0BCC TAMIL VOWEL SIGN AU = U+0BC6 TAMIL VOWEL SIGN E + U+0BD7 TAMIL AU LENGTH MARK
Notes:
  1. When you search a decomposed form of codepoints, you are also getting the search results of the atomic codepoint. Eg:
    മ + േ + ാ == മോ and മ + ോ == മോ
    Eventhough the code points are differnt for both of them, since there is a canonical equivalence between them, when you search one, you should get the second.
  2. When you sort the words with canonically equivalent codes, they should come adjacent.
  3. There are some languages where unicode defined the atomic code points obsolete and corresponding sequence as valid one without defining the canonical equivalence. One example is Khmer language. There U+17A8 KHMER INDEPENDENT VOWEL QUK was the atomically enocoded letter for the sequence U+17A7 KHMER INDEPENDENT VOWEL QU U+1780 KHMER LETTER KA. But now the description of U+17A8 KHMER INDEPENDENT VOWEL QUK says " obsolete ligature for the sequence U+17A7 KHMER INDEPENDENT VOWEL QU U+1780 KHMER LETTER KA , use of the sequence is now preferred "
  4. Unicode 5.1 defined new codepoints for the 6 chillu letters in Malayalam which are currently represented by consonant + virama + ZWJ. So a single letter can be represented in both ways. But unicode did not define the canonical equivalence for them. This results in dual encoding and users will not able to get the search results with one representation if they search with other representation.
  5. Windows does not implement the canonical equivalence at all(when tested in windows XP Sp2 for the above mentioned scripts).
  6. Google search gives the correct search results for words with canonical equivalent sequence. Example used is മോഷണം <=> മോഷണം
  7. Yahoo search gives the correct search results for words with canonical equivalent sequence. Example word used is മോഷണം <=> മോഷണം. But unlike google, the search key highlighted in search results uses a decomposed sequence. i.e Yahoo replaces the search key in the search results with decomposed unicode sequence while showing the results.
References:
  1. http://en.wikipedia.org/wiki/Canonical_equivalence
  2. http://unicode.org/reports/tr15/
Tags:

ചില്ലും മലയാളം കമ്പ്യൂട്ടിങ്ങും
[info]santhoshtr
മലയാളം കമ്പ്യൂട്ടിങ്ങിന്റെ മുകളില്‍ തലനാരിഴയില്‍ ഒരു വാള്‍ തൂങ്ങിക്കിടപ്പാണ്. ചില്ലു കൊണ്ടുള്ള ഒരു വാള്‍. വാള്‍ വീണാല്‍ മലയാളം രണ്ട് കഷണമാകും. ഒന്നാമത്തേത് നിങ്ങള്‍ വായിച്ചു കൊണ്ടിരിക്കുന്ന ഈ മലയാളം. രണ്ടാമത്തേത് അറ്റോമിക് ചില്ലുകള്‍ ഉപയോഗിച്ചുള്ള വേറൊരു മലയാളം...

"ഞങ്ങള്‍ തീരുമാനിച്ചു കഴിഞ്ഞു. നല്ലതോ ചീത്തയോ അതു നിങ്ങള്‍ അനുഭവിക്കുക" ഇത് അറ്റോമിക് ചില്ലുവാദികളുടെ മുദ്രാവാക്യത്തിന്റെ മലയാളപരിഭാഷ. ഇവിടെ ജയിക്കുന്നതാരുമാകട്ടെ തോല്ക്കുന്നത് ഭാഷ തന്നെയെന്നുറപ്പ്.

ഖരാക്ഷരം + വിരാമം + ZWJ എന്ന ഇപ്പോഴുള്ള ചില്ലക്ഷരത്തിന്റെ എന്‍കോഡിങ്ങിനു പകരം ഒറ്റ ഒരു യുണിക്കോഡ് വേണമെന്ന ആവശ്യം വളരെക്കാലമായി ഒരു വിഭാഗം മലയാളികള്‍ക്കിടയില്‍ ഉയര്‍ന്നു തുടങ്ങിയിട്ട്. അപ്പോള്‍ നിങ്ങള്‍ ചോദിച്ചേക്കാം ഇപ്പോഴുള്ള രീതിക്ക് എന്താണ് പ്രശ്നമെന്ന്. അതിനുള്ള ഉത്തരം എനിക്കിതേവരെ മനസ്സിലായിട്ടില്ല. മലയാളം ബ്ലോഗുകള്‍, വിക്കിപീഡിയ, മലയാളം സോഫ്റ്റ്​വെയറുകള്‍, പ്രാദേശികവത്കരിക്കപ്പെട്ട ഓപ്പറേറ്റിങ്ങ് സിസ്റ്റങ്ങള്‍, ഈയുള്ളവന്‍ തയ്യാറാക്കിക്കൊണ്ടിരിക്കുന്ന ഗ്നു ആസ്പെല് spelling checker (ഇപ്പോള്‍ ഒരു ലക്ഷത്തി മുപ്പതിനായിരത്തിലധികം മലയാളം വാക്കുകളുണ്ട്) ഇവയെല്ലാം ഇതിന് തെളിവുകള്‍ മാത്രം. ജീമെയിലില്‍ ചില്ലക്ഷരം വരുന്നില്ലെങ്കില്‍ അത് ജീമെയിലിന്റെ പിഴവാണ്. ബ്രൗസറില്‍ ചില്ലക്ഷരം വരുന്നില്ലെങ്കില്‍ അത് ബ്രൗസറിന്റെ അല്ലെങ്കില്‍ ചിത്രീകരണസംവിധാനത്തിന്റെ പിഴവാണ്. ഭാഷയുടേതല്ല. ഭാഷയെ മാറ്റലല്ല അതിനുള്ള പ്രതിവിധി. സോഫ്റ്റ്​വെയറിന്റെ പിഴവുകള്‍ ഭാഷകളുടെ നിലനില്പിനൊരിക്കലും വെല്ലുവിളിയാകരുത്.

സാങ്കേതികതയുടെ പേരില്‍ ഭാഷയോടുള്ള ഈ അതിക്രമം മലയാളത്തിന് പുത്തരിയല്ല. ടൈപ്പ്റൈറ്ററിന്റെ കാലത്ത് ലിപി പരിഷ്കാരത്തിന്റെ പേരില്‍ ലിപിയെ വെട്ടിമുറിക്കാന്‍ നമ്മുടെ പണ്ഡിതര്‍ തുനിഞ്ഞിരുന്നു. ആയുര്‍ബലം ഉള്ളതുകൊണ്ട് അകാലചരമമടയാതെ ഭാഷ രക്ഷപ്പെട്ടു. പ്രബുദ്ധരായ മലയാളികള്‍ ആ പരിഷ്കാരത്തെ അവഗണിച്ചു. ടൈപ്പ്റൈറ്ററിന്റെ സാങ്കേതികത്തികവില്ലായ്മ കമ്പ്യൂട്ടര്‍ പരിഹരിച്ചു. ഡിജിറ്റല്‍ ലോകത്തില്‍ മലയാളം അതിന്റെ ബാല്യദശയിലേക്ക് കടന്നു. ചരിത്രം വീണ്ടും ആവര്‍ത്തിക്കുന്നു. ഇത്തവണയും ഇതിനു മുന്നിട്ടിറങ്ങിയിരിക്കുന്നത് മലയാളികള്‍ തന്നെ. ഇതു വരെയുള്ള ഡിജിറ്റല്‍ മലയാളം കണ്ടെന്റ് മൊത്തം അസാധുവാക്കാനുള്ള ഒരു ശ്രമം. എനിക്കുറപ്പുണ്ട്, ഇതും ഒരു തുഗ്ളക്ക് പരിഷ്കാരമായി അവശേഷിക്കും. മലയാളത്തിന്റെ ഡിജിറ്റല്‍ പുരോഗതി വീണ്ടും അതിന്റെ ശൈശവം മുതല്‍ തുടങ്ങുകയോ?!.

എന്തു മാറ്റം വന്നാലും ഇപ്പോഴുള്ള സോഫ്റ്റ്​വെയറുകള്‍ നിലവിലുള്ള മലയാളം തന്നെ ഉത്പാദിപ്പിച്ചു കൊണ്ടിരിക്കും. ഉപയോക്താക്കള്‍ ഉപയോഗിച്ചു കൊണ്ടിരിക്കുന്ന ഇന്സ്ക്രിപ്റ്റ്, സ്വനലേഖ, വരമൊഴി എന്നീ നിവേശക രീതികളെല്ലാം നിലവിലുള്ള രീതി തന്നെ തുടരും. ചിത്രീകരണ സംവിധാനങ്ങള്‍ നിലവിലുള്ള രീതിയില്‍ തന്നെ റെന്‍ഡര്‍ ചെയ്യും. അങ്ങനെ കൂടുതല്‍ മലയാളം ഡിജിറ്റല്‍ ലോകത്തില്‍ നിറയും. ആ ലോകത്തിലേക്ക് അറ്റോമിക് ചില്ലെന്ന അപരന്‍ വന്നാല്‍ വാക്കുകള്‍ തിരിച്ചറിയാനാകാതെ ഡിജിറ്റല്‍ സംവിധാനങ്ങള്‍ അലങ്കോലമാകും. cons+virama+zwj = atomic Chillu എന്ന സമസ്യ എല്ലാ സോഫ്റ്റ്​വെയറുകളും മനസ്സിലാക്കേണ്ടി വരും. Dual Encoding എന്നത് തീരാശാപമായി മലയാളത്തെ പിന്തുടരും. എത്രകാലത്തേക്ക്? ഡിജിറ്റല്‍ വിവരങ്ങള്‍ക്ക് മരണമില്ലാത്തതു കൊണ്ട് അനന്തതയോളം...

ഇന്‍ഡിക് മെയിലിങ്ങ് ലിസ്റ്റില്‍( indic@unicode.org ) ചര്‍ച്ചകള്‍ ചൂടുപിടിക്കുകയാണ്. അറ്റോമിക് ചില്ല് എന്തിന്?, അതു കൊണ്ട് മാത്രമേ പരിഹരിക്കാന്‍ പറ്റൂ എന്നുള്ള എന്ത് പ്രശ്നമാണ് മലയാളത്തിനുള്ളത് എന്ന ചോദ്യങ്ങള്‍ക്ക് കൃത്യമായ ഉത്തരം നല്കാതെ ഒഴിഞ്ഞു മാറി നടക്കുകയാണ് അറ്റോമിക് ചില്ലുവാദികള്‍. ചിലരുടെ വ്യക്തിപരമായ പ്രശസ്തിക്കു വേണ്ടി മലയാളത്തിനെ കുരുതി കൊടുക്കണോ? ചരിത്രപരമായ മറ്റൊരു മണ്ടത്തരത്തിന് മലയാളം ഇരയാവല്ലേ എന്നു നമുക്കു പ്രാര്‍ത്ഥിക്കാം. നിരവധി ആക്രമണങ്ങളെ അതിജീവിച്ച മലയാളം ഇതും അതിജീവിക്കുമെന്നു പ്രതീക്ഷിക്കാം.

Home