קידוד תווים

קִידּוּד תווים הוא התאמה בין קבוצת תווים לקבוצה אחרת, למשל מספרים או אותות חשמליים, שנועדה לרוב לאפשר אחסונו של טקסט על גבי מחשב או לאפשר שליחתו של טקסט דרך אמצעי תקשורת שונים. דוגמה פשוטה ומוכרת לקידוד תווים היא קוד מורס, המקודד אותיות לטיניות לרצף קווים ונקודות, או לחלופין ללחיצות קצרות וארוכות על כפתור הטלגרף לשם שליחתם דרכו למכשיר טלגרף אחר. דוגמה נוספת היא קוד ASCII, המקודד אותיות, ספרות וסימנים אחרים למספרים בינאריים באורך 7 סיביות.

רקע

משחר ההיסטוריה מנצלת החברה האנושית צורות גרפיות לשם העברת מסרים, החל מכתב החרטומים העתיק וכלה באלפבית המודרני. הצורך בקידוד תווים עולה כאשר ברצוננו להשתמש באותן צורות גרפיות, אותן אנו מכירים ומזהים, אך מסיבות אלו ואחרות הדבר נבצר מאיתנו. משמעותו של קידוד התווים הוא המרתן של הצורות למשהו אחר, בו אנו כן יכולים להשתמש, והעברת המסר בצורה עקיפה זו. חשוב לציין שלא מדובר בתרגום, אלא העברה מלאה של הצורה הגרפית למשהו אחר התואם לה בדיוק. בקידוד נתונים ניתן לומר שמקבל המסר יכול "לראות בעיני רוחו" את אותן צורות גרפיות שקודדנו משום שבסה"כ אנחנו נותנים לו הצגה אחרת שלהן.
דוגמה לקידוד תווים לא-מודרני, שהומצא בשנת 1821, היא כתב ברייל. למרות שברשותנו אותיות, סימן גרפי מוכר ונח המשמש אותנו להעברת מסרים, נבצר מאנשים עיוורים להשתמש בו משום שהם אינם יכולים לראות את הסימן. כתב ברייל יוצר התאמה בין האותיות לקבוצות של שש נקודות שחלקן בולטות וחלקן לא. אדם עיוור מסוגל להשתמש בצורה המקודדת על ידי מישוש ואבחנה בין נקודה בולטת לנקודה לא בולטת וכך הוא מסוגל להבין את המסר שברצוננו להעביר.
קידוד תווים לא-מודרני נוסף הוא קוד מורס שהומצא בשנת 1835. גם כאן מדובר בקידודו של אלפבית אך הפעם הסיבה היא אינה מגבלה אנושית אלא מגבלה טכנולוגית. מכשיר הטלגרף אינו מסוג להעביר אותיות וספרות אך הוא כן מסוגל להעביר אותות חשמליים, קוד מורס מתאים לכל תו רצף של אותות חשמליים וכך ניתן להעביר את התווים דרך מכשיר הטלגרף.
העידן המודרני הציג את המחשב. בצורה גסה ביותר ניתן לומר שהמחשב הוא מכונה המסוגלת לאחסן אך ורק מספרים וליתר דיוק מספרים בינאריים. זאת היא עושה על ידי אותות חשמליים המייצגים את הערכים הבינאריים 0 ו-1. לעומת זאת, נדרש מהמחשב לייצג סימנים שונים ומורכבים: אלפבית בשפות שונות, סימני ניקוד, סימנים מתמטיים שונים ותווים נוספים שהצורך לייצגם עלה עם השנים. עלה הצורך לייצג את כל אותם תווים באמצעות מספרים בלבד וכך הפך נושא קידוד התווים לנושא מרכזי במדעי המחשב.
בתחילת הדרך, המונח "קידוד תווים", בהתייחס למדעי המחשב, טמן בחובו הן את אוסף התווים בהם תומך הקידוד והן את הדרך בה תווים אלה יקודדו וכיצד יישמר הקידוד במערכות המחשב. הגדרה זו לא סיפקה את צרכיה המשתנים של האנושות שדרשה ייצוג יעיל, אמין וחסכוני של תווים רבים.

