4#include "Stroika/Frameworks/StroikaPreComp.h"
8#include "SimpleTextStore.h"
11using namespace Stroika::Frameworks;
12using namespace Stroika::Frameworks::Led;
16 SimpleTextStoreMarkerHook ()
21 , fIsPreRemoved (false)
27 virtual size_t GetStart ()
const override;
28 virtual size_t GetEnd ()
const override;
29 virtual size_t GetLength ()
const override;
30 virtual void GetStartEnd (
size_t* start,
size_t* end)
const override;
37MarkerOwner* SimpleTextStoreMarkerHook::GetOwner ()
const
42size_t SimpleTextStoreMarkerHook::GetStart ()
const
44 Assert (fStart < 0x8000000);
50size_t SimpleTextStoreMarkerHook::GetEnd ()
const
52 Assert (fStart < 0x8000000);
53 Assert (fLength < 0x8000000);
54 return fStart + fLength;
57size_t SimpleTextStoreMarkerHook::GetLength ()
const
59 Assert (fLength < 0x8000000);
63void SimpleTextStoreMarkerHook::GetStartEnd (
size_t* start,
size_t* end)
const
65 Assert (fStart < 0x8000000);
66 Assert (fLength < 0x8000000);
70 *end = fStart + fLength;
73#if qStaticInlineFunctionsInDebugModeNoInliningArentTreatedAsStatic
74#define OurStuff SimpleTextStore_OurStuff
76static inline SimpleTextStoreMarkerHook* OurStuff (
const Marker* marker)
79 AssertNotNull ((SimpleTextStoreMarkerHook*)marker->fTextStoreHook);
80 AssertMember ((SimpleTextStoreMarkerHook*)marker->fTextStoreHook, SimpleTextStoreMarkerHook);
81 return (SimpleTextStoreMarkerHook*)marker->fTextStoreHook;
89SimpleTextStore::SimpleTextStore ()
95 fBuffer =
new Led_tChar[0];
99SimpleTextStore::~SimpleTextStore ()
101 Require (GetMarkerOwners ().size () == 1);
107 Require (fMarkers.size () == 0);
115TextStore* SimpleTextStore::ConstructNewTextStore ()
const
117 return new SimpleTextStore ();
120void SimpleTextStore::CopyOut (
size_t from,
size_t count, Led_tChar* buffer)
const noexcept
126 Require (from + count <= GetEnd ());
127 (void)::memcpy (buffer, &fBuffer[from], count *
sizeof (Led_tChar));
130void SimpleTextStore::ReplaceWithoutUpdate (
size_t from,
size_t to,
const Led_tChar* withWhat,
size_t withWhatCount)
143 DeleteAfter_ (to - from, from);
144 InsertAfter_ (withWhat, withWhatCount, from);
148void SimpleTextStore::InsertAfter_ (
const Led_tChar* what,
size_t howMany,
size_t after)
151 size_t newBufSize = howMany + fLength;
152 Led_tChar* newBuf =
new Led_tChar[newBufSize];
154 (void)::memcpy (newBuf, fBuffer, after *
sizeof (Led_tChar));
157 (void)::memcpy (newBuf + after, what, howMany *
sizeof (Led_tChar));
159 (void)::memcpy (newBuf + after + howMany, &fBuffer[after], (fLength - after) *
sizeof (Led_tChar));
162 fLength = newBufSize;
167 for (
size_t i = 0; i < fMarkers.size (); ++i) {
168 Marker* mi = fMarkers[i];
169 size_t start = mi->GetStart ();
170 size_t len = mi->GetLength ();
171 size_t end = start + len;
173 OurStuff (mi)->fStart = start + howMany;
175 else if (after >= start and after < end) {
176 OurStuff (mi)->fLength = len + howMany;
182void SimpleTextStore::DeleteAfter_ (
size_t howMany,
size_t after)
185 Assert (howMany + after <= fLength);
188 Assert (fLength >= howMany);
189 size_t howManyToMove = fLength - (after + howMany);
190 Assert (howManyToMove <= fLength);
191 Assert (howManyToMove + after <= fLength);
192 (void)::memmove (&fBuffer[after], &fBuffer[after + howMany], howManyToMove *
sizeof (Led_tChar));
196 for (
size_t i = 0; i < fMarkers.size (); ++i) {
197 Marker* mi = fMarkers[i];
198 size_t start = mi->GetStart ();
199 size_t len = mi->GetLength ();
200 size_t end = start + len;
202 if (howMany + after <= start) {
203 Assert (start >= howMany);
204 OurStuff (mi)->fStart = start - howMany;
207 Assert (howMany > (start - after));
208 size_t deleteNCharsOffFront = howMany - (start - after);
209 size_t moveFront = howMany - deleteNCharsOffFront;
210 OurStuff (mi)->fStart = start - moveFront;
214 OurStuff (mi)->fLength = (len > deleteNCharsOffFront) ? (len - deleteNCharsOffFront) : 0;
217 else if (after >= start and after < end) {
219 if (end - after < howMany) {
225 Assert (newEnd >= start);
226 size_t newLen = newEnd - start;
227 OurStuff (mi)->fLength = newLen;
233void SimpleTextStore::AddMarker (Marker* marker,
size_t lhs,
size_t length,
MarkerOwner* owner)
237#if !qVirtualBaseMixinCallDuringCTORBug
238 Require (owner->PeekAtTextStore () ==
this);
240 Require (owner ==
this or IndexOf (GetMarkerOwners (), owner) != kBadIndex);
241 Require (IndexOf (fMarkers, marker) == kBadIndex);
242 Require (lhs < 0x80000000);
243 Require (length < 0x80000000);
245 Assert (marker->fTextStoreHook ==
nullptr);
246 marker->fTextStoreHook =
new SimpleTextStoreMarkerHook ();
247 Assert (marker->GetOwner () ==
nullptr);
248 OurStuff (marker)->fOwner = owner;
249 OurStuff (marker)->fStart = lhs;
250 OurStuff (marker)->fLength = length;
256 for (
size_t i = 0; i < fMarkers.size (); ++i) {
257 Marker* mi = fMarkers[i];
258 if (mi->GetStart () > lhs) {
261 fMarkers.insert (fMarkers.begin () + i, marker);
268 PUSH_BACK (fMarkers, marker);
272void SimpleTextStore::RemoveMarkers (Marker*
const markerArray[],
size_t markerCount)
274 Assert (markerCount == 0 or markerArray !=
nullptr);
275 for (
size_t i = 0; i < markerCount; ++i) {
276 Marker* marker = markerArray[i];
277 if (marker->fTextStoreHook !=
nullptr) {
280 vector<Marker*>::iterator index = find (fMarkers.begin (), fMarkers.end (), marker);
281 Assert (index != fMarkers.end ());
282 fMarkers.erase (index);
283 OurStuff (marker)->fOwner =
nullptr;
285 delete marker->fTextStoreHook;
286 marker->fTextStoreHook =
nullptr;
291void SimpleTextStore::PreRemoveMarker (Marker* marker)
294 Require (not OurStuff (marker)->fIsPreRemoved);
295 OurStuff (marker)->fIsPreRemoved =
true;
298void SimpleTextStore::SetMarkerRange (Marker* marker,
size_t start,
size_t end)
noexcept
302 Assert (start <= end);
306 if (marker->GetStart () == start) {
307 OurStuff (marker)->fLength = end - start;
312 RemoveMarker (marker);
313 AddMarker (marker, start, end - start, owner);
317void SimpleTextStore::CollectAllMarkersInRangeInto (
size_t from,
size_t to,
const MarkerOwner* owner, MarkerSink& output)
const
320 for (
auto i = fMarkers.begin (); i != fMarkers.end (); ++i) {
323 if (Overlap (*m, from, to)) {
324 if (owner == kAnyMarkerOwner or owner == m->GetOwner ()) {
325 if (not OurStuff (m)->fIsPreRemoved) {
333#if qStroika_Foundation_Debug_AssertionsChecked
334void SimpleTextStore::Invariant_ ()
const
336 TextStore::Invariant_ ();
337 for (
size_t i = 0; i < fMarkers.size (); ++i) {
338 Marker* mi = fMarkers[i];
340 Assert (IndexOf (fMarkers, mi) == i);
342 size_t start = mi->GetStart ();
343 size_t len = mi->GetLength ();
344 size_t end = start + len;
346 Assert (start <= end);
347 Assert (end <= GetEnd () + 1);
#define RequireNotNull(p)
#define AssertMember(p, c)
conditional_t< qStroika_Foundation_Memory_PreferBlockAllocation and andTrueCheck, BlockAllocationUseHelper< T >, Common::Empty > UseBlockAllocationIfAppropriate
Use this to enable block allocation for a particular class. Beware of subclassing.