ייסורי Unicode ב־2009, או תמיכה ב־unicode בסביבות שונות.

ב־14.4.2009, מאת ארתיום; פורסם תחת: תכנה חופשית, פיתוח, תכנה ומחשבים, Unicode; ‏4 תגובות

אחד הדברים החסרים ביותר ב־C++‎, מבחינתי, זה העדר תמיכה טובה ב־Unicode. למרות ש־std::wstring ו־std::locale קיימים הם לא נותנים מענה על כל דרישות העבודה עם Unicode.

יש שפות תכנות כמו Python ו־Java בהן התמיכה הזו נחשבת ל"טבעית". אז החלטתי לעשות בדיקה ולבדוק מספר דברים חיוניים בעיבוד טקסט טבעי: החלפה בין אותיות גדולות וקטנות וכן מציאת גבולות המילים. דברים שנראים טריוויאליים עבור אנגלית למעשה הופכים לכלל לא טריויאליים כאשר מדובר בשפות אחרות:

  1. שינוי אות קטנה לגדולה: ß גרמנית צריכה להפוך ל־SS (שתי אותיות).
  2. שינוי אות גדולה לקטנה: Σ היוונית הופכת ל־σ במרכז המילה ול־ς בסופה.
  3. הפרדת מילים לצורך חיתוך הטקסט: 中文 אלה שתי מילים ולא מילה אחת.

בדקתי 6 כלים: ספריית ICU עם API במספר שפות, ספריית glib יחד עם pango עבור C, ספריות Qt3 ו־Qt4 עבור C++‎, וגם כלים טבעיים של Java, ‏C++‎ ושל Python.

אקדים ואומר, המקרים הפשוטים כמו המרת: "Артём" (השם הפרטי שלי ברוסית) ל"АРТЁМ" עבדו בכל הכלים ושפות, אבל במקרים יותר מורכבים התוצאות היו כלל לא מעודדות:

כלילאותיות גדולותלאותיות קטנותגבולות המילים
C++‎נכשלנכשלאין תמיכה
C++/ICU‎הצליחהצליחהצליח
C++/Qt4‎הצליחנכשלהצליח
C++/Qt3‎נכשלנכשלאין תמיכה
C/glib+pangoהצליחהצליחנכשל
Java/JDKהצליחהצליחנכשל
Java/ICU4jהצליחהצליחהצליח
Pythonנכשלנכשלאין תמיכה
Python/PyICU‎הצליחהצליחהצליח

עכשיו פרטים

ICU: היא הספריה החזקה ביותר שנותנת מענה לכל הבעיות, בצורה באמת טובה, אבל... התיעוד שלה על הפנים, ה־API הטבעי שלה, אפילו שהוא ב־C++‎ בנוי בצורה מאוד לא נוחה ומאוד מיושנת.

C++/STL: למרות שהתמיכה בהמרת קידוד, השוואת מחרוזות ושינוי case קיימת, ה־API לא ממש נוח ודורש עבודה ישירה עם char*‎ או wchar_t*‎, ולא דרך האיטרטורים -- מה שלא מאפשר עבודה ישירת עם std::string או std::wstring.‏

glib+pango: נותן מענה מספיק טוב לבעיות בסיסיות והייתי אומר די נוח לכתיבה ב־C, אבל... הוא עדיין נותן רק מענה חלקי בלבד, בנוסף הפרדה בין מילים דרושת pango -- ספריה די מסובכת ומסתבר גם לא עובדת מספיק טוב.

Qt3:‏ API נוח אבל נותן מענה מאוד בסיסי לתמיכה ב־Unicode שלא יודע להתמודד עם דברים קצת פחות טריוויאליים.

Qt4: למרות שיש שיפור ניכר בשוואה ל־Qt3 עדיין יש דברים שלא עובדים כמצופה (הפיכת Σ ל־σ או ל־ς לפי ההקשר).‏

Java: התמיכה שלה ב־Unicode די טובה וה־Api שלה נגזר מ־ICU, עדיין JDK כפישהו מתקשה לענות על כל הדרישות (לא יודע להבחין ש־中文 אלה שתי מילים).

Python כפישהו: נותן מענה מאוד בסיסי לבעיות Unicode, בפרט לא יודע לטפל במקרים קצת יותר מסובכים.

PyICU: אומנם קיים אבל התיעוד שלו פשוט איננו --- צריך לנחש כיצד הדברים מהכרות עם ICU.‏

