util/local_database/qlocalexml2cpp.py
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 #!/usr/bin/env python
       
     2 #############################################################################
       
     3 ##
       
     4 ## Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     5 ## All rights reserved.
       
     6 ## Contact: Nokia Corporation (qt-info@nokia.com)
       
     7 ##
       
     8 ## This file is part of the test suite of the Qt Toolkit.
       
     9 ##
       
    10 ## $QT_BEGIN_LICENSE:LGPL$
       
    11 ## No Commercial Usage
       
    12 ## This file contains pre-release code and may not be distributed.
       
    13 ## You may use this file in accordance with the terms and conditions
       
    14 ## contained in the Technology Preview License Agreement accompanying
       
    15 ## this package.
       
    16 ##
       
    17 ## GNU Lesser General Public License Usage
       
    18 ## Alternatively, this file may be used under the terms of the GNU Lesser
       
    19 ## General Public License version 2.1 as published by the Free Software
       
    20 ## Foundation and appearing in the file LICENSE.LGPL included in the
       
    21 ## packaging of this file.  Please review the following information to
       
    22 ## ensure the GNU Lesser General Public License version 2.1 requirements
       
    23 ## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    24 ##
       
    25 ## In addition, as a special exception, Nokia gives you certain additional
       
    26 ## rights.  These rights are described in the Nokia Qt LGPL Exception
       
    27 ## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    28 ##
       
    29 ## If you have questions regarding the use of this file, please contact
       
    30 ## Nokia at qt-info@nokia.com.
       
    31 ##
       
    32 ##
       
    33 ##
       
    34 ##
       
    35 ##
       
    36 ##
       
    37 ##
       
    38 ##
       
    39 ## $QT_END_LICENSE$
       
    40 ##
       
    41 #############################################################################
       
    42 
       
    43 import sys
       
    44 import xml.dom.minidom
       
    45 
       
    46 def check_static_char_array_length(name, array):
       
    47     # some compilers like VC6 doesn't allow static arrays more than 64K bytes size.
       
    48     size = reduce(lambda x, y: x+len(escapedString(y)), array, 0)
       
    49     if size > 65535:
       
    50         print "\n\n\n#error Array %s is too long! " % name
       
    51         sys.stderr.write("\n\n\nERROR: the content of the array '%s' is too long: %d > 65535 " % (name, size))
       
    52         sys.exit(1)
       
    53 
       
    54 def wrap_list(lst):
       
    55     def split(lst, size):
       
    56         for i in range(len(lst)/size+1):
       
    57             yield lst[i*size:(i+1)*size]
       
    58     return ",\n".join(map(lambda x: ", ".join(x), split(lst, 20)))
       
    59 
       
    60 def firstChildElt(parent, name):
       
    61     child = parent.firstChild
       
    62     while child:
       
    63         if child.nodeType == parent.ELEMENT_NODE \
       
    64             and (not name or child.nodeName == name):
       
    65             return child
       
    66         child = child.nextSibling
       
    67     return False
       
    68 
       
    69 def nextSiblingElt(sibling, name):
       
    70     sib = sibling.nextSibling
       
    71     while sib:
       
    72         if sib.nodeType == sibling.ELEMENT_NODE \
       
    73             and (not name or sib.nodeName == name):
       
    74             return sib
       
    75         sib = sib.nextSibling
       
    76     return False
       
    77 
       
    78 def eltText(elt):
       
    79     result = ""
       
    80     child = elt.firstChild
       
    81     while child:
       
    82         if child.nodeType == elt.TEXT_NODE:
       
    83             if result:
       
    84                 result += " "
       
    85             result += child.nodeValue
       
    86         child = child.nextSibling
       
    87     return result
       
    88 
       
    89 def loadLanguageMap(doc):
       
    90     result = {}
       
    91 
       
    92     language_list_elt = firstChildElt(doc.documentElement, "languageList")
       
    93     language_elt = firstChildElt(language_list_elt, "language")
       
    94     while language_elt:
       
    95         language_id = int(eltText(firstChildElt(language_elt, "id")))
       
    96         language_name = eltText(firstChildElt(language_elt, "name"))
       
    97         language_code = eltText(firstChildElt(language_elt, "code"))
       
    98         result[language_id] = (language_name, language_code)
       
    99         language_elt = nextSiblingElt(language_elt, "language")
       
   100 
       
   101     return result
       
   102 
       
   103 def loadCountryMap(doc):
       
   104     result = {}
       
   105 
       
   106     country_list_elt = firstChildElt(doc.documentElement, "countryList")
       
   107     country_elt = firstChildElt(country_list_elt, "country")
       
   108     while country_elt:
       
   109         country_id = int(eltText(firstChildElt(country_elt, "id")))
       
   110         country_name = eltText(firstChildElt(country_elt, "name"))
       
   111         country_code = eltText(firstChildElt(country_elt, "code"))
       
   112         result[country_id] = (country_name, country_code)
       
   113         country_elt = nextSiblingElt(country_elt, "country")
       
   114 
       
   115     return result
       
   116 
       
   117 def loadDefaultMap(doc):
       
   118     result = {}
       
   119 
       
   120     list_elt = firstChildElt(doc.documentElement, "defaultCountryList")
       
   121     elt = firstChildElt(list_elt, "defaultCountry")
       
   122     while elt:
       
   123         country = eltText(firstChildElt(elt, "country"));
       
   124         language = eltText(firstChildElt(elt, "language"));
       
   125         result[language] = country;
       
   126         elt = nextSiblingElt(elt, "defaultCountry");
       
   127     return result
       
   128 
       
   129 def fixedCountryName(name, dupes):
       
   130     if name in dupes:
       
   131         return name + "Country"
       
   132     return name
       
   133 
       
   134 def fixedLanguageName(name, dupes):
       
   135     if name in dupes:
       
   136         return name + "Language"
       
   137     return name
       
   138 
       
   139 def findDupes(country_map, language_map):
       
   140     country_set = set([ v[0] for a, v in country_map.iteritems() ])
       
   141     language_set = set([ v[0] for a, v in language_map.iteritems() ])
       
   142     return country_set & language_set
       
   143 
       
   144 def languageNameToId(name, language_map):
       
   145     for key in language_map.keys():
       
   146         if language_map[key][0] == name:
       
   147             return key
       
   148     return -1
       
   149 
       
   150 def countryNameToId(name, country_map):
       
   151     for key in country_map.keys():
       
   152         if country_map[key][0] == name:
       
   153             return key
       
   154     return -1
       
   155 
       
   156 def convertFormat(format):
       
   157     result = ""
       
   158     i = 0
       
   159     while i < len(format):
       
   160         if format[i] == "'":
       
   161             result += "'"
       
   162             i += 1
       
   163             while i < len(format) and format[i] != "'":
       
   164                 result += format[i]
       
   165                 i += 1
       
   166             if i < len(format):
       
   167                 result += "'"
       
   168                 i += 1
       
   169         else:
       
   170             s = format[i:]
       
   171             if s.startswith("EEEE"):
       
   172                 result += "dddd"
       
   173                 i += 4
       
   174             elif s.startswith("EEE"):
       
   175                 result += "ddd"
       
   176                 i += 3
       
   177             elif s.startswith("a"):
       
   178                 result += "AP"
       
   179                 i += 1
       
   180             elif s.startswith("z"):
       
   181                 result += "t"
       
   182                 i += 1
       
   183             elif s.startswith("v"):
       
   184                 i += 1
       
   185             else:
       
   186                 result += format[i]
       
   187                 i += 1
       
   188 
       
   189     return result
       
   190 
       
   191 class Locale:
       
   192     def __init__(self, elt):
       
   193         self.language = eltText(firstChildElt(elt, "language"))
       
   194         self.country = eltText(firstChildElt(elt, "country"))
       
   195         self.decimal = int(eltText(firstChildElt(elt, "decimal")))
       
   196         self.group = int(eltText(firstChildElt(elt, "group")))
       
   197         self.listDelim = int(eltText(firstChildElt(elt, "list")))
       
   198         self.percent = int(eltText(firstChildElt(elt, "percent")))
       
   199         self.zero = int(eltText(firstChildElt(elt, "zero")))
       
   200         self.minus = int(eltText(firstChildElt(elt, "minus")))
       
   201         self.plus = int(eltText(firstChildElt(elt, "plus")))
       
   202         self.exp = int(eltText(firstChildElt(elt, "exp")))
       
   203         self.am = eltText(firstChildElt(elt, "am"))
       
   204         self.pm = eltText(firstChildElt(elt, "pm"))
       
   205         self.longDateFormat = convertFormat(eltText(firstChildElt(elt, "longDateFormat")))
       
   206         self.shortDateFormat = convertFormat(eltText(firstChildElt(elt, "shortDateFormat")))
       
   207         self.longTimeFormat = convertFormat(eltText(firstChildElt(elt, "longTimeFormat")))
       
   208         self.shortTimeFormat = convertFormat(eltText(firstChildElt(elt, "shortTimeFormat")))
       
   209         self.standaloneLongMonths = eltText(firstChildElt(elt, "standaloneLongMonths"))
       
   210         self.standaloneShortMonths = eltText(firstChildElt(elt, "standaloneShortMonths"))
       
   211         self.standaloneNarrowMonths = eltText(firstChildElt(elt, "standaloneNarrowMonths"))
       
   212         self.longMonths = eltText(firstChildElt(elt, "longMonths"))
       
   213         self.shortMonths = eltText(firstChildElt(elt, "shortMonths"))
       
   214         self.narrowMonths = eltText(firstChildElt(elt, "narrowMonths"))
       
   215         self.standaloneLongDays = eltText(firstChildElt(elt, "standaloneLongDays"))
       
   216         self.standaloneShortDays = eltText(firstChildElt(elt, "standaloneShortDays"))
       
   217         self.standaloneNarrowDays = eltText(firstChildElt(elt, "standaloneNarrowDays"))
       
   218         self.longDays = eltText(firstChildElt(elt, "longDays"))
       
   219         self.shortDays = eltText(firstChildElt(elt, "shortDays"))
       
   220         self.narrowDays = eltText(firstChildElt(elt, "narrowDays"))
       
   221 
       
   222 def loadLocaleMap(doc, language_map, country_map):
       
   223     result = {}
       
   224 
       
   225     locale_list_elt = firstChildElt(doc.documentElement, "localeList")
       
   226     locale_elt = firstChildElt(locale_list_elt, "locale")
       
   227     while locale_elt:
       
   228         locale = Locale(locale_elt)
       
   229         language_id = languageNameToId(locale.language, language_map)
       
   230         country_id = countryNameToId(locale.country, country_map)
       
   231         result[(language_id, country_id)] = locale
       
   232 
       
   233         locale_elt = nextSiblingElt(locale_elt, "locale")
       
   234 
       
   235     return result
       
   236 
       
   237 def compareLocaleKeys(key1, key2):
       
   238     if key1 == key2:
       
   239         return 0
       
   240 
       
   241     if key1[0] == key2[0]:
       
   242         l1 = compareLocaleKeys.locale_map[key1]
       
   243         l2 = compareLocaleKeys.locale_map[key2]
       
   244 
       
   245         if l1.language in compareLocaleKeys.default_map:
       
   246             default = compareLocaleKeys.default_map[l1.language]
       
   247             if l1.country == default:
       
   248                 return -1
       
   249             if l2.country == default:
       
   250                 return 1
       
   251     else:
       
   252         return key1[0] - key2[0]
       
   253 
       
   254     return key1[1] - key2[1]
       
   255 
       
   256 
       
   257 def languageCount(language_id, locale_map):
       
   258     result = 0
       
   259     for key in locale_map.keys():
       
   260         if key[0] == language_id:
       
   261             result += 1
       
   262     return result
       
   263 
       
   264 class StringDataToken:
       
   265     def __init__(self, index, length):
       
   266         self.index = index
       
   267         self.length = length
       
   268     def __str__(self):
       
   269         return " %d,%d " % (self.index, self.length)
       
   270 
       
   271 class StringData:
       
   272     def __init__(self):
       
   273         self.data = []
       
   274         self.hash = {}
       
   275     def append(self, s):
       
   276         if s in self.hash:
       
   277             return self.hash[s]
       
   278 
       
   279         lst = map(lambda x: hex(ord(x)), s)
       
   280         index = len(self.data)
       
   281         if index >= 65535:
       
   282             print "\n\n\n#error Data index is too big!"
       
   283             sys.stderr.write ("\n\n\nERROR: index exceeds the uint16 range! index = %d\n" % index)
       
   284             sys.exit(1)
       
   285         size = len(lst)
       
   286         if size >= 65535:
       
   287             print "\n\n\n#error Data is too big!"
       
   288             sys.stderr.write ("\n\n\nERROR: data size exceeds the uint16 range! size = %d\n" % size)
       
   289             sys.exit(1)
       
   290         token = StringDataToken(index, size)
       
   291         self.hash[s] = token
       
   292         self.data += lst
       
   293         return token
       
   294 
       
   295 def escapedString(s):
       
   296     result = ""
       
   297     i = 0
       
   298     while i < len(s):
       
   299         if s[i] == '"':
       
   300             result += '\\"'
       
   301             i += 1
       
   302         else:
       
   303             result += s[i]
       
   304             i += 1
       
   305     s = result
       
   306 
       
   307     line = ""
       
   308     need_escape = False
       
   309     result = ""
       
   310     for c in s:
       
   311         if ord(c) < 128 and (not need_escape or ord(c.lower()) < ord('a') or ord(c.lower()) > ord('f')):
       
   312             line += c
       
   313             need_escape = False
       
   314         else:
       
   315             line += "\\x%02x" % (ord(c))
       
   316             need_escape = True
       
   317         if len(line) > 80:
       
   318             result = result + "\n" + "\"" + line + "\""
       
   319             line = ""
       
   320     line += "\\0"
       
   321     result = result + "\n" + "\"" + line + "\""
       
   322     if result[0] == "\n":
       
   323         result = result[1:]
       
   324     return result
       
   325 
       
   326 def printEscapedString(s):
       
   327     print escapedString(s);
       
   328 
       
   329 
       
   330 def main():
       
   331     doc = xml.dom.minidom.parse("locale.xml")
       
   332     language_map = loadLanguageMap(doc)
       
   333     country_map = loadCountryMap(doc)
       
   334     default_map = loadDefaultMap(doc)
       
   335     locale_map = loadLocaleMap(doc, language_map, country_map)
       
   336     dupes = findDupes(language_map, country_map)
       
   337 
       
   338     # Language enum
       
   339     print "enum Language {"
       
   340     language = ""
       
   341     for key in language_map.keys():
       
   342         language = fixedLanguageName(language_map[key][0], dupes)
       
   343         print "    " + language + " = " + str(key) + ","
       
   344     print "    LastLanguage = " + language
       
   345     print "};"
       
   346 
       
   347     print
       
   348 
       
   349     # Country enum
       
   350     print "enum Country {"
       
   351     country = ""
       
   352     for key in country_map.keys():
       
   353         country = fixedCountryName(country_map[key][0], dupes)
       
   354         print "    " + country + " = " + str(key) + ","
       
   355     print "    LastCountry = " + country
       
   356     print "};"
       
   357 
       
   358     print
       
   359 
       
   360     # Locale index
       
   361     print "static const quint16 locale_index[] = {"
       
   362     print "     0, // unused"
       
   363     index = 0
       
   364     for key in language_map.keys():
       
   365         i = 0
       
   366         count = languageCount(key, locale_map)
       
   367         if count > 0:
       
   368             i = index
       
   369             index += count
       
   370         print "%6d, // %s" % (i, language_map[key][0])
       
   371     print "     0 // trailing 0"
       
   372     print "};"
       
   373 
       
   374     print
       
   375 
       
   376     date_format_data = StringData()
       
   377     time_format_data = StringData()
       
   378     months_data = StringData()
       
   379     standalone_months_data = StringData()
       
   380     days_data = StringData()
       
   381     am_data = StringData()
       
   382     pm_data = StringData()
       
   383 
       
   384     # Locale data
       
   385     print "static const QLocalePrivate locale_data[] = {"
       
   386     print "//      lang   terr    dec  group   list  prcnt   zero  minus  plus    exp sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth  sMonth lMonth  sDays  lDays  am,len      pm,len"
       
   387 
       
   388     locale_keys = locale_map.keys()
       
   389     compareLocaleKeys.default_map = default_map
       
   390     compareLocaleKeys.locale_map = locale_map
       
   391     locale_keys.sort(compareLocaleKeys)
       
   392 
       
   393     for key in locale_keys:
       
   394         l = locale_map[key]
       
   395 
       
   396         print "    { %6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s }, // %s/%s" \
       
   397                     % (key[0], key[1],
       
   398                         l.decimal,
       
   399                         l.group,
       
   400                         l.listDelim,
       
   401                         l.percent,
       
   402                         l.zero,
       
   403                         l.minus,
       
   404                         l.plus,
       
   405                         l.exp,
       
   406                         date_format_data.append(l.shortDateFormat),
       
   407                         date_format_data.append(l.longDateFormat),
       
   408                         time_format_data.append(l.shortTimeFormat),
       
   409                         time_format_data.append(l.longTimeFormat),
       
   410                         standalone_months_data.append(l.standaloneShortMonths),
       
   411                         standalone_months_data.append(l.standaloneLongMonths),
       
   412                         standalone_months_data.append(l.standaloneNarrowMonths),
       
   413                         months_data.append(l.shortMonths),
       
   414                         months_data.append(l.longMonths),
       
   415                         months_data.append(l.narrowMonths),
       
   416                         days_data.append(l.standaloneShortDays),
       
   417                         days_data.append(l.standaloneLongDays),
       
   418                         days_data.append(l.standaloneNarrowDays),
       
   419                         days_data.append(l.shortDays),
       
   420                         days_data.append(l.longDays),
       
   421                         days_data.append(l.narrowDays),
       
   422                         am_data.append(l.am),
       
   423                         pm_data.append(l.pm),
       
   424                         l.language,
       
   425                         l.country)
       
   426     print "    {      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,     0,0,     0,0,     0,0,     0,0,     0,0,     0,0,     0,0,    0,0,    0,0,    0,0,   0,0,   0,0,   0,0,   0,0,   0,0,   0,0,   0,0,   0,0 }  // trailing 0s"
       
   427     print "};"
       
   428 
       
   429     print
       
   430 
       
   431     # Date format data
       
   432     #check_static_char_array_length("date_format", date_format_data.data)
       
   433     print "static const ushort date_format_data[] = {"
       
   434     print wrap_list(date_format_data.data)
       
   435     print "};"
       
   436 
       
   437     print
       
   438 
       
   439     # Time format data
       
   440     #check_static_char_array_length("time_format", time_format_data.data)
       
   441     print "static const ushort time_format_data[] = {"
       
   442     print wrap_list(time_format_data.data)
       
   443     print "};"
       
   444 
       
   445     print
       
   446 
       
   447     # Months data
       
   448     #check_static_char_array_length("months", months_data.data)
       
   449     print "static const ushort months_data[] = {"
       
   450     print wrap_list(months_data.data)
       
   451     print "};"
       
   452 
       
   453     print
       
   454 
       
   455     # Standalone months data
       
   456     #check_static_char_array_length("standalone_months", standalone_months_data.data)
       
   457     print "static const ushort standalone_months_data[] = {"
       
   458     print wrap_list(standalone_months_data.data)
       
   459     print "};"
       
   460 
       
   461     print
       
   462 
       
   463     # Days data
       
   464     #check_static_char_array_length("days", days_data.data)
       
   465     print "static const ushort days_data[] = {"
       
   466     print wrap_list(days_data.data)
       
   467     print "};"
       
   468 
       
   469     print
       
   470 
       
   471     # AM data
       
   472     #check_static_char_array_length("am", am_data.data)
       
   473     print "static const ushort am_data[] = {"
       
   474     print wrap_list(am_data.data)
       
   475     print "};"
       
   476 
       
   477     print
       
   478 
       
   479     # PM data
       
   480     #check_static_char_array_length("pm", am_data.data)
       
   481     print "static const ushort pm_data[] = {"
       
   482     print wrap_list(pm_data.data)
       
   483     print "};"
       
   484 
       
   485     print
       
   486 
       
   487     # Language name list
       
   488     print "static const char language_name_list[] ="
       
   489     print "\"Default\\0\""
       
   490     for key in language_map.keys():
       
   491         print "\"" + language_map[key][0] + "\\0\""
       
   492     print ";"
       
   493 
       
   494     print
       
   495 
       
   496     # Language name index
       
   497     print "static const quint16 language_name_index[] = {"
       
   498     print "     0, // Unused"
       
   499     index = 8
       
   500     for key in language_map.keys():
       
   501         language = language_map[key][0]
       
   502         print "%6d, // %s" % (index, language)
       
   503         index += len(language) + 1
       
   504     print "};"
       
   505 
       
   506     print
       
   507 
       
   508     # Country name list
       
   509     print "static const char country_name_list[] ="
       
   510     print "\"Default\\0\""
       
   511     for key in country_map.keys():
       
   512         if key == 0:
       
   513             continue
       
   514         print "\"" + country_map[key][0] + "\\0\""
       
   515     print ";"
       
   516 
       
   517     print
       
   518 
       
   519     # Country name index
       
   520     print "static const quint16 country_name_index[] = {"
       
   521     print "     0, // AnyCountry"
       
   522     index = 8
       
   523     for key in country_map.keys():
       
   524         if key == 0:
       
   525             continue
       
   526         country = country_map[key][0]
       
   527         print "%6d, // %s" % (index, country)
       
   528         index += len(country) + 1
       
   529     print "};"
       
   530 
       
   531     print
       
   532 
       
   533     # Language code list
       
   534     print "static const unsigned char language_code_list[] ="
       
   535     print "\"  \\0\" // Unused"
       
   536     for key in language_map.keys():
       
   537         code = language_map[key][1]
       
   538         if len(code) == 2:
       
   539             code += r"\0"
       
   540         print "\"%2s\" // %s" % (code, language_map[key][0])
       
   541     print ";"
       
   542 
       
   543     print
       
   544 
       
   545     # Country code list
       
   546     print "static const unsigned char country_code_list[] ="
       
   547     for key in country_map.keys():
       
   548         print "\"%2s\" // %s" % (country_map[key][1], country_map[key][0])
       
   549     print ";"
       
   550 
       
   551 
       
   552 if __name__ == "__main__":
       
   553     main()