/// <summary> /// Resets the decoder. /// </summary> /// <remarks> /// Resets the state of the decoder. /// </remarks> public void Reset () { state = initial; nsaved = 0; saved = 0; uulen = 0; }
/// <summary> /// Initializes a new instance of the <see cref="MimeKit.Encodings.UUDecoder"/> class. /// </summary> /// <remarks> /// Creates a new Unix-to-Unix decoder. /// </remarks> /// <param name="payloadOnly"> /// If <c>true</c>, decoding begins immediately rather than after finding a begin-line. /// </param> public UUDecoder (bool payloadOnly) { initial = payloadOnly ? UUDecoderState.Payload : UUDecoderState.ExpectBegin; Reset (); }
/// <summary> /// Decodes the specified input into the output buffer. /// </summary> /// <remarks> /// <para>Decodes the specified input into the output buffer.</para> /// <para>The output buffer should be large enough to hold all of the /// decoded input. For estimating the size needed for the output buffer, /// see <see cref="EstimateOutputLength"/>.</para> /// </remarks> /// <returns>The number of bytes written to the output buffer.</returns> /// <param name="input">A pointer to the beginning of the input buffer.</param> /// <param name="length">The length of the input buffer.</param> /// <param name="output">A pointer to the beginning of the output buffer.</param> public unsafe int Decode (byte* input, int length, byte* output) { if (state == UUDecoderState.Ended) return 0; bool last_was_eoln = uulen == 0; byte* inend = input + length; byte* outptr = output; byte* inptr = input; byte c; if (state < UUDecoderState.Payload) { if ((inptr = ScanBeginMarker (inptr, inend)) == inend) return 0; } while (inptr < inend) { if (*inptr == (byte) '\r') { inptr++; continue; } if (*inptr == (byte) '\n') { last_was_eoln = true; inptr++; continue; } if (uulen == 0 || last_was_eoln) { // first octet on a line is the uulen octet uulen = uudecode_rank[*inptr]; last_was_eoln = false; if (uulen == 0) { state = UUDecoderState.Ended; break; } inptr++; continue; } c = *inptr++; if (uulen > 0) { // save the byte saved = (saved << 8) | c; nsaved++; if (nsaved == 4) { byte b0 = (byte) ((saved >> 24) & 0xFF); byte b1 = (byte) ((saved >> 16) & 0xFF); byte b2 = (byte) ((saved >> 8) & 0xFF); byte b3 = (byte) (saved & 0xFF); if (uulen >= 3) { *outptr++ = (byte) (uudecode_rank[b0] << 2 | uudecode_rank[b1] >> 4); *outptr++ = (byte) (uudecode_rank[b1] << 4 | uudecode_rank[b2] >> 2); *outptr++ = (byte) (uudecode_rank[b2] << 6 | uudecode_rank[b3]); uulen -= 3; } else { if (uulen >= 1) { *outptr++ = (byte) (uudecode_rank[b0] << 2 | uudecode_rank[b1] >> 4); uulen--; } if (uulen >= 1) { *outptr++ = (byte) (uudecode_rank[b1] << 4 | uudecode_rank[b2] >> 2); uulen--; } } nsaved = 0; saved = 0; } } else { break; } } return (int) (outptr - output); }
unsafe byte* ScanBeginMarker (byte* inptr, byte* inend) { while (inptr < inend) { if (state == UUDecoderState.ExpectBegin) { if (nsaved != 0 && nsaved != (byte) '\n') { while (inptr < inend && *inptr != (byte) '\n') inptr++; if (inptr == inend) { nsaved = *(inptr - 1); return inptr; } nsaved = *inptr++; if (inptr == inend) return inptr; } nsaved = *inptr++; if (nsaved != (byte) 'b') continue; state = UUDecoderState.B; if (inptr == inend) return inptr; } if (state == UUDecoderState.B) { nsaved = *inptr++; if (nsaved != (byte) 'e') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.Be; if (inptr == inend) return inptr; } if (state == UUDecoderState.Be) { nsaved = *inptr++; if (nsaved != (byte) 'g') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.Beg; if (inptr == inend) return inptr; } if (state == UUDecoderState.Beg) { nsaved = *inptr++; if (nsaved != (byte) 'i') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.Begi; if (inptr == inend) return inptr; } if (state == UUDecoderState.Begi) { nsaved = *inptr++; if (nsaved != (byte) 'n') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.Begin; if (inptr == inend) return inptr; } if (state == UUDecoderState.Begin) { nsaved = *inptr++; if (nsaved != (byte) ' ') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.ExpectPayload; if (inptr == inend) return inptr; } if (state == UUDecoderState.ExpectPayload) { while (inptr < inend && *inptr != (byte) '\n') inptr++; if (inptr == inend) return inptr; state = UUDecoderState.Payload; nsaved = 0; return inptr + 1; } } return inptr; }
/// <summary> /// Initializes a new instance of the <see cref="MimeKit.Encodings.UUDecoder"/> class. /// </summary> /// <remarks> /// Creates a new Unix-to-Unix decoder. /// </remarks> /// <param name="payloadOnly"> /// If <c>true</c>, decoding begins immediately rather than after finding a begin-line. /// </param> public UUDecoder(bool payloadOnly) { initial = payloadOnly ? UUDecoderState.Payload : UUDecoderState.ExpectBegin; Reset(); }
/// <summary> /// Decodes the specified input into the output buffer. /// </summary> /// <remarks> /// <para>Decodes the specified input into the output buffer.</para> /// <para>The output buffer should be large enough to hold all of the /// decoded input. For estimating the size needed for the output buffer, /// see <see cref="EstimateOutputLength"/>.</para> /// </remarks> /// <returns>The number of bytes written to the output buffer.</returns> /// <param name="input">A pointer to the beginning of the input buffer.</param> /// <param name="length">The length of the input buffer.</param> /// <param name="output">A pointer to the beginning of the output buffer.</param> public unsafe int Decode(byte *input, int length, byte *output) { if (state == UUDecoderState.Ended) { return(0); } bool last_was_eoln = uulen == 0; byte *inend = input + length; byte *outptr = output; byte *inptr = input; byte c; if (state < UUDecoderState.Payload) { if ((inptr = ScanBeginMarker(inptr, inend)) == inend) { return(0); } } while (inptr < inend) { if (*inptr == (byte)'\r') { inptr++; continue; } if (*inptr == (byte)'\n') { last_was_eoln = true; inptr++; continue; } if (uulen == 0 || last_was_eoln) { // first octet on a line is the uulen octet uulen = uudecode_rank[*inptr]; last_was_eoln = false; if (uulen == 0) { state = UUDecoderState.Ended; break; } inptr++; continue; } c = *inptr++; if (uulen > 0) { // save the byte saved = (saved << 8) | c; nsaved++; if (nsaved == 4) { byte b0 = (byte)((saved >> 24) & 0xFF); byte b1 = (byte)((saved >> 16) & 0xFF); byte b2 = (byte)((saved >> 8) & 0xFF); byte b3 = (byte)(saved & 0xFF); if (uulen >= 3) { *outptr++ = (byte)(uudecode_rank[b0] << 2 | uudecode_rank[b1] >> 4); *outptr++ = (byte)(uudecode_rank[b1] << 4 | uudecode_rank[b2] >> 2); *outptr++ = (byte)(uudecode_rank[b2] << 6 | uudecode_rank[b3]); uulen -= 3; } else { if (uulen >= 1) { *outptr++ = (byte)(uudecode_rank[b0] << 2 | uudecode_rank[b1] >> 4); uulen--; } if (uulen >= 1) { *outptr++ = (byte)(uudecode_rank[b1] << 4 | uudecode_rank[b2] >> 2); uulen--; } } nsaved = 0; saved = 0; } } else { break; } } return((int)(outptr - output)); }
unsafe byte *ScanBeginMarker(byte *inptr, byte *inend) { while (inptr < inend) { if (state == UUDecoderState.ExpectBegin) { if (nsaved != 0 && nsaved != (byte)'\n') { while (inptr < inend && *inptr != (byte)'\n') { inptr++; } if (inptr == inend) { nsaved = *(inptr - 1); return(inptr); } nsaved = *inptr++; if (inptr == inend) { return(inptr); } } nsaved = *inptr++; if (nsaved != (byte)'b') { continue; } state = UUDecoderState.B; if (inptr == inend) { return(inptr); } } if (state == UUDecoderState.B) { nsaved = *inptr++; if (nsaved != (byte)'e') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.Be; if (inptr == inend) { return(inptr); } } if (state == UUDecoderState.Be) { nsaved = *inptr++; if (nsaved != (byte)'g') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.Beg; if (inptr == inend) { return(inptr); } } if (state == UUDecoderState.Beg) { nsaved = *inptr++; if (nsaved != (byte)'i') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.Begi; if (inptr == inend) { return(inptr); } } if (state == UUDecoderState.Begi) { nsaved = *inptr++; if (nsaved != (byte)'n') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.Begin; if (inptr == inend) { return(inptr); } } if (state == UUDecoderState.Begin) { nsaved = *inptr++; if (nsaved != (byte)' ') { state = UUDecoderState.ExpectBegin; continue; } state = UUDecoderState.ExpectPayload; if (inptr == inend) { return(inptr); } } if (state == UUDecoderState.ExpectPayload) { while (inptr < inend && *inptr != (byte)'\n') { inptr++; } if (inptr == inend) { return(inptr); } state = UUDecoderState.Payload; nsaved = 0; return(inptr + 1); } } return(inptr); }