Is there a native function to detect if file is UTF encoding?
    Kiith-Sa via Digitalmars-d 
    digitalmars-d at puremagic.com
       
    Fri Aug 22 07:59:00 PDT 2014
    
    
  
On Friday, 22 August 2014 at 13:53:04 UTC, MacAsm wrote:
> To call decode() from std.encoding I need to make sure it is an 
> UTF (may ne ASCII too) otherwise is will skyp over ASCII 
> values. Is there any D native for it or I need to check byte 
> order mark and write one myself?
This may be simpler for reference:
https://github.com/kiith-sa/tinyendian/blob/master/source/tinyendian.d
Note that you _can't_ reliably differentiate between UTF-8 and 
plain ASCII,
because not all UTF-8 files start with a UTF-8 BOM.
However, you can (relatively) quickly determine if a UTF-8/ASCII 
buffer contains only ASCII characters; as UTF-8 bytes always have 
the topmost bit set, and ASCII don't, you can use a 64-bit 
bitmask and check by 8 characters at a time.
See 
https://github.com/kiith-sa/D-YAML/blob/master/source/dyaml/reader.d,
specifically the countASCII() function - it should be easy to 
change it into 'detectNonASCII':
/// Counts the number of ASCII characters in buffer until the 
first UTF-8 sequence.
///
/// Used to determine how many characters we can process without 
decoding.
size_t countASCII(const(char)[] buffer) @trusted pure nothrow 
@nogc
{
     size_t count = 0;
     // The topmost bit in ASCII characters is always 0
     enum ulong Mask8 = 0x7f7f7f7f7f7f7f7f;
     enum uint Mask4 = 0x7f7f7f7f;
     enum ushort Mask2 = 0x7f7f;
     // Start by checking in 8-byte chunks.
     while(buffer.length >= Mask8.sizeof)
     {
         const block = *cast(typeof(Mask8)*)buffer.ptr;
         const masked = Mask8 & block;
         if(masked != block) { break; }
         count += Mask8.sizeof;
         buffer = buffer[Mask8.sizeof .. $];
     }
     // If 8 bytes didn't match, try 4, 2 bytes.
     import std.typetuple;
     foreach(Mask; TypeTuple!(Mask4, Mask2))
     {
         if(buffer.length < Mask.sizeof) { continue; }
         const block = *cast(typeof(Mask)*)buffer.ptr;
         const masked = Mask & block;
         if(masked != block) { continue; }
         count += Mask.sizeof;
         buffer = buffer[Mask.sizeof .. $];
     }
     // If even a 2-byte chunk didn't match, test just one byte.
     if(buffer.empty || buffer[0] >= 0x80) { return count; }
     ++count;
     return count;
}
    
    
More information about the Digitalmars-d
mailing list