דגם קידוד

תקני הקידוד יוניקוד ו-ISO 10646, שהתאחדו יחדיו לקידוד תווים אחיד, הציגו לראשונה את הדגם החדש של קידוד תווים. דגם זה מחדש בכך שהוא מחלק את הקידוד למספר חלקים. במקום לציין מיד את התווים ודרך קידודם במחשב, אנו מפרידים בין ההגדרה של מהם התווים הקיימים בקידוד, מהו המספר התואם לכל תו, כיצד מספרים אלו מקודדים לרצפי "יחידות קוד" (מספרים "קטנים" באורך קבוע) ולבסוף כיצד רצפים אלו מקודדים לרצפי אוקטטות (בתים). הרעיון מאחורי הפרדה זו הוא ליצור קבוצת תווים אחידה ומשותפת לכל העולם, אותה ניתן לקודד בדרכים שונות. מטרה זו מושגת בכך שהגדרת התווים היא חלק נפרד מההגדרה כיצד לקודד אותם. הגדרת התווים רשומה בצורה רשמית וכל צורת קידוד יכולה להסתמך על הגדרה זו, בניגוד לקידודים ישנים בהם הגדרת התווים הייתה מוטמעת בדרך הקידוד.
אם כן, קידוד תווים הוא כעת שילוב של מספר הגדרות חדשות. יש לציין שקיימים חילוקי דעות בנוגע למושגים המשמשים להגדרתו של כל חלק וכן גם תרגומים שונים של מונחים אלה לשפה העברית.

רפרטואר תווים

רפרטואר תווים הוא קבוצת כל התווים בהם תומך הקידוד. אלו הם כל התווים שקידוד זה יכול לקודד. הרפרטואר יכול להיות סגור, כלומר, שלא ניתן להוסיף לו תווים חדשים מבלי ליצור תקן חדש (כך ב־ASCII ובמרבית תקני ISO 8859), או שהוא יכול להיות פתוח, כלומר, מאפשר הוספת תווים חדשים (כך ביוניקוד).
כפי שצוין קודם לכן, קידוד תווים הוא התאמה בין תו למשהו אחר. בניית רפרטואר התווים מהווה את השלב הראשוני ביצירת אותה התאמה, זהו השלב בו אנו עונים על השאלה המהותית "מהו תו?". נניח ונרצה לקודד את המילה "שָׁם" המתחילה באות שי"ן ימין עם קמץ מתחתיה, האם האות שי"ן היא תו נפרד או שמא הנקודה בצדה הימני היא חלק מאותו תו? האם הקמץ מהווה חלק מהתו או שאולי הוא תו נפרד? קידוד מילה נעשה על ידי קידוד של כל תו במילה, כדי לעשות זאת עלינו לפרק את המילה לאוסף של תווים הכתובים בזה אחר זה, בצורה ליניארית, אז נוכל לקודדם האחד אחרי השני. דרושה החלטה בנוגע לדרך לפרק את השפה לתווים, יחידות קטנות שנוכל לרשום ברצף והן ייצגו כל טקסט אפשרי בשפה, החלטה זו מתבטאת בבניית רפרטואר התווים בו אנו רושמים את כל אותן יחידות קטנות.
נבחן את האלפבית העברי כמקרה מייצג, ניתן לחלקו לאותיות, ספרות, סימני פיסוק ומספר תווים מיוחדים כמו תו הרווח. כל טקסט בשפה העברית ניתן לרישום באמצעות רצפים המורכבים מהיחידות הנ"ל. כתיבתו של טקסט מנוקד מוסיפה נדבך נוסף של קושי, שכן יש צורך להחליט באיזו צורה ייוצגו אותיות מנוקדות. ניתן ליצור תווים ייחודיים המייצגים אות עם סימן ניקוד, דבר המכונה בעגה המקצועית "תו מורכב מראש" (precomposed character), או לחלופין, ניתן לייצג את סימני הניקוד עצמם בתור תווים נפרדים. השימוש בתווים מורכבים מראש קל יותר ומאפשר דרכים פשוטות להתמודד עם הטקסט, כל אות מנוקדת תהווה תו בפני עצמה ופשוט נקודד אותה בהתאם. לא נדרשים חוקים מיוחדים הקובעים כיצד לשלב בין תו המייצג אות לתו המייצג סימן ניקוד ואין צורך לדאוג למקרה של מספר סימני ניקוד על אותה אות, פשוט ניצור תו נוסף. שיטה זו, מאידך, תצרוך מאיתנו לחשוב על כל האפשרויות של אות וניקודיה ולהוסיף תו מיוחד לכל אפשרות, מעשה בזבזני במקום שעלול להוביל גם לאפשרות שנשכח או לא נחשוב על צירוף מסוים ואחר-כך לא ניתן יהיה לייצגו באמצעות קידוד זה. לחלופין, ייצוג כל סימן ניקוד כתו נפרד יצרוך אמנם יצירת חוקים מהסוג שהוזכרו לעיל, אך יאפשר הצגתו של כל שילוב שהוא בין אות לסימן או מספר סימני ניקוד וזאת תוך שימוש במספר תווים מינימלי - מספר האותיות ומספר סימני הניקוד. קידוד היוניקוד, למשל, תומך בשתי הדרכים. בעיה דומה, עם פתרונות דומים, מופיעה גם בניסיון לייצג את האלפבית הלטיני, היווני והקירילי, בו קיימים סימנים דיאקרטיים המופיעים על חלק מן האותיות. בעיות נוספות העלולות לצוץ בעת ניסיון חלוקתה של השפה הם עניין הדו-כיווניות, כפי שקיים בעברית ובשפות נוספות בהן הכתיבה מבוצעת מימין לשמאל, בניגוד למרבית השפות, וכן הבעיה של הצורך בהצגתם של תווים מסוימים בצורה מחוברת כאשר סגנון החיבור תלוי בתווים עצמם, בעיה המופיעה בשפה הערבית, למשל.