ICU4J: היתרון הגדול שלו שהוא מאוד דומה ל־JDK ואפשר בקלות להחליף אותו ע"י החלפת import פשוטה (כמעט).

סיכום

חבל שב־2009:

  • שפות התכנות ופלטפורמות פופולריות נותנות מענה חלקי בלבד לבעיות Unicode.
  • אין מעטפת נוחה ומודרנית של ICU עבור C++‎.

מקווה שמישהו מתישהו יכניס אחת כזו ל־Boost.

תגובות

ik_5, ב־15.4.2009, 0:03

יש תמיכה בסיסית בלבד ב FreePascal. התחלתי פעם יחידה שאמורה לטפל במציאת גבולות ועשיית פעולות על תווים מרובי בתים, אבל לא היה לי סבלנות לסיים אותה, ולא היה לי צורך ממשי להמשיך אותה.

התמיכה שקיימת (עד כמה שאני יודע לפחות) היא בטיפוסי משתנים שונים כדוגמת UTF8Char ו UTF8String וכן WideChar ו WideString. כמו כן יש פונקציות להמיר בין קידודים שונים, יש תמיכה בiconv ובlibc מאזן יצר פעם ספרייה לעבודה עם Bidi שלא ניסיתי אף פע (היא גם לא נארזת בהפצה הרשמית) אבל בזה עד כמה שאני יודע זה נגמר.

ארתיום, ב־15.4.2009, 8:16

יש תמיכה בסיסית בלבד ב FreePascal. התחלתי פעם יחידה שאמורה לטפל במציאת גבולות ועשיית פעולות על תווים מרובי בתים, אבל לא היה לי סבלנות לסיים אותה, ולא היה לי צורך ממשי להמשיך אותה.

עבודה עם תווים מרובי בתים היא באמת פשוטה. דבר כזה אפשר לכתוב בחצי יום כולל חיבור iconv. הבעיה היא דברים לא טריויאליים כמו שציינתי, שינוי case הפרדת מילים (לא תוים).

כן WideChar ו WideString.

האם WideChar הוא 16 או 32 ביט? מה שמזכיר לי את הנושא שכתבתי עליו פעם -- מדוע לא כדאי להשתמש ב־utf-16 אלא ב־utf8 או utf-32.

שוב, הבעיה היא מאוד מורכבת ופתרונות טובים כמעט ואינם.

ik_5, ב־15.4.2009, 11:54

עבודה עם תווים מרובי בתים היא באמת פשוטה. דבר כזה אפשר לכתוב בחצי יום כולל חיבור iconv. הבעיה היא דברים לא טריויאליים כמו שציינתי, שינוי case הפרדת מילים (לא תוים).

אין. לגבי case היה דיון והחליטו שלא מוכנים בגלל שבניגוד ל ASCII ששם זה חישוב מתמטי, אין ליוניקוד שום חישוב מתמטי בשביל upper/lower case, מה שאומר שיהיה בלוק ענק של זכרון רק בשביל טבלת המרה, משהו שלא צריך להגיע דרך ה RTL אלא מספריות מעל ה RTL אם כבר (אני בן אלו שהיו בעד ההחלטה).

בברירת מחדל FPC עובד עם UTF-8, אבל בRTL אין הרבה פונקציות לנושא פרט להמרה, קידוד וכו' (בצורה טבעית ולא רק ספריות כדוגמת iconv).

האם WideChar הוא 16 או 32 ביט? מה שמזכיר לי את הנושא שכתבתי עליו פעם – מדוע לא כדאי להשתמש ב־utf-16 אלא ב־utf8 או utf-32.

זה 16 ביט, מסתבר (לא ידעתי עד שבדקתי עכשיו) שיש גם UCS4Char שהוא 32 ביט.

ik_5, ב־15.4.2009, 12:13

שחכתי לציין גם שאם אתה עובד נגיד בלזרוס, אז יש לו יחידות נוספות שאין ל FPC ה"רגיל", ושם כן יש כלים להתמודד עם UTF8. למשל לזהות אות, ואם הבית שבחרת הוא לא ההתחלה, אז לזהות איפה ההתחלה. לדעת להעתיק תווים, מיקומים שלהם, מחיקה של תווים וכו' בצורה חכמה יותר (שמתאימה ל multi-byte char)

הוסף תגובה:

 
 כתובת דוא"ל לא תוצג
 

ניתן לכתוב תגובות עם שימוש בתחביר Markdown.

חובה לאפשר JavaScript כדי להגיב.

דפים

נושאים