Assign¶
Level: 201 · for anyone with a hex editor open
One line: X[i] = Operand copies one number into every value, so the bytes it writes are decided before it runs — Treat Data As says how many bytes one copy fills and the Endian toggle says their order — which is why Assign 0xFEFF to a Short writes a byte order mark and Assign 0 with Operand Step 1 writes a code-page chart.
What the dialog does¶
010 Editor's manual ↗ gives Assign the shortest line in the list, X[i] = Operand, and the dialog's Description box repeats it. No value is read: what the range held before makes no difference to the result. That makes Assign the cleanest place to watch the other settings work, because the formula cannot hide them — the operand is a number, and a number becomes bytes only after the two decisions Hex: a number, or a picture of bytes is about, a width and an order. The chapter page covers each control once.
In Python¶
Verified output of assign_py.py — regenerated by tools/run_examples.py, never hand-typed.
1. ONE OPERAND, FOUR PATTERNS
------------------------------------------------------------------------
Assign 0x41 over the same eight zero bytes, four ways. The formula
is the same every time; how many bytes one copy fills, and in which
order, is not.
Unsigned Byte 41 41 41 41 41 41 41 41
Unsigned Short, little 41 00 41 00 41 00 41 00
Unsigned Short, big 00 41 00 41 00 41 00 41
Unsigned Int, little 41 00 00 00 41 00 00 00
The second row is 'A' and a NUL, four times -- which is what
UTF-16LE writes for AAAA:
.decode('utf-16-le') 'AAAA'
== 'AAAA'.encode('utf-16-le') True
2. ASSIGN FEFF TO ONE SHORT AND YOU HAVE WRITTEN A BOM
------------------------------------------------------------------------
U+FEFF, the byte order mark, is a 16-bit value. Assign it to the
first Unsigned Short of a file and the Endian toggle picks which of
the two marks you wrote:
little ff fe == codecs.BOM_UTF16_LE: True
big fe ff == codecs.BOM_UTF16_BE: True
3. OPERAND STEP BUILDS THE TABLE EVERY CODE PAGE IS DRAWN ON
------------------------------------------------------------------------
Assign 0 with Operand Step 1 over 256 bytes writes every byte value
once, in order:
the first eight 00 01 02 03 04 05 06 07
the last eight f8 f9 fa fb fc fd fe ff
== bytes(range(256)): True
Decode that file one byte at a time and count what each table calls
a character:
latin-1 256 of 256
cp1252 251 of 256 refuses 81 8d 8f 90 9d
ascii 128 of 256
utf-8 128 of 256
4. THE TYPE DECIDES THE BYTES, NOT ONLY HOW MANY
------------------------------------------------------------------------
Type 1 into the Operand box. What reaches the file depends on the
type it is written as:
Unsigned Byte 01
Unsigned Int, little 01 00 00 00
Unsigned Int, big 00 00 00 01
Float, little 00 00 80 3f
Double, little 00 00 00 00 00 00 f0 3f
A Float or a Double is not the integer in more bytes. It is the
same number in a different notation, and none of its bytes is 01.
5. OPERAND STEP ON A SHORT COUNTS IN CHARACTERS
------------------------------------------------------------------------
Assign 0x41 with Operand Step 1, as a little-endian Unsigned Short,
over eight bytes:
41 00 42 00 43 00 44 00 .decode('utf-16-le') -> 'ABCD'
One operand, many patterns¶
Section 1 is the whole page in eight bytes. Typed as 0x41, the operand is 65 whatever the type. Written as an Unsigned Byte it is one byte, 41, and fills the range eight times; written as a little-endian Unsigned Short it is 41 00, which is A in UTF-16LE, so the same range now reads AAAA to a UTF-16 decoder and A, NUL, A, NUL to everything else.
Section 2 is the same fact with a famous number. U+FEFF is a 16-bit value, so Assign 0xFEFF to the first Unsigned Short of a file writes a byte order mark: FF FE under Little Endian and FE FF under Big Endian, byte for byte what Python's codecs.BOM_UTF16_LE and codecs.BOM_UTF16_BE hold. The toggle chooses which mark, not whether.
Section 4 is the one to remember when the type is Float or Double. A 1 typed into the box does not become 01 padded to four bytes; it becomes the IEEE 754 encoding of 1.0, 00 00 80 3F, and none of those bytes is 01. Treat Data As decides the notation a number is written in, not only its size.
Operand Step writes a table¶
With Operand Step 1, Assign stops being a fill and becomes a counter. Over 256 bytes from 0 it writes every byte value once, in order — the file every code page chart is a picture of — and section 3 hands that file to four decoders one byte at a time: Latin-1 accepts all 256, Windows-1252 refuses the five values it leaves empty, 81 8D 8F 90 9D, and ASCII and UTF-8 accept only the first 128 on their own. Section 5 steps a Short from 0x41 and gets ABCD in UTF-16LE: a step on a two-byte value counts in characters.
What the manual does not say¶
- What Assign writes when the operand does not fit the type — 300 as an Unsigned Byte, or −1 as an Unsigned Short. The program never tries.
- What happens when Operand Step carries the operand past the top of the type partway through a range.
- What becomes of the last few bytes of a range too short to hold a whole value.
The chapter page lists the open questions for all twenty operations.
If you are coming from Python or ABAP¶
Python. There is no fill-with-a-number call, and the reason is this page: a number has to become bytes before it can fill anything, and that is the step where the width and the order are chosen. struct.pack('<H', 0xFEFF) is section 2's first row, struct.pack('<4H', 0x41, 0x42, 0x43, 0x44) is section 5, and bytes(range(256)) is the Operand Step table. To write one into the middle of a bytearray, assign it to a slice of the same length.
ABAP. (Not machine-checked — CI cannot run ABAP.) Assigning an i to an x field is Assign with the Endian toggle on Big: the integer's four bytes are placed right-justified in big-endian order, and padded or cut on the left ↗, so assigning 65 to a TYPE x LENGTH 2 field writes 00 41 on every application server. No assignment writes little-endian; a little-endian field is written by reversing the bytes yourself, which is Swap Bytes.
Try it¶
- In a copy of any file, select sixteen bytes and Assign
0x41with Operand Step 1 as Unsigned Short. Set View > Character Set to Unicode and read the range, then flip View > Endian and read it again. - Assign
0xFEFFto the first two bytes of a UTF-16 text file saved without a mark, and open it in two editors you use. Then do it with the other Endian setting and see which of them notice. - Build section 3's table in 256 bytes of a scratch file and step through View > Character Set, counting in each how many of the 256 draw as a character.
- Assign 1 to the same four bytes as Float and then as Unsigned Int, and read each result in the Inspector as the other type.
See also¶
- Swap Bytes — the operation that turns one byte order mark into the other
- Byte order and the BOM — what
FF FEtells a reader, and what it costs - Code pages — what each table does with the 256 bytes section 3 writes
- Hex: a number, or a picture of bytes — why an operand needs a width and an order before it is bytes