מערכת תווים מקודדת

מערכת תווים מקודדת (באנגלית: Coded Character Set) מגדירה כיצד לייצג רפרטואר תווים באמצעות שלמים לא-שליליים המכונים "נקודות קוד". אנו מתאימים לכל תו מספר שייצג אותו מעתה והלאה. לדוגמה, ביוניקוד מותאמת האות העברית אל"ף למספר 1488. כאן אנו מבצעים את ההתאמה עליה דיברנו כאשר הגדרנו מהו קידוד תווים. במדעי המחשב קיימת הנחה סמויה שההתאמה בקידודי התווים השונים היא תמיד בין תווים למספרים שלמים לא-שליליים.
מספר יכול לייצג תו אחד בלבד, אסור שיקרה מצב בו מספר אחד מייצג תווים רבים, זה ייצור עמימות ולא יאפשר פענוח אמין של הטקסט לאחר הקידוד. לעומת זאת, ייתכן ומספרים שונים ייצגו את אותו התו, תופעה זו מתרחשת ביוניקוד, למשל, מטעמי תאימות לאחור לקידודים ישנים יותר.
מספר קבוצות תווים מקודדות יכולות לחלוק רפרטואר תווים משותף, קידוד התווים ISO-8859-1 ודפי קוד 037 ו-500 של דפי הקוד של יבמ מכסים כולם את אותו רפרטואר התווים אך כל אחד מהם ממפה את התווים למספרים שונים.

צורת קידוד תווים

צורת קידוד תווים (באנגלית: Character Encoding Form (CEF)‎) מגדירה כיצד יש להמיר את נקודות הקוד, הערכים המספריים המוגדרים במערכת התווים המקודדת, ל"ערכי קוד", רצף שלמים בגודל מוגבל.
מחשבים מייצגים מספרים בצורה בינארית תוך שימוש במספר קבוע של סיביות. מספר הסיביות משתנה ממחשב למחשב. משום שמספר הסיביות המשמש להצגתו של מספר, קבוע, ניתן לייצג רק מספרים עד לגודל מסוים. לדוגמה, מחשב המשתמש ביחידות של 16 סיביות לשם ייצוג מספר יוכל לייצג באופן ישיר רק את המספרים בין 0 ל-65,535. ערכן של נקודות הקוד שרירותי ואינו מוגבל על ידי אילוצים של ייצוג בסיביות ואכן בקידודים מסוימים הוא בין 0 ל-1.4 מיליון למשל. כדי לייצג מספרים אלה, ניתן לנקוט בדרך העקיפה של שימוש במספר יחידות של 16 סיביות לשם ייצוגו של מספר בודד.
צורת קידוד תווים היא מיפוי של "נקודת קוד", מספר המייצג תו וערכו שרירותי, לרצף של אחד או יותר "ערכי קוד", שהם אותם מספרים שהמחשב יכול לייצג וכל אחד מהם בגודל מוגבל, 0 עד 65,535, למשל. צורת קידוד התווים תקבע כיצד יש לקודד את המספרים הגדולים וכיצד לפענח אחר-כך את המספרים הכתובים בזיכרון המחשב. כך למשל, שימוש בצורת קידוד התווים UTF-8 יוביל לכך שבזיכרון המחשב ייכתבו האחד אחרי השני המספרים 215 ו-144, אך הכוונה תהיה למספר 1488 שהוא נקודת הקוד של האות העברית אל"ף.
צורת קידוד התווים הפשוטה ביותר היא בחירת מספר יחידות שיספיק לייצוגה של כל נקודת קוד במערכת התווים המקודדת בצורה ישירה. נקבע למשל, שאם המערכת משתמשת כיחידה בסיסית ב-8 סיביות, אנחנו נקרא כל פעם שני מספרים שכאלה ונתייחס אליהם כמספר אחד באורך 16 סיביות. שיטה זו עובדת מצוין עבור מערכות תווים מקודדות שאת נקודות הקוד הגדולים ביותר בהן ניתנים לייצוג על ידי 8 סיביות (כמו למשל ASCII), וניתן להשתמש בה גם עבור מערכות בהן דרושות 16 סיביות לשם ייצוג נקודות הקוד. שיטה זו מתחילה להוות מועקה כשאנו מדברים על מערכות תווים גדולות יותר, כמו למשל ביוניקוד בה דרושות לפחות 21 סיביות. זיכרון רב מתבזבז ומערכות קיימות מתקשות להתמודד עם יחידות בסיסיות בגדלים אלו. לכן, רב המערכות כיום תומכות בשימוש בצורות קידוד תווים מתוחכמות יותר, כמו UTF-8 או UTF-16, בהן ניתן להשתמש במספר משתנה של בתים  לייצוג כל תו.

סכימת קידוד תווים

סכימת קידוד התווים (באנגלית: Character Encoding Scheme (CES)‎) מגדירה כיצד ימופו ערכי הקוד, השלמים שגודלם מוגבל, לרצף של אוקטטות, או במילים אחרות בתים שהם יחידות של 8 סיביות, כדי לאחסנם במערכת מבוססת אוקטטות, או לשדרם ברשת מבוססת אוקטטות.
לרב, אין צורך בציון מיוחד משום שמראש בחרנו בערכי הקוד כך שניתן יהיה לייצגם על ידי 8 סיביות או שקבענו כיצד יש להשתמש ביחידות של 8 סיביות כדי לייצגם. ביוניקוד למשל, סכימת קידוד התווים פשוטה למדי ומציינת לרב רק אם יש צורך בהצגת ערכי הקוד בצורה של big-endians או little-endians, וגם זה לא נדרש כאשר משתמשים ב-UTF-8. למרות זאת, לעיתים נחוץ שימוש בסכימות קידוד תווים מתקדמות יותר, המשתמשים בערכי מילוט לשם החלפה בין מספר סכימות פשוטות יותר (כך ב ISO 2022), ובין סכימות כיווץ, המנסות לצמצם את מספר הבתים בו נעשה שימוש לכל נקודת קוד (לדוגמה, סכימת הכיווץ הסטנדרטית ליוניקוד,Standard Compression Scheme for Unicode (SCSU), BOCU, ו-Punycode).