/// <summary>
        /// Saves the processed markup to a string.
        /// </summary>
        /// <returns>A string containing the processed markup.</returns>
        public string Save()
        {
            if (!cleaned)
                throw new InvalidOperationException("CleanAndRepair() must be called before Save().");

            var tempEnc = this.CharacterEncoding;
            var tempBOM = this.OutputByteOrderMark;
            this.OutputCharacterEncoding = EncodingType.Utf8;
            this.OutputByteOrderMark = AutoBool.No;

            uint bufferLength = 1;
            byte[] htmlBytes;
            GCHandle handle = new GCHandle();
            do
            {
                // Buffer was too small - bufferLength should now be the required length, so try again...
                if (handle.IsAllocated) handle.Free();

                // this setting appears to be reset by libtidy after calling tidySaveString; we need to set it each time
                this.OutputCharacterEncoding = EncodingType.Utf8;

                htmlBytes = new byte[bufferLength];
                handle = GCHandle.Alloc(htmlBytes, GCHandleType.Pinned);
            } while (PInvoke.tidySaveString(this.handle, handle.AddrOfPinnedObject(), ref bufferLength) == -12);

            handle.Free();

            this.OutputCharacterEncoding = tempEnc;
            this.OutputByteOrderMark = tempBOM;
            return Encoding.UTF8.GetString(htmlBytes);
        }