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;
73static inline SimpleTextStoreMarkerHook* OurStuff (
const Marker* marker)
76 AssertNotNull ((SimpleTextStoreMarkerHook*)marker->fTextStoreHook);
77 AssertMember ((SimpleTextStoreMarkerHook*)marker->fTextStoreHook, SimpleTextStoreMarkerHook);
78 return (SimpleTextStoreMarkerHook*)marker->fTextStoreHook;
86SimpleTextStore::SimpleTextStore ()
92 fBuffer =
new Led_tChar[0];
96SimpleTextStore::~SimpleTextStore ()
98 Require (GetMarkerOwners ().size () == 1);
104 Require (fMarkers.size () == 0);
112TextStore* SimpleTextStore::ConstructNewTextStore ()
const
114 return new SimpleTextStore ();
117void SimpleTextStore::CopyOut (
size_t from,
size_t count, Led_tChar* buffer)
const noexcept
123 Require (from + count <= GetEnd ());
124 (void)::memcpy (buffer, &fBuffer[from], count *
sizeof (Led_tChar));
127void SimpleTextStore::ReplaceWithoutUpdate (
size_t from,
size_t to,
const Led_tChar* withWhat,
size_t withWhatCount)
140 DeleteAfter_ (to - from, from);
141 InsertAfter_ (withWhat, withWhatCount, from);
145void SimpleTextStore::InsertAfter_ (
const Led_tChar* what,
size_t howMany,
size_t after)
148 size_t newBufSize = howMany + fLength;
149 Led_tChar* newBuf =
new Led_tChar[newBufSize];
151 (void)::memcpy (newBuf, fBuffer, after *
sizeof (Led_tChar));
154 (void)::memcpy (newBuf + after, what, howMany *
sizeof (Led_tChar));
156 (void)::memcpy (newBuf + after + howMany, &fBuffer[after], (fLength - after) *
sizeof (Led_tChar));
159 fLength = newBufSize;
164 for (
size_t i = 0; i < fMarkers.size (); ++i) {
165 Marker* mi = fMarkers[i];
166 size_t start = mi->GetStart ();
167 size_t len = mi->GetLength ();
168 size_t end = start + len;
170 OurStuff (mi)->fStart = start + howMany;
172 else if (after >= start and after < end) {
173 OurStuff (mi)->fLength = len + howMany;
179void SimpleTextStore::DeleteAfter_ (
size_t howMany,
size_t after)
182 Assert (howMany + after <= fLength);
185 Assert (fLength >= howMany);
186 size_t howManyToMove = fLength - (after + howMany);
187 Assert (howManyToMove <= fLength);
188 Assert (howManyToMove + after <= fLength);
189 (void)::memmove (&fBuffer[after], &fBuffer[after + howMany], howManyToMove *
sizeof (Led_tChar));
193 for (
size_t i = 0; i < fMarkers.size (); ++i) {
194 Marker* mi = fMarkers[i];
195 size_t start = mi->GetStart ();
196 size_t len = mi->GetLength ();
197 size_t end = start + len;
199 if (howMany + after <= start) {
200 Assert (start >= howMany);
201 OurStuff (mi)->fStart = start - howMany;
204 Assert (howMany > (start - after));
205 size_t deleteNCharsOffFront = howMany - (start - after);
206 size_t moveFront = howMany - deleteNCharsOffFront;
207 OurStuff (mi)->fStart = start - moveFront;
211 OurStuff (mi)->fLength = (len > deleteNCharsOffFront) ? (len - deleteNCharsOffFront) : 0;
214 else if (after >= start and after < end) {
216 if (end - after < howMany) {
222 Assert (newEnd >= start);
223 size_t newLen = newEnd - start;
224 OurStuff (mi)->fLength = newLen;
230void SimpleTextStore::AddMarker (Marker* marker,
size_t lhs,
size_t length,
MarkerOwner* owner)
234 Require (owner->PeekAtTextStore () ==
this);
235 Require (owner ==
this or IndexOf (GetMarkerOwners (), owner) != kBadIndex);
236 Require (IndexOf (fMarkers, marker) == kBadIndex);
237 Require (lhs < 0x80000000);
238 Require (length < 0x80000000);
240 Assert (marker->fTextStoreHook ==
nullptr);
241 marker->fTextStoreHook =
new SimpleTextStoreMarkerHook ();
242 Assert (marker->GetOwner () ==
nullptr);
243 OurStuff (marker)->fOwner = owner;
244 OurStuff (marker)->fStart = lhs;
245 OurStuff (marker)->fLength = length;
251 for (
size_t i = 0; i < fMarkers.size (); ++i) {
252 Marker* mi = fMarkers[i];
253 if (mi->GetStart () > lhs) {
256 fMarkers.insert (fMarkers.begin () + i, marker);
263 PUSH_BACK (fMarkers, marker);
267void SimpleTextStore::RemoveMarkers (Marker*
const markerArray[],
size_t markerCount)
269 Assert (markerCount == 0 or markerArray !=
nullptr);
270 for (
size_t i = 0; i < markerCount; ++i) {
271 Marker* marker = markerArray[i];
272 if (marker->fTextStoreHook !=
nullptr) {
275 vector<Marker*>::iterator index = find (fMarkers.begin (), fMarkers.end (), marker);
276 Assert (index != fMarkers.end ());
277 fMarkers.erase (index);
278 OurStuff (marker)->fOwner =
nullptr;
280 delete marker->fTextStoreHook;
281 marker->fTextStoreHook =
nullptr;
286void SimpleTextStore::PreRemoveMarker (Marker* marker)
289 Require (not OurStuff (marker)->fIsPreRemoved);
290 OurStuff (marker)->fIsPreRemoved =
true;
293void SimpleTextStore::SetMarkerRange (Marker* marker,
size_t start,
size_t end)
noexcept
297 Assert (start <= end);
301 if (marker->GetStart () == start) {
302 OurStuff (marker)->fLength = end - start;
307 RemoveMarker (marker);
308 AddMarker (marker, start, end - start, owner);
312void SimpleTextStore::CollectAllMarkersInRangeInto (
size_t from,
size_t to,
const MarkerOwner* owner, MarkerSink& output)
const
315 for (
auto i = fMarkers.begin (); i != fMarkers.end (); ++i) {
318 if (Overlap (*m, from, to)) {
319 if (owner == kAnyMarkerOwner or owner == m->GetOwner ()) {
320 if (not OurStuff (m)->fIsPreRemoved) {
328#if qStroika_Foundation_Debug_AssertionsChecked
329void SimpleTextStore::Invariant_ ()
const
331 TextStore::Invariant_ ();
332 for (
size_t i = 0; i < fMarkers.size (); ++i) {
333 Marker* mi = fMarkers[i];
335 Assert (IndexOf (fMarkers, mi) == i);
337 size_t start = mi->GetStart ();
338 size_t len = mi->GetLength ();
339 size_t end = start + len;
341 Assert (start <= end);
342 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.