If I need to copy some memory of a given size, is there a typical Forth word to do this? Something like C's memcpy
or memmove
?
1 Answers
Copying memory
The Forth standard defines MOVE
in the Core word set, for copying arbitrary memory:
MOVE
( addr1 addr2 u -- )
If u is greater than zero, copy the contents of u consecutive address units at addr1 to the u consecutive address units at addr2. AfterMOVE
completes, the u consecutive address units at addr2 contain exactly what the u consecutive address units at addr1 contained before the move.
Like memmove
, MOVE
allows the source and destination to overlap, as if the copy had happened using an intermediate buffer.
Propagating strings
The Forth standard also defines CMOVE
and CMOVE>
in the String word set:
CMOVE
( c-addr1 c-addr2 u -- )
If u is greater than zero, copy u consecutive characters from the data space starting at c-addr1 to that starting at c-addr2, proceeding character-by-character from lower addresses to higher addresses.
CMOVE>
( c-addr1 c-addr2 u -- )
If u is greater than zero, copy u consecutive characters from the data space starting at c-addr1 to that starting at c-addr2, proceeding character-by-character from higher addresses to lower addresses.
CMOVE
and CMOVE>
copy characters one-by-one, in order, beginning at the start and end of the strings respectively.
MOVE
is already capable of copying strings safely (using CHARS
for full compliance with the standard). But CMOVE
and CMOVE>
can be used to repeat portions of a string easily, or implement algorithms similar to LZ77 decompression. This is known as propagation. For example:
\ Allocate space for a string, starting with AB
CREATE str 'A' C, 'B' C, 18 CHARS ALLOT
str 2 TYPE \ prints AB
\ Use CMOVE to propagate AB over rest of string
str str 2 CHARS + 18 CMOVE
str 20 TYPE \ prints ABABABABABABABABABAB
CMOVE>
is also known as <CMOVE
in older Forths.
There is a COPY
word in some Forths for writing a block's contents over another block easily.