1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4// ---------------------------------------------------------------------------
5
6//
7// Buffer.cpp
8// ---------------------------------------------------------------------------
9
10#include "stdafx.h"
11#include "sbuffer.h"
12#include "ex.h"
13#include "holder.h"
14#include "stdmacros.h"
15
16// Try to minimize the performance impact of contracts on CHK build.
17#if defined(_MSC_VER)
18#pragma inline_depth (20)
19#endif
20
21const DWORD g_garbageFillBuffer[GARBAGE_FILL_BUFFER_ITEMS] =
22{
23 GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD,
24 GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD,
25 GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD,
26 GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD, GARBAGE_FILL_DWORD,
27};
28
29//----------------------------------------------------------------------------
30// ReallocateBuffer
31// Low level buffer reallocate routine
32//----------------------------------------------------------------------------
33void SBuffer::ReallocateBuffer(COUNT_T allocation, Preserve preserve)
34{
35 CONTRACT_VOID
36 {
37 PRECONDITION(CheckPointer(this));
38 PRECONDITION(CheckBufferClosed());
39 PRECONDITION(CheckAllocation(allocation));
40 PRECONDITION(allocation >= m_size);
41 POSTCONDITION(m_allocation == allocation);
42 if (allocation > 0) THROWS; else NOTHROW;
43 GC_NOTRIGGER;
44 SUPPORTS_DAC_HOST_ONLY;
45 }
46 CONTRACT_END;
47
48 BYTE *newBuffer = NULL;
49 if (allocation > 0)
50 {
51 newBuffer = NewBuffer(allocation);
52
53 if (preserve == PRESERVE)
54 {
55 // Copy the relevant contents of the old buffer over
56 DebugMoveBuffer(newBuffer, m_buffer, m_size);
57 }
58 }
59
60 if (IsAllocated())
61 DeleteBuffer(m_buffer, m_allocation);
62
63 m_buffer = newBuffer;
64 m_allocation = allocation;
65
66 if (allocation > 0)
67 SetAllocated();
68 else
69 ClearAllocated();
70
71 ClearImmutable();
72
73 RETURN;
74}
75
76void SBuffer::Replace(const Iterator &i, COUNT_T deleteSize, COUNT_T insertSize)
77{
78 CONTRACT_VOID
79 {
80 THROWS;
81 GC_NOTRIGGER;
82 PRECONDITION(CheckPointer(this));
83 PRECONDITION(CheckIteratorRange(i, deleteSize));
84 SUPPORTS_DAC_HOST_ONLY;
85 }
86 CONTRACT_END;
87
88 COUNT_T startRange = (COUNT_T) (i.m_ptr - m_buffer);
89 // The PRECONDITION(CheckIterationRange(i, deleteSize)) should check this in
90 // contract-checking builds, but this ensures we don't integer overflow if someone
91 // passes in an egregious deleteSize by capping it to the remaining length in the
92 // buffer.
93 if ((COUNT_T)(m_buffer + m_size - i.m_ptr) < deleteSize)
94 {
95 _ASSERTE(!"Trying to replace more bytes than are remaining in the buffer.");
96 deleteSize = (COUNT_T)(m_buffer + m_size - i.m_ptr);
97 }
98 COUNT_T endRange = startRange + deleteSize;
99 COUNT_T end = m_size;
100
101 SCOUNT_T delta = insertSize - deleteSize;
102
103 if (delta < 0)
104 {
105 // Buffer is shrinking
106
107 DebugDestructBuffer(i.m_ptr, deleteSize);
108
109 DebugMoveBuffer(m_buffer + endRange + delta,
110 m_buffer + endRange,
111 end - endRange);
112
113 Resize(m_size+delta, PRESERVE);
114
115 i.Resync(this, m_buffer + startRange);
116
117 }
118 else if (delta > 0)
119 {
120 // Buffer is growing
121
122 ResizePadded(m_size+delta);
123
124 i.Resync(this, m_buffer + startRange);
125
126 DebugDestructBuffer(i.m_ptr, deleteSize);
127
128 DebugMoveBuffer(m_buffer + endRange + delta,
129 m_buffer + endRange,
130 end - endRange);
131
132 }
133 else
134 {
135 // Buffer stays the same size. We need to DebugDestruct it first to keep
136 // the invariant that the new space is clean.
137
138 DebugDestructBuffer(i.m_ptr, insertSize);
139 }
140
141 DebugConstructBuffer(i.m_ptr, insertSize);
142
143 RETURN;
144}
145
146
147