vec#
קריאה או כתיבה של חריץ ברוחב קבוע בתוך מחרוזת המטופלת כווקטור ביטים ארוז.
vec רואה את EXPR כמערך של מספרים שלמים חסרי־סימן, כל אחד ברוחב BITS, ארוזים גב־אל־גב מתחילת המחרוזת. OFFSET מאנדקס לתוך אותו מערך - לא לתוך בתים, לא לתוך ביטים, אלא לתוך אלמנטים בגודל BITS. צורת הקריאה מחזירה את המספר השלם באותו חריץ; צורת ה־lvalue כותבת אחד. הרוחבים הם 1, 2, 4, 8, 16, 32, ובמהדורות 64־ביט גם 64.
תקציר#
my $n = vec($buf, $offset, $bits);
vec($buf, $offset, $bits) = $n;
מה מקבלים בחזרה#
בהקשר rvalue, מספר שלם חסר־סימן - תוכן החריץ הנבחר, מורחב באפסים למספר Perl. בהקשר lvalue, חריץ הניתן להשמה; השמה חותכת את הערך הימני ל־BITS וכותבת אותו לתוך המחרוזת, מרחיבה את המחרוזת בבתי אפס אם OFFSET חורג מהסוף הנוכחי.
הסוגריים סביב vec(...) בצורת ה־lvalue נדרשים - בלעדיהם, vec $buf, $o, $b = 3 מפרסר את ה־= כחלק מרשימת הארגומנטים.
כיצד הביטים מסודרים#
הפריסה תלויה ב־BITS, ונבחרת כך שהקוד יהיה נייד בין מכונות big-endian ו־little-endian:
BITS == 8: כל חריץ הוא בית אחד של המחרוזת.vec($s, $i, 8)הוא הערך חסר־הסימן שלsubstr($s, $i, 1).BITS == 16,32,64: בתי המחרוזת מקובצים לחלקים שלBITS/8ומפורשים בסדר big-endian - שווה־ערך ל־unpackעםn,N, או (במהדורות 64־ביט)Q>/ המקבילה המוסרית.vec($s, 0, 32)קורא את ארבעת הבתים הראשונים כ־uint32big-endian.BITS == 4, 2, 1: המחרוזת מפורקת לבתים, וכל בית מפוצל לקבוצות של8/BITS, ממוספרות בסדר דמוי־little-endian בתוך הבית. ערכי הביטים מהנמוך לגבוה הם0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80. אז עבורchr(0x36)(0b00110110):BITS == 4נותן את שני ה־nibbles(0x6, 0x3).BITS == 2נותן את ארבע קבוצות הדו־ביט(0x2, 0x1, 0x3, 0x0).BITS == 1נותן את שמונת הביטים(0, 1, 1, 0, 1, 1, 0, 0).
חריץ הנמצא כולו מחוץ לסוף המחרוזת נקרא כ־0. כתיבה מעבר לסוף מגדילה את המחרוזת בבתי אפס כדי להגיע לחריץ. OFFSET שלילי הוא שגיאה קטלנית.
מצב גלובלי שהוא נוגע בו#
אין. vec פועל אך ורק על הארגומנטים שלו.
דוגמאות#
קריאת בית באינדקס נתון:
my $s = "Perl";
print vec($s, 0, 8); # 80 (== ord 'P')
print vec($s, 3, 8); # 108 (== ord 'l')
בניית מחרוזת על־ידי כתיבת מילים big-endian של 32־ביט:
my $buf = '';
vec($buf, 0, 32) = 0x5065726C; # "Perl"
vec($buf, 1, 32) = 0x50657270; # "PerlPerp"
print $buf; # PerlPerp
שימוש ב־vec כמערך בוליאני קומפקטי - ביט אחד לכל דגל:
my $flags = '';
vec($flags, 17, 1) = 1;
vec($flags, 42, 1) = 1;
print vec($flags, 17, 1); # 1
print vec($flags, 18, 1); # 0 (slot never set, still zero)
print length $flags; # 6 (string auto-extended to fit bit 42)
ספירת הביטים הקבועים בווקטור ביטים בלי לעבור ביט־ביט בלולאה - התבנית האידיומטית משתמשת ב־unpack:
my $ones = unpack("%32b*", $flags); # population count
המרת ווקטור ביטים למחרוזת של 0־ים ו־1־ים להצגה:
my $bits = unpack("b*", $flags); # "00...010...010..."
שילוב שני ווקטורי ביטים עם אופרטורי המחרוזת הביטיים - אלה מטפלים באופרנדי מחרוזת כווקטורי ביטים באותה צורה ש־vec קורא וכותב:
my $union = $flags_a | $flags_b;
my $intersection = $flags_a & $flags_b;
my $diff = $flags_a ^ $flags_b;
מקרי קצה#
קדימות lvalue:
vec EXPR, O, B = Nהיא שגיאת תחביר. יש לכתוב תמידvec(EXPR, O, B) = N.קריאה מחוץ לסוף:
vec($short, 1_000_000, 8)מחזיר0, לעולם אינו מת, לעולם אינו מזהיר.כתיבה מחוץ לסוף: המחרוזת מרופדת באפסים עד לחריץ. עבור
BITS == 1, כתיבת ביט 94 מגדילה את המחרוזת ל־12 בתים.OFFSETשלילי: קטלני -"Negative offset to vec in lvalue context"או המקבילה ב־rvalue.BITSאינו חזקת שתיים נתמכת: קטלני עם"Illegal number of bits in vec". הרוחבים התקפים הם 1, 2, 4, 8, 16, 32, ו־64 במהדורות 64־ביט.מחרוזות מקודדות UTF-8:
vecרוצה מחרוזת בתים. אם הסקלר מתויג UTF-8, Perl מנסה תחילה להוריד אותו לייצוג של בית־אחד־לכל־תו. אם לתו כלשהו יש נקודת קוד של 256 או יותר, הדבר נכשל קטלנית עם"Wide character in vec". יש לקרוא ל־utf8::downgradeבמכוון, או לארוז את הנתונים עםpack"C*"תחילה, לפני שפונים ל־vec.קריאה על
undef: תחתuse warnings, מפעיל אזהרתuninitializedעל ארגומנט המחרוזת; מחזיר0.ערך השמה רחב מ־
BITS: הערך ממוסך לביטים הנמוכים שלBITS.vec($s, 0, 4) = 0x1Fמאחסן0xF.
הבדלים מ־upstream#
תואם מלא ל־upstream Perl 5.42.
ראו גם#
pack- לבנות מבני בינארי רבי־שדות;vecהוא המקבילה לגישה רנדומלית כאשר לכל שדה יש אותו רוחבunpack- לשלוף שדות ממחרוזת בינארית; יש להשתמש ב־unpack("b*", $v)אוunpack("%32b*", $v)כדי להציג או לעשות popcount לווקטור ביטים שלvecsubstr- גישה רנדומלית ברמת הבית כאשרBITSהיה8ורוצים גם של־lvalue יגדיל או יקטין את המחרוזתsprintf- לעצב את המספר השלם שקריאתvecמחזירה, למשלsprintf "%08b", vec($s, $i, 8)ord- שווה־ערך חד־פעמי ל־vec($s, $i, 8)כאשר נדרש רק ערך הבית ולעולם אין השמה חזרה