I think this would be simpler if you reversed the logic: i.e. start at contentLength >= 4 to capture utf32 then drop down to utf8, then utf16.  You then don't need all the checks for utf16LE.