public ByteString From(short value, ByteStringType type = ByteStringType.Mutable) { var result = AllocateInternal(sizeof(short), type); ((short *)result._pointer->Ptr)[0] = value; RegisterForValidation(result); return(result); }
public ByteString From(byte value, ByteStringType type = ByteStringType.Mutable) { var result = AllocateInternal(1, type); result._pointer->Ptr[0] = value; RegisterForValidation(result); return(result); }
public ByteStringContext.InternalScope ToSlice(ByteStringContext context, ByteStringType type, out Slice str) { var buffer = ToBuffer(); ByteString byteString; var scope = context.From(buffer, 0, buffer.Length, type, out byteString); str = new Slice(byteString); return(scope); }
public void SetUserDefinedFlags(ByteStringType flags) { if ((flags & ByteStringType.ByteStringMask) != 0) { throw new ArgumentException("The flags passed contains reserved bits."); } _pointer->Flags |= flags; }
public ByteString FromPtr(byte *valuePtr, int size, ByteStringType type = ByteStringType.Mutable | ByteStringType.External) { Debug.Assert(valuePtr != null, $"{nameof(valuePtr)} cant be null."); Debug.Assert(size >= 0, $"{nameof(size)} cannot be negative."); var result = AllocateExternal(valuePtr, size, type | ByteStringType.External); // We are allocating external, so we will force it (even if we are checking for it in debug). RegisterForValidation(result); return(result); }
private ByteString AllocateWholeSegment(int length, ByteStringType type) { // The allocation is big, therefore we will just allocate the segment and move on. var segment = AllocateSegment(length + sizeof(ByteStringStorage)); var byteString = Create(segment.Current, length, segment.Size, type); segment.Current += byteString._pointer->Size; _wholeSegments.Add(segment); return(byteString); }
public ByteString From(byte *valuePtr, int size, ByteStringType type = ByteStringType.Mutable) { Debug.Assert(valuePtr != null, $"{nameof(valuePtr)} cant be null."); Debug.Assert((type & ByteStringType.External) == 0, $"{nameof(From)} is not expected to be called with the '{nameof(ByteStringType.External)}' requested type, use {nameof(FromPtr)} instead."); var result = AllocateInternal(size, type); Memory.Copy(result._pointer->Ptr, valuePtr, size); RegisterForValidation(result); return(result); }
public static Slice ToSlice(this string str, ByteStringContext context, ByteStringType type = ByteStringType.Mutable) { var size = Encoding.UTF8.GetByteCount(str); Debug.Assert(size <= ushort.MaxValue); var sliceWriter = new SliceWriter(size); sliceWriter.Write(str); return(sliceWriter.CreateSlice(context, type)); }
public ByteString Clone(ByteString value, ByteStringType type = ByteStringType.Mutable) { Debug.Assert(value._pointer != null, $"{nameof(value)} cant be null."); // TODO: If origin and destination are immutable, we can create external references. var result = AllocateInternal(value.Length, type); Memory.CopyInline(result._pointer->Ptr, value._pointer->Ptr, value._pointer->Length); RegisterForValidation(result); return(result); }
public ByteString From(byte[] value, int size, ByteStringType type = ByteStringType.Mutable) { Debug.Assert(value != null, $"{nameof(value)} cant be null."); var result = AllocateInternal(size, type); fixed(byte *ptr = value) { Memory.Copy(result._pointer->Ptr, ptr, size); } RegisterForValidation(result); return(result); }
public Slice GetNodeKey(LowLevelTransaction tx, int nodeNumber, ByteStringType type = ByteStringType.Mutable | ByteStringType.External) { var node = GetNode(nodeNumber); // This will ensure that we can create a copy or just use the pointer instead. if ((type & ByteStringType.External) == 0) { return(TreeNodeHeader.ToSlice(tx.Allocator, node, type)); } else { return(TreeNodeHeader.ToSlicePtr(tx.Allocator, node, type)); } }
private ByteString Create(void *ptr, int length, int size, ByteStringType type = ByteStringType.Immutable) { Debug.Assert(length <= size - sizeof(ByteStringStorage)); var basePtr = (ByteStringStorage *)ptr; basePtr->Flags = type; basePtr->Length = length; basePtr->Ptr = (byte *)ptr + sizeof(ByteStringStorage); basePtr->Size = size; // We are registering the storage for validation here. Not the ByteString itself RegisterForValidation(basePtr); return(new ByteString(basePtr)); }
public ByteString From(string value, Encoding encoding, ByteStringType type = ByteStringType.Mutable) { Debug.Assert(value != null, $"{nameof(value)} cant be null."); int maxSize = 4 * value.Length; // Important if not working with Unicode. // http://stackoverflow.com/questions/9533258/what-is-the-maximum-number-of-bytes-for-a-utf-8-encoded-character var result = AllocateInternal(maxSize, type); fixed(char *ptr = value) { int length = encoding.GetBytes(ptr, value.Length, result.Ptr, maxSize); // We can do this because it is internal. See if it makes sense to actually give this ability. result._pointer->Length = length; } RegisterForValidation(result); return(result); }
private ByteString AllocateExternal(byte *valuePtr, int size, ByteStringType type) { Debug.Assert((type & ByteStringType.External) != 0, "This allocation routine is only for use with external storage byte strings."); int allocationSize = sizeof(ByteStringStorage); ByteStringStorage *storagePtr; if (_externalFastPoolCount > 0) { storagePtr = (ByteStringStorage *)_externalFastPool[--_externalFastPoolCount].ToPointer(); } else if (_externalStringPool.Count != 0) { storagePtr = (ByteStringStorage *)_externalStringPool.Pop().ToPointer(); } else { if (_externalCurrentLeft == 0) { AllocateExternalSegment(_allocationBlockSize); } storagePtr = (ByteStringStorage *)_externalCurrent.Current; _externalCurrent.Current += _externalAlignedSize; _externalCurrentLeft--; } storagePtr->Flags = type; storagePtr->Length = size; storagePtr->Ptr = valuePtr; // We are registering the storage for validation here. Not the ByteString itself RegisterForValidation(storagePtr); return(new ByteString(storagePtr)); }
public ByteString Skip(ByteString value, int bytesToSkip, ByteStringType type = ByteStringType.Mutable) { Debug.Assert(value._pointer != null, "ByteString cant be null."); if (bytesToSkip < 0) { throw new ArgumentException($"'{nameof(bytesToSkip)}' cannot be smaller than 0."); } if (bytesToSkip > value.Length) { throw new ArgumentException($"'{nameof(bytesToSkip)}' cannot be bigger than '{nameof(value)}.Length' 0."); } // TODO: If origin and destination are immutable, we can create external references. int size = value.Length - bytesToSkip; var result = AllocateInternal(size, type); Memory.CopyInline(result._pointer->Ptr, value._pointer->Ptr + bytesToSkip, size); RegisterForValidation(result); return(result); }
public static ByteStringContext.InternalScope From(ByteStringContext context, string value, ByteStringType type, out Slice str) { var scope = context.From(value, type, out ByteString s); str = new Slice(s); return(scope); }
public static ByteStringContext.ExternalScope External(ByteStringContext context, byte *value, int size, ByteStringType type, out Slice slice) { var scope = context.FromPtr(value, size, type | ByteStringType.External, out ByteString str); slice = new Slice(str); return(scope); }
public static ByteStringContext.InternalScope From(ByteStringContext context, byte *value, int size, ByteStringType type, out Slice str) { var scope = context.From(value, size, type, out ByteString byteString); str = new Slice(byteString); return(scope); }
public static ByteStringContext.InternalScope From(ByteStringContext context, byte[] value, int offset, int count, ByteStringType type, out Slice str) { var scope = context.From(value, offset, count, type, out ByteString byteString); str = new Slice(byteString); return(scope); }
public static ByteStringContext.InternalScope From(ByteStringContext context, byte[] value, ByteStringType type, out Slice str) { var scope = context.From(value, 0, value.Length, type, out ByteString byteString); str = new Slice(byteString); return(scope); }
public static ByteStringContext.InternalScope ToSlice(ByteStringContext context, TreeNodeHeader *node, ByteStringType type, out Slice str) { ByteString byteString; var scope = context.From((byte *)node + Constants.Tree.NodeHeaderSize, node->KeySize, type | (ByteStringType)SliceOptions.Key, out byteString); str = new Slice(byteString); return(scope); }
public Slice CreateSlice(ByteStringContext context, int size, ByteStringType type = ByteStringType.Mutable) { var content = context.From(_buffer, size, type); return(new Slice(content)); }
private ByteString AllocateInternal(int length, ByteStringType type) { Debug.Assert((type & ByteStringType.External) == 0, "This allocation routine is only for use with internal storage byte strings."); type &= ~ByteStringType.External; // We are allocating internal, so we will force it (even if we are checking for it in debug). int allocationSize = length + sizeof(ByteStringStorage); // This is even bigger than the configured allocation block size. There is no reason why we shouldn't // allocate it directly. When released (if released) this will be reused as a segment, ensuring that the context // could handle that. if (allocationSize > _allocationBlockSize) { return(AllocateWholeSegment(length, type)); // We will pass the length because this is a whole allocated segment able to hold a length size ByteString. } int reusablePoolIndex = GetPoolIndexForReuse(allocationSize); int allocationUnit = Bits.NextPowerOf2(allocationSize); // The allocation unit is bigger than MinBlockSize (therefore it wont be 2^n aligned). // Then we will 64bits align the allocation. if (allocationUnit > MinBlockSizeInBytes) { allocationUnit += sizeof(long) - allocationUnit % sizeof(long); } // All allocation units are 32 bits aligned. If not we will have a performance issue. Debug.Assert(allocationUnit % sizeof(int) == 0); // If we can reuse... we retrieve those. if (allocationSize <= MinBlockSizeInBytes && _internalReusableStringPoolCount[reusablePoolIndex] != 0) { // This is a stack because hotter memory will be on top. Stack <IntPtr> pool = _internalReusableStringPool[reusablePoolIndex]; _internalReusableStringPoolCount[reusablePoolIndex]--; void *ptr = pool.Pop().ToPointer(); return(Create(ptr, length, allocationUnit, type)); } else { int currentSizeLeft = _internalCurrent.SizeLeft; if (allocationUnit > currentSizeLeft) // This shouldn't happen that much, if it does you should increase your default allocation block. { SegmentInformation segment = null; // We will try to find a hot segment with enough space if available. // Older (colder) segments are at the front of the list. That's why we would start scanning backwards. for (int i = _internalReadyToUseMemorySegments.Count - 1; i >= 0; i--) { var segmentValue = _internalReadyToUseMemorySegments[i]; if (segmentValue.SizeLeft >= allocationUnit) { // Put the last where this one is (if it is the same, this is a no-op) and remove it from the list. _internalReadyToUseMemorySegments[i] = _internalReadyToUseMemorySegments[_internalReadyToUseMemorySegments.Count - 1]; _internalReadyToUseMemorySegments.RemoveAt(_internalReadyToUseMemorySegments.Count - 1); segment = segmentValue; break; } } // If the size left is bigger than MinBlockSize, we release current as a reusable segment if (currentSizeLeft > MinBlockSizeInBytes) { byte *start = _internalCurrent.Current; byte *end = start + currentSizeLeft; _internalReadyToUseMemorySegments.Add(new SegmentInformation { Start = start, Current = start, End = end, CanDispose = false }); } else if (currentSizeLeft > sizeof(ByteStringType) + MinReusableBlockSizeInBytes) { // The memory chunk left is big enough to make sense to reuse it. reusablePoolIndex = GetPoolIndexForReservation(currentSizeLeft); Stack <IntPtr> pool = this._internalReusableStringPool[reusablePoolIndex]; if (pool == null) { pool = new Stack <IntPtr>(); this._internalReusableStringPool[reusablePoolIndex] = pool; } pool.Push(new IntPtr(_internalCurrent.Current)); this._internalReusableStringPoolCount[reusablePoolIndex]++; } // Use the segment and if there is no segment available that matches the request, just get a new one. this._internalCurrent = segment ?? AllocateSegment(_allocationBlockSize); } var byteString = Create(_internalCurrent.Current, length, allocationUnit, type); _internalCurrent.Current += byteString._pointer->Size; return(byteString); } }
public Slice ToSlice(ByteStringContext context, ByteStringType type = ByteStringType.Mutable) { return(new Slice(context.From(ToBuffer(), type))); }
public Slice Clone(ByteStringContext context, ByteStringType type = ByteStringType.Mutable) { return(new Slice(context.Clone(this.Content, type))); }
public static Slice From(ByteStringContext context, byte *value, int size, ByteStringType type = ByteStringType.Mutable) { return(new Slice(context.From(value, size, type))); }
public static Slice External(ByteStringContext context, byte *value, int size, ByteStringType type = ByteStringType.Mutable | ByteStringType.External) { return(new Slice(context.FromPtr(value, size, type | ByteStringType.External))); }
public static ByteStringContext.ExternalScope ToSlicePtr(ByteStringContext context, TreeNodeHeader *node, ByteStringType type, out Slice slice) { ByteString str; var scope = context.FromPtr((byte *)node + Constants.Tree.NodeHeaderSize, node->KeySize, type, out str); slice = new Slice(str); return(scope); }
public Slice Skip(ByteStringContext context, int bytesToSkip, ByteStringType type = ByteStringType.Mutable) { return(new Slice(context.Skip(this.Content, bytesToSkip, type))); }
public static Slice ToSliceUsingBuffer(this string str, ByteStringContext context, byte[] buffer, ByteStringType type = ByteStringType.Mutable) { var sliceWriter = new SliceWriter(buffer); sliceWriter.Write(str); return(sliceWriter.CreateSlice(context, type)); }