/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using Lucene.Net.Support; using UnicodeUtil = Lucene.Net.Util.UnicodeUtil; namespace Lucene.Net.Store { /// Abstract base class for output to a file in a Directory. A random-access /// output stream. Used for all Lucene index output operations. /// /// /// /// /// public abstract class IndexOutput : IDisposable { /// Writes a single byte. /// /// public abstract void WriteByte(byte b); /// Writes an array of bytes. /// the bytes to write /// /// the number of bytes to write /// /// /// public virtual void WriteBytes(byte[] b, int length) { WriteBytes(b, 0, length); } /// Writes an array of bytes. /// the bytes to write /// /// the offset in the byte array /// /// the number of bytes to write /// /// /// public abstract void WriteBytes(byte[] b, int offset, int length); /// Writes an int as four bytes. /// /// public virtual void WriteInt(int i) { WriteByte((byte) (i >> 24)); WriteByte((byte) (i >> 16)); WriteByte((byte) (i >> 8)); WriteByte((byte) i); } /// Writes an int in a variable-length format. Writes between one and /// five bytes. Smaller values take fewer bytes. Negative numbers are not /// supported. /// /// /// public virtual void WriteVInt(int i) { while ((i & ~ 0x7F) != 0) { WriteByte((byte) ((i & 0x7f) | 0x80)); i = Number.URShift(i, 7); } WriteByte((byte) i); } /// Writes a long as eight bytes. /// /// public virtual void WriteLong(long i) { WriteInt((int) (i >> 32)); WriteInt((int) i); } /// Writes an long in a variable-length format. Writes between one and five /// bytes. Smaller values take fewer bytes. Negative numbers are not /// supported. /// /// /// public virtual void WriteVLong(long i) { while ((i & ~ 0x7F) != 0) { WriteByte((byte) ((i & 0x7f) | 0x80)); i = Number.URShift(i, 7); } WriteByte((byte) i); } /// Writes a string. /// /// public virtual void WriteString(System.String s) { UnicodeUtil.UTF8Result utf8Result = new UnicodeUtil.UTF8Result(); UnicodeUtil.UTF16toUTF8(s, 0, s.Length, utf8Result); WriteVInt(utf8Result.length); WriteBytes(utf8Result.result, 0, utf8Result.length); } /// Writes a sub sequence of characters from s as the old /// format (modified UTF-8 encoded bytes). /// /// the source of the characters /// /// the first character in the sequence /// /// the number of characters in the sequence /// /// -- please pre-convert to utf8 bytes /// instead or use /// [Obsolete("-- please pre-convert to utf8 bytes instead or use WriteString")] public virtual void WriteChars(System.String s, int start, int length) { int end = start + length; for (int i = start; i < end; i++) { int code = (int) s[i]; if (code >= 0x01 && code <= 0x7F) WriteByte((byte) code); else if (((code >= 0x80) && (code <= 0x7FF)) || code == 0) { WriteByte((byte) (0xC0 | (code >> 6))); WriteByte((byte) (0x80 | (code & 0x3F))); } else { WriteByte((byte) (0xE0 | (Number.URShift(code, 12)))); WriteByte((byte) (0x80 | ((code >> 6) & 0x3F))); WriteByte((byte) (0x80 | (code & 0x3F))); } } } /// Writes a sub sequence of characters from char[] as /// the old format (modified UTF-8 encoded bytes). /// /// the source of the characters /// /// the first character in the sequence /// /// the number of characters in the sequence /// /// -- please pre-convert to utf8 bytes instead or use /// [Obsolete("-- please pre-convert to utf8 bytes instead or use WriteString")] public virtual void WriteChars(char[] s, int start, int length) { int end = start + length; for (int i = start; i < end; i++) { int code = (int) s[i]; if (code >= 0x01 && code <= 0x7F) WriteByte((byte) code); else if (((code >= 0x80) && (code <= 0x7FF)) || code == 0) { WriteByte((byte) (0xC0 | (code >> 6))); WriteByte((byte) (0x80 | (code & 0x3F))); } else { WriteByte((byte) (0xE0 | (Number.URShift(code, 12)))); WriteByte((byte) (0x80 | ((code >> 6) & 0x3F))); WriteByte((byte) (0x80 | (code & 0x3F))); } } } private static int COPY_BUFFER_SIZE = 16384; private byte[] copyBuffer; /// Copy numBytes bytes from input to ourself. public virtual void CopyBytes(IndexInput input, long numBytes) { System.Diagnostics.Debug.Assert(numBytes >= 0, "numBytes=" + numBytes); long left = numBytes; if (copyBuffer == null) copyBuffer = new byte[COPY_BUFFER_SIZE]; while (left > 0) { int toCopy; if (left > COPY_BUFFER_SIZE) toCopy = COPY_BUFFER_SIZE; else toCopy = (int) left; input.ReadBytes(copyBuffer, 0, toCopy); WriteBytes(copyBuffer, 0, toCopy); left -= toCopy; } } /// Forces any buffered output to be written. public abstract void Flush(); /// Closes this stream to further operations. [Obsolete("Use Dispose() instead.")] public void Close() { Dispose(); } /// Closes this stream to further operations. public void Dispose() { Dispose(true); } protected abstract void Dispose(bool disposing); /// Returns the current position in this file, where the next write will /// occur. /// /// /// public abstract long FilePointer { get; } /// Sets current position in this file, where the next write will occur. /// /// public abstract void Seek(long pos); /// The number of bytes in the file. public abstract long Length { get; } /// Set the file length. By default, this method does /// nothing (it's optional for a Directory to implement /// it). But, certain Directory implementations (for /// /// can use this to inform the /// underlying IO system to pre-allocate the file to the /// specified size. If the length is longer than the /// current file length, the bytes added to the file are /// undefined. Otherwise the file is truncated. /// /// file length /// public virtual void SetLength(long length) { } // map must be Map public virtual void WriteStringStringMap(System.Collections.Generic.IDictionary map) { if (map == null) { WriteInt(0); } else { WriteInt(map.Count); foreach (var entry in map) { WriteString(entry.Key); WriteString(entry.Value); } } } } }