Δεδομένα σταθερού μήκους

vec#

Διαβάζει ή γράφει μια θυρίδα σταθερού πλάτους μέσα σε μια συμβολοσειρά που αντιμετωπίζεται ως πακεταρισμένο διάνυσμα bits.

Η vec θεωρεί την EXPR ως πίνακα μη προσημασμένων ακεραίων, καθένας με πλάτος BITS, πακεταρισμένων ο ένας μετά τον άλλο από την αρχή της συμβολοσειράς. Το OFFSET ευρετηριάζει σε αυτόν τον πίνακα - όχι σε bytes, όχι σε bits, αλλά σε στοιχεία μεγέθους BITS. Η μορφή ανάγνωσης επιστρέφει τον ακέραιο σε αυτή τη θυρίδα· η μορφή lvalue γράφει έναν. Τα πλάτη είναι 1, 2, 4, 8, 16, 32, και σε builds 64-bit το 64.

Σύνοψη#

my $n = vec($buf, $offset, $bits);
vec($buf, $offset, $bits) = $n;

Τι επιστρέφεται#

Σε rvalue περιβάλλον, έναν μη προσημασμένο ακέραιο - τα περιεχόμενα της επιλεγμένης θυρίδας, επεκταμένα με μηδενικά σε αριθμό της Perl. Σε lvalue περιβάλλον, μια εκχωρήσιμη θυρίδα· η εκχώρηση αποκόπτει τη δεξιά τιμή σε BITS και τη γράφει στη συμβολοσειρά, επεκτείνοντας τη συμβολοσειρά με μηδενικά bytes αν το OFFSET βρίσκεται πέρα από το τρέχον τέλος.

Οι παρενθέσεις γύρω από το vec(...) στη μορφή lvalue είναι απαραίτητες - χωρίς αυτές, το vec $buf, $o, $b = 3 αναλύει το = ως μέρος της λίστας ορισμάτων.

Πώς διατάσσονται τα bits#

Η διάταξη εξαρτάται από τα BITS, και επιλέγεται ώστε ο κώδικας να είναι φορητός μεταξύ μηχανών big- και little-endian:

  • BITS == 8: κάθε θυρίδα είναι ένα byte της συμβολοσειράς. Το vec($s, $i, 8) είναι η μη προσημασμένη τιμή του substr($s, $i, 1).

  • BITS == 16, 32, 64: τα bytes της συμβολοσειράς ομαδοποιούνται σε κομμάτια των BITS/8 και ερμηνεύονται σε σειρά big-endian - ισοδύναμο με την unpack με n, N, ή (σε builds 64-bit) Q> / το ηθικό ισοδύναμο. Το vec($s, 0, 32) διαβάζει τα πρώτα τέσσερα bytes ως big-endian uint32.

  • BITS == 4, 2, 1: η συμβολοσειρά σπάει σε bytes, και κάθε byte χωρίζεται σε 8/BITS ομάδες, αριθμημένες little-endian-ish εντός του byte. Οι τιμές bit από χαμηλό σε υψηλό είναι 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80. Έτσι για το chr(0x36) (0b00110110):

    • Το BITS == 4 δίνει τα δύο nibbles (0x6, 0x3).

    • Το BITS == 2 δίνει τις τέσσερις ομάδες των 2 bits (0x2, 0x1, 0x3, 0x0).

    • Το BITS == 1 δίνει τα οκτώ bits (0, 1, 1, 0, 1, 1, 0, 0).

Μια θυρίδα εντελώς εκτός του τέλους της συμβολοσειράς διαβάζεται ως 0. Η εγγραφή πέρα από το τέλος μεγαλώνει τη συμβολοσειρά με μηδενικά bytes για να φτάσει τη θυρίδα. Ένα αρνητικό OFFSET είναι μοιραίο σφάλμα.

Καθολική κατάσταση που επηρεάζει#

Καμία. Η vec λειτουργεί καθαρά επί των ορισμάτων της.

Παραδείγματα#

Διαβάστε ένα byte σε δοσμένο δείκτη:

my $s = "Perl";
print vec($s, 0, 8);            # 80   (== ord 'P')
print vec($s, 3, 8);            # 108  (== ord 'l')

Κατασκευάστε μια συμβολοσειρά γράφοντας λέξεις 32-bit big-endian:

my $buf = '';
vec($buf, 0, 32) = 0x5065726C;  # "Perl"
vec($buf, 1, 32) = 0x50657270;  # "PerlPerp"
print $buf;                     # PerlPerp

Χρησιμοποιήστε τη vec ως συμπαγή πίνακα λογικών τιμών - ένα bit ανά σημαία:

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)

Μετρήστε τα ενεργοποιημένα bits σε διάνυσμα bits χωρίς βρόχο bit-προς-bit - το ιδιωματικό μοτίβο χρησιμοποιεί την unpack:

my $ones = unpack("%32b*", $flags);   # population count

Μετατρέψτε ένα διάνυσμα bits σε συμβολοσειρά από 0 και 1 για εμφάνιση:

my $bits = unpack("b*", $flags);      # "00...010...010..."

Συνδυάστε δύο διανύσματα bits με τους bitwise τελεστές συμβολοσειρών - αυτοί αντιμετωπίζουν τους τελεστέους συμβολοσειρών ως διανύσματα bits του ίδιου σχήματος που διαβάζει και γράφει η 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, η εγγραφή του bit 94 μεγαλώνει τη συμβολοσειρά στα 12 bytes.

  • Αρνητικό OFFSET: μοιραίο - "Negative offset to vec in lvalue context" ή το ισοδύναμο rvalue.

  • Τα BITS δεν είναι υποστηριζόμενη δύναμη του δύο: μοιραίο με "Illegal number of bits in vec". Έγκυρα πλάτη είναι 1, 2, 4, 8, 16, 32, και 64 σε builds 64-bit.

  • Συμβολοσειρές κωδικοποιημένες σε UTF-8: η vec θέλει συμβολοσειρά bytes. Αν το βαθμωτό φέρει τη σημαία UTF-8, η Perl προσπαθεί πρώτα να το υποβιβάσει σε αναπαράσταση ενός byte ανά χαρακτήρα. Αν κάποιος χαρακτήρας έχει codepoint 256 ή υψηλότερο, αυτό αποτυγχάνει μοιραία με "Wide character in vec". Καλέστε την utf8::downgrade σκόπιμα, ή πακετάρετε τα δεδομένα πρώτα με pack "C*", πριν προστρέξετε στη vec.

  • Ανάγνωση σε undef: υπό use warnings, ενεργοποιεί προειδοποίηση uninitialized στο όρισμα συμβολοσειράς· επιστρέφει 0.

  • Τιμή εκχώρησης πλατύτερη από τα BITS: η τιμή μασκάρεται στα κατώτερα BITS bits. Το vec($s, 0, 4) = 0x1F αποθηκεύει 0xF.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • pack - κατασκευάστε δυαδικές δομές πολλαπλών πεδίων· η vec είναι το αντίστοιχο τυχαίας πρόσβασης όταν κάθε πεδίο έχει το ίδιο πλάτος

  • unpack - εξαγάγετε πεδία από δυαδική συμβολοσειρά· χρησιμοποιήστε unpack("b*", $v) ή unpack("%32b*", $v) για να αποδώσετε ή να μετρήσετε popcount ενός διανύσματος bits της vec

  • substr - τυχαία πρόσβαση σε επίπεδο byte όταν τα BITS θα ήταν 8 και θέλετε επίσης η lvalue να μεγαλώσει ή να συρρικνώσει τη συμβολοσειρά

  • sprintf - μορφοποιήστε τον ακέραιο που επιστρέφει μια ανάγνωση vec, π.χ. sprintf "%08b", vec($s, $i, 8)

  • ord - ισοδύναμο μίας εκτέλεσης της vec($s, $i, 8) όταν χρειάζεστε μόνο την τιμή byte και ποτέ δεν εκχωρείτε πίσω