};
// following method encodes an utf8 character into a byte buffer.
- // NOTE: If 'bytes' is null, this function only counts bytes and chars
- // without writing anything.
+ // NOTE: If 'byteCount' is < 0, this function only counts used bytes
+ // without writing anything.
// NOTE: BOM (0xEF 0xBB 0xBF) is not yet supported.
// See http://www.cl.cam.ac.uk/~mgk25/unicode.html
private unsafe static EncoderStatus InternalGetByte (
charsProcessed++;
charCount--;
if (ch < (uint) 0x80) {
- if (bytes != null) {
+ if (byteCount >= 0) {
if (byteCount < 1)
return EncoderStatus.InsufficientSpace;
*bytes++ = (byte) ch;
}
bytesProcessed++;
} else if (ch < (uint) 0x0800) {
- if (bytes != null) {
+ if (byteCount >= 0) {
if (byteCount < 2)
return EncoderStatus.InsufficientSpace;
*bytes++ = (byte) ((uint) 0xC0 | (ch >> 6) & 0x3f);
}
bytesProcessed += 2;
} else if (ch < (uint) 0xD800 || ch > (uint) 0xDFFF) {
- if (bytes != null) {
+ if (byteCount >= 0) {
if (byteCount < 3)
return EncoderStatus.InsufficientSpace;
*bytes++ = (byte) ((uint) 0xE0 | (ch >> 12));
// We have a correct surrogate pair.
ch = 0x10000 + (uint) ch - (uint) 0xDC00
+ ((leftChar - (uint) 0xD800) << 10);
- if (bytes != null) {
+ if (byteCount >= 0) {
if (byteCount < 4)
return EncoderStatus.InsufficientSpace;
*bytes++ = (byte) (0xF0 | (ch >> 18));
// This function is called when we want to flush the decoder state
// (i.e. in case of invalid UTF-16 characters or dangling surrogates)
- internal unsafe static void InternalGetBytes_flush (
+ internal unsafe static void InternalGetBytesFlush (
byte* bytes, int byteCount,
EncoderFallbackBuffer fallbackBuffer,
int charsProcessed, ref int bytesProcessed,
int t_charsProcessed, t_bytesProcessed;
// in normal circumstances fallbackBuffer never is null, except
- // for avoiding infinite recursive calls when we have called
- // InternalGetBytes from this function
+ // when we have called InternalGetBytes from this function
+ // (for avoiding infinite recursive calls)
if (fallbackBuffer == null)
return;
fixed (char *fb_chars = fallback_chars) {
leftChar = 0;
switch (bytes != null
- ? InternalGetBytes (fb_chars, fallback_chars.Length,
- bytes + bytesProcessed, byteCount - bytesProcessed,
- null, out t_charsProcessed, out t_bytesProcessed,
- ref leftChar,
- true)
- : InternalGetBytes (fb_chars, fallback_chars.Length,
- null, 0,
- null, out t_charsProcessed, out t_bytesProcessed,
- ref leftChar,
- true)) {
+ ? InternalGetBytes (
+ fb_chars, fallback_chars.Length,
+ bytes + bytesProcessed, byteCount - bytesProcessed,
+ null, out t_charsProcessed, out t_bytesProcessed,
+ ref leftChar,
+ true)
+ : InternalGetBytes (
+ fb_chars, fallback_chars.Length,
+ null, byteCount,
+ null, out t_charsProcessed, out t_bytesProcessed,
+ ref leftChar,
+ true)) {
case EncoderStatus.Ok:
// everything OK :D
bytesProcessed += t_bytesProcessed;
leftChar = 0;
}
+ // InternalGetBytes processor. Can encode or count space needed for
+ // encoding, depending on the enabled mode:
+ // - encoder
+ // enabled when byteCount >= 0 (but bytes may be null)
+ // - counter
+ // enabled when bytes == null && byteCount < 0
internal unsafe static EncoderStatus InternalGetBytes (
char* chars, int charCount,
byte* bytes, int byteCount,
else
if (charCount > 0 && chars == null)
throw new ArgumentNullException ("chars");
- if (byteCount < 0)
- throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_NonNegative"));
- else
- if(byteCount > 0 && bytes == null)
+ if (bytes == null)
+ {
+ if (byteCount > 0)
throw new ArgumentNullException ("bytes");
+ } else {
+ if (byteCount <= 0)
+ throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_NonNegative"));
+ }
// reset counters
charsProcessed = 0;
out t_charsProcessed, out t_bytesProcessed, ref leftChar)
: InternalGetByte (
chars + charsProcessed, charCount - charsProcessed,
- null, 0,
+ null, byteCount,
out t_charsProcessed, out t_bytesProcessed, ref leftChar);
// if not enough space return here
case EncoderStatus.InputRunOut:
if (flush)
- InternalGetBytes_flush (
+ InternalGetBytesFlush (
bytes, byteCount,
fallbackBuffer,
charsProcessed, ref bytesProcessed,
case EncoderStatus.InvalidChar:
case EncoderStatus.InvalidSurrogate:
- InternalGetBytes_flush (
+ InternalGetBytesFlush (
bytes, byteCount,
fallbackBuffer,
charsProcessed, ref bytesProcessed,
return EncoderStatus.Ok;
}
- internal unsafe static EncoderStatus InternalGetBytes (
+ internal unsafe static EncoderStatus InternalGetBytesEncode (
+ char* chars, int charCount,
+ byte* bytes, int byteCount,
+ EncoderFallbackBuffer fallbackBuffer,
+ out int charsProcessed, out int bytesProcessed,
+ ref uint leftChar,
+ bool flush)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException ("byteCount", _("ArgRange_Array"));
+
+ return InternalGetBytes (
+ chars, charCount,
+ bytes, byteCount,
+ fallbackBuffer,
+ out charsProcessed, out bytesProcessed,
+ ref leftChar,
+ flush);
+ }
+
+ internal unsafe static EncoderStatus InternalGetBytesEncode (
char[] chars, int charIndex, int charCount,
byte[] bytes, int byteIndex,
EncoderFallbackBuffer fallbackBuffer,
{
if (chars == null)
throw new ArgumentNullException ("chars");
+ if (bytes == null)
+ throw new ArgumentNullException ("bytes");
if (charIndex < 0 || charIndex >= chars.Length)
throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
if (charCount < 0 || charCount > (chars.Length - charIndex))
throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
- if (byteIndex < 0 || byteIndex > (bytes != null && bytes.Length > 0 ? bytes.Length : 0))
+ if (byteIndex < 0 || byteIndex > bytes.Length)
throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
unsafe {
fixed (byte *bptr = bytes) {
return InternalGetBytes (
cptr + charIndex, charCount,
- bytes != null ? bptr + byteIndex : null,
- bytes != null ? bytes.Length - byteIndex : 0,
+ bptr + byteIndex, bytes.Length - byteIndex,
fallbackBuffer,
out charsProcessed, out bytesProcessed,
ref leftChar,
}
}
+ internal unsafe static EncoderStatus InternalGetBytesCount (
+ char* chars, int charCount,
+ EncoderFallbackBuffer fallbackBuffer,
+ out int charsProcessed, out int bytesProcessed,
+ ref uint leftChar,
+ bool flush)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
+
+ return InternalGetBytes (
+ chars, charCount,
+ null, -1,
+ fallbackBuffer,
+ out charsProcessed, out bytesProcessed,
+ ref leftChar,
+ flush);
+ }
+
+ internal unsafe static EncoderStatus InternalGetBytesCount (
+ char[] chars, int charIndex, int charCount,
+ EncoderFallbackBuffer fallbackBuffer,
+ out int charsProcessed, out int bytesProcessed,
+ ref uint leftChar,
+ bool flush)
+ {
+ if (chars == null)
+ throw new ArgumentNullException ("chars");
+ if (charIndex < 0 || charIndex >= chars.Length)
+ throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_Array"));
+ if (charCount < 0 || charCount > (chars.Length - charIndex))
+ throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_Array"));
+
+ unsafe {
+ fixed (char *cptr = chars) {
+ return InternalGetBytes (
+ cptr + charIndex, charCount,
+ null, -1,
+ fallbackBuffer,
+ out charsProcessed, out bytesProcessed,
+ ref leftChar,
+ flush);
+ }
+ }
+ }
+
#region GetByteCount()
// Get the number of bytes needed to encode a character buffer.
{
uint leftChar = 0;
int charsProcessed, bytesProcessed;
- InternalGetBytes (chars, index, count,
- null, 0,
- EncoderFallback.CreateFallbackBuffer (),
- out charsProcessed, out bytesProcessed,
- ref leftChar,
- true);
+ InternalGetBytesCount (
+ chars, index, count,
+ EncoderFallback.CreateFallbackBuffer (),
+ out charsProcessed, out bytesProcessed,
+ ref leftChar,
+ true);
return bytesProcessed;
}
{
int charsProcessed, bytesProcessed;
uint leftChar = 0;
- InternalGetBytes (chars, count,
- null, 0,
- EncoderFallback.CreateFallbackBuffer (),
- out charsProcessed, out bytesProcessed,
- ref leftChar,
- true);
+ InternalGetBytesCount (
+ chars, count,
+ EncoderFallback.CreateFallbackBuffer (),
+ out charsProcessed, out bytesProcessed,
+ ref leftChar,
+ true);
return bytesProcessed;
}
{
int charsProcessed, bytesProcessed;
uint leftChar = 0;
- EncoderStatus status;
- if (bytes == null)
- throw new ArgumentNullException ("bytes");
- status = InternalGetBytes (
+ if (InternalGetBytesEncode (
chars, charIndex, charCount,
bytes, byteIndex,
EncoderFallback.CreateFallbackBuffer (),
out charsProcessed, out bytesProcessed,
ref leftChar,
- true);
- if (status == EncoderStatus.InsufficientSpace)
+ true) == EncoderStatus.InsufficientSpace)
throw new ArgumentException ("Insufficient Space", "bytes");
return bytesProcessed;
}
EncoderStatus status;
if (s == null)
throw new ArgumentNullException ("s");
- if (bytes == null)
- throw new ArgumentNullException ("bytes");
if (charIndex < 0 || charIndex >= s.Length)
throw new ArgumentOutOfRangeException ("charIndex", _("ArgRange_StringIndex"));
if (charCount < 0 || charCount > (s.Length - charIndex))
throw new ArgumentOutOfRangeException ("charCount", _("ArgRange_StringRange"));
- if (byteIndex < 0 || byteIndex > (bytes.Length > 0 ? bytes.Length - 1 : 0))
+ if (byteIndex < 0 || byteIndex > bytes.Length)
throw new ArgumentOutOfRangeException ("byteIndex", _("ArgRange_Array"));
unsafe {
fixed (char *cptr = s) {
fixed (byte *bptr = bytes) {
- status = InternalGetBytes (
+ status = InternalGetBytesEncode (
cptr + charIndex, charCount,
bptr + byteIndex, bytes.Length - byteIndex,
EncoderFallback.CreateFallbackBuffer (),
{
int charsProcessed, bytesProcessed;
uint leftChar = 0;
- EncoderStatus status;
- if (bytes == null)
- throw new ArgumentNullException ("bytes");
- if (byteCount < 0)
- throw new IndexOutOfRangeException ("charCount");
- status = InternalGetBytes (
+ if (InternalGetBytesEncode (
chars, charCount, bytes, byteCount,
EncoderFallback.CreateFallbackBuffer (),
out charsProcessed, out bytesProcessed,
ref leftChar,
- true);
- if (status == EncoderStatus.InsufficientSpace)
+ true) == EncoderStatus.InsufficientSpace)
throw new ArgumentException ("Insufficient Space", "bytes");
return bytesProcessed;
}
preambleSize = 3;
emittedIdentifier = true;
}
- InternalGetBytes (chars, count,
- null, 0,
- this.FallbackBuffer,
- out charsProcessed, out bytesProcessed,
- ref leftChar,
- flush);
+ InternalGetBytesCount (
+ chars, count,
+ this.FallbackBuffer,
+ out charsProcessed, out bytesProcessed,
+ ref leftChar,
+ flush);
return bytesProcessed + preambleSize;
}
preambleSize = 3;
emittedIdentifier = true;
}
- InternalGetBytes (chars, index, count,
- null, 0,
- this.FallbackBuffer,
- out charsProcessed, out bytesProcessed,
- ref leftChar,
- flush);
+ InternalGetBytesCount (
+ chars, index, count,
+ this.FallbackBuffer,
+ out charsProcessed, out bytesProcessed,
+ ref leftChar,
+ flush);
return bytesProcessed + preambleSize;
}
byte* bytes, int byteCount, bool flush)
{
int charsProcessed, bytesProcessed, preambleSize = 0;
- EncoderStatus status;
if (emitIdentifier && !emittedIdentifier) {
if (byteCount < 3)
throw new ArgumentException ("Insufficient Space", "UTF8 preamble");
emittedIdentifier = true;
byteCount -= 3;
}
- status = InternalGetBytes (chars, charCount,
- bytes, byteCount,
- this.FallbackBuffer,
- out charsProcessed, out bytesProcessed,
- ref leftChar,
- flush);
- if (status == EncoderStatus.InsufficientSpace)
+ if (InternalGetBytesEncode (
+ chars, charCount,
+ bytes, byteCount,
+ this.FallbackBuffer,
+ out charsProcessed, out bytesProcessed,
+ ref leftChar,
+ flush) == EncoderStatus.InsufficientSpace)
throw new ArgumentException ("Insufficient Space", "bytes");
return bytesProcessed + preambleSize;
}
int byteIndex, bool flush)
{
int charsProcessed, bytesProcessed, preambleSize = 0;
- EncoderStatus status;
if (emitIdentifier && !emittedIdentifier) {
if (bytes.Length - byteIndex < 3)
throw new ArgumentException ("Insufficient Space", "UTF8 preamble");
preambleSize = 3;
emittedIdentifier = true;
}
- status = InternalGetBytes (
+ if (InternalGetBytesEncode (
chars, charIndex, charCount,
bytes, byteIndex,
this.FallbackBuffer,
out charsProcessed, out bytesProcessed,
ref leftChar,
- flush);
- if (status == EncoderStatus.InsufficientSpace)
+ flush) == EncoderStatus.InsufficientSpace)
throw new ArgumentException ("Insufficient Space", "bytes");
return bytesProcessed + preambleSize;
}
byteCount -= 3;
}
}
- InternalGetBytes (
+ InternalGetBytesEncode (
chars, charCount,
bytes, byteCount,
this.FallbackBuffer,