הבלוג של ארתיום
בלוג על לינוקס, תוכנה חופשית, מוזיקה, סלסה, ומה לא!
ייסורי Unicode ב־2009, או תמיכה ב־unicode בסביבות שונות.
אחד הדברים החסרים ביותר ב־C++, מבחינתי, זה העדר תמיכה טובה ב־Unicode. למרות ש־std::wstring ו־std::locale קיימים הם לא נותנים מענה על כל דרישות העבודה עם Unicode.
יש שפות תכנות כמו Python ו־Java בהן התמיכה הזו נחשבת ל"טבעית". אז החלטתי לעשות בדיקה ולבדוק מספר דברים חיוניים בעיבוד טקסט טבעי: החלפה בין אותיות גדולות וקטנות וכן מציאת גבולות המילים. דברים שנראים טריוויאליים עבור אנגלית למעשה הופכים לכלל לא טריויאליים כאשר מדובר בשפות אחרות:
- שינוי אות קטנה לגדולה: ß גרמנית צריכה להפוך ל־SS (שתי אותיות).
- שינוי אות גדולה לקטנה: Σ היוונית הופכת ל־σ במרכז המילה ול־ς בסופה.
- הפרדת מילים לצורך חיתוך הטקסט: 中文 אלה שתי מילים ולא מילה אחת.
בדקתי 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.
תגובות
יש תמיכה בסיסית בלבד ב FreePascal. התחלתי פעם יחידה שאמורה לטפל במציאת גבולות ועשיית פעולות על תווים מרובי בתים, אבל לא היה לי סבלנות לסיים אותה, ולא היה לי צורך ממשי להמשיך אותה.
התמיכה שקיימת (עד כמה שאני יודע לפחות) היא בטיפוסי משתנים שונים כדוגמת UTF8Char ו UTF8String וכן WideChar ו WideString. כמו כן יש פונקציות להמיר בין קידודים שונים, יש תמיכה בiconv ובlibc מאזן יצר פעם ספרייה לעבודה עם Bidi שלא ניסיתי אף פע (היא גם לא נארזת בהפצה הרשמית) אבל בזה עד כמה שאני יודע זה נגמר.
עבודה עם תווים מרובי בתים היא באמת פשוטה. דבר כזה אפשר לכתוב בחצי יום כולל חיבור iconv. הבעיה היא דברים לא טריויאליים כמו שציינתי, שינוי case הפרדת מילים (לא תוים).
האם WideChar הוא 16 או 32 ביט? מה שמזכיר לי את הנושא שכתבתי עליו פעם -- מדוע לא כדאי להשתמש ב־utf-16 אלא ב־utf8 או utf-32.
שוב, הבעיה היא מאוד מורכבת ופתרונות טובים כמעט ואינם.
אין. לגבי case היה דיון והחליטו שלא מוכנים בגלל שבניגוד ל ASCII ששם זה חישוב מתמטי, אין ליוניקוד שום חישוב מתמטי בשביל upper/lower case, מה שאומר שיהיה בלוק ענק של זכרון רק בשביל טבלת המרה, משהו שלא צריך להגיע דרך ה RTL אלא מספריות מעל ה RTL אם כבר (אני בן אלו שהיו בעד ההחלטה).
בברירת מחדל FPC עובד עם UTF-8, אבל בRTL אין הרבה פונקציות לנושא פרט להמרה, קידוד וכו' (בצורה טבעית ולא רק ספריות כדוגמת iconv).
זה 16 ביט, מסתבר (לא ידעתי עד שבדקתי עכשיו) שיש גם UCS4Char שהוא 32 ביט.
שחכתי לציין גם שאם אתה עובד נגיד בלזרוס, אז יש לו יחידות נוספות שאין ל FPC ה"רגיל", ושם כן יש כלים להתמודד עם UTF8. למשל לזהות אות, ואם הבית שבחרת הוא לא ההתחלה, אז לזהות איפה ההתחלה. לדעת להעתיק תווים, מיקומים שלהם, מחיקה של תווים וכו' בצורה חכמה יותר (שמתאימה ל multi-byte char)
הוסף תגובה:
חובה לאפשר JavaScript כדי להגיב.