My goal is to efficiently overwrite several sections of a blob, while leaving its overall content and structure pristine. To this end, I have written the following functions:
replace :: ByteString -> Int -> ByteString -> ByteString
replace source offset replacement = prefix <> replacement <> suffix
where
prefix = ByteString.take offset source
suffix = ByteString.drop (offset + ByteString.length replacement) source
fix :: Int -> ByteString -> ByteString -> ByteString
fix offset replacement source = replace source offset replacement
And this is how they work:
λ replace "I have a cat." 0x09 "dog"
"I have a dog."
λ fix 0x0A "fat" . fix 0x03 "dog" $ "My cat is red."
"My dog is fat."
Unfortunately, <>
= append
is linear time, and therefore these functions too. Having the
knowledge that the replacement is just as long as the section being replaced, surely we can do
better?
I would be especially joyful if it happens that we can replace multiple sections in time less than linear over the number of replacements.