Say we have an arbitrary long array of bytes read with the sysread() Perl function that we have to split in a fixed number of CHARS avoiding to truncate in the middle of an unicode grapheme.
As an example, say we have to split an array of bytes in chunks of 5 CHARS and that we have the following byte sequence:
0x61 0x62 0x63 0x64 0x65 0xcc 0x81 0x61 0x62 0x63 0x64 0xe2 0x82 0xac
Reading the last byte of the first 5 bytes (0X65) we get that it is a valid grapheme (char e) and scanning byte per byte the second byte sequence rightward and testing (using the \X matcher) the increasing sequence (first 0xCC, then 0xCC 0x81) we get that the sequence 0xCC 0x81 is also a valid grapheme (a non printable char or a strange space), but the correct grapheme is 0x65 0xCC 0x81 (char é).
My try was, starting from the cut point (e.g. between 5th and 6th byte), to test if the left byte (in our case 0x65) falls or not in the [\xC0-\xFF] range.
If NOT: add byte per byte from the right sequence and truncate the sequence when the matcher /^\X$/ returns false and this approach in my tests worked fine.
My problem is that when the last byte of first sequence falls in the range [\xC0-\xFF] it means I might be in the middle of a grapheme and then I go crazy because I can't figure out how to correctly identify the boundaries of the grapheme cluster (as they may be arbitrarily long).
Note 1: I can't UTF-8 encode the whole input file and work at CHAR level because I have to deal with files of some TB and the performance is a must.
Note 2: I read the excellent Tom Chirstiansen's Perl Unicode Cookbook and it helped me a lot to better understand some Unicode basis but not to find a way to solve my problem.
Any help or tip would be really appreciated
PS: Should I consider using the C++ ICU library instead of Perl?
UPDATE I omitted for sake of semplicity that I don't scan the whole file, but I do a parallel processing of fixed length chunks of the file using the sysread() with an offset.. then I use the sysseek() on each chunk boundary to look ahead or backward, searching for the grapheme boundaries.