From e333843348e800ae9dddeb8af5d567d172e87185 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Fri, 3 Feb 2006 21:22:00 +0000 Subject: [PATCH] Added Alloc/Copy/FreeRunArray() as Axel's suggestion, and used it internally in TextView. Also fixed small memory leak git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16224 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/interface/TextView.h | 10 +- src/kits/interface/BTextView/TextView.cpp | 116 ++++++++++++++-------- 2 files changed, 78 insertions(+), 48 deletions(-) diff --git a/headers/os/interface/TextView.h b/headers/os/interface/TextView.h index a49e1f33c2..020bc52d6f 100644 --- a/headers/os/interface/TextView.h +++ b/headers/os/interface/TextView.h @@ -236,10 +236,12 @@ virtual void GetPreferredSize(float *width, float *height); virtual void AllAttached(); virtual void AllDetached(); -static void* FlattenRunArray(const text_run_array *inArray, - int32 *outSize = NULL); -static text_run_array* UnflattenRunArray(const void *data, - int32 *outSize = NULL); + +static text_run_array* AllocRunArray(int32 entryCount, int32 *outSize = NULL); +static text_run_array* CopyRunArray(const text_run_array *orig, int32 countDelta = 0); +static void FreeRunArray(text_run_array *array); +static void * FlattenRunArray(const text_run_array *inArray, int32 *outSize = NULL); +static text_run_array* UnflattenRunArray(const void *data, int32 *outSize = NULL); protected: virtual void InsertText(const char *inText, diff --git a/src/kits/interface/BTextView/TextView.cpp b/src/kits/interface/BTextView/TextView.cpp index 2c67e20bb5..4b1be24ed8 100644 --- a/src/kits/interface/BTextView/TextView.cpp +++ b/src/kits/interface/BTextView/TextView.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -274,7 +275,7 @@ BTextView::BTextView(BMessage *archive) text_run_array *runArray = UnflattenRunArray(flattenedRun, (int32 *)&runSize); if (runArray) { SetRunArray(0, TextLength(), runArray); - free(runArray); + FreeRunArray(runArray); } } @@ -351,7 +352,7 @@ BTextView::Archive(BMessage *data, bool deep) const } else err = B_NO_MEMORY; - free(runArray); + FreeRunArray(runArray); return err; } @@ -1337,7 +1338,7 @@ BTextView::Copy(BClipboard *clipboard) text_run_array *runArray = RunArray(fSelStart, fSelEnd, &size); clip->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE, runArray, size); - free(runArray); + FreeRunArray(runArray); } clipboard->Commit(); } @@ -1647,16 +1648,10 @@ BTextView::RunArray(int32 startOffset, int32 endOffset, int32 *outSize) const if (styleRange == NULL) return NULL; - text_run_array *res = (text_run_array *)malloc(sizeof(int32) - + (sizeof(text_run) * styleRange->count)); + text_run_array *res = AllocRunArray(styleRange->count, outSize); - if (!res) { - if (outSize) - *outSize = 0; + if (!res) return NULL; - } - - res->count = styleRange->count; for (int32 i = 0; i < res->count; i++) { res->runs[i].offset = styleRange->runs[i].offset; @@ -1664,9 +1659,6 @@ BTextView::RunArray(int32 startOffset, int32 endOffset, int32 *outSize) const res->runs[i].color = styleRange->runs[i].style.color; } - if (outSize != NULL) - *outSize = sizeof(int32) + (sizeof(text_run) * res->count); - return res; } @@ -2599,6 +2591,65 @@ BTextView::AllDetached() } +/* static */ +text_run_array * +BTextView::AllocRunArray(int32 entryCount, int32 *outSize) +{ + int32 size = sizeof(text_run_array) + (entryCount - 1) * sizeof(text_run); + + text_run_array *runArray = (text_run_array *)malloc(size); + if (runArray == NULL) { + if (outSize != NULL) + *outSize = 0; + return NULL; + } + + memset(runArray, 0, sizeof(size)); + + runArray->count = entryCount; + + // Call constructors explicitly as the text_run_array + // was allocated with malloc + for (int32 i = 0; i < runArray->count; i++) + new (&runArray->runs[i].font) BFont; + //runArray->runs[i].font = new BFont; + + if (outSize != NULL) + *outSize = size; + + return runArray; +} + + +/* static */ +text_run_array * +BTextView::CopyRunArray(const text_run_array *orig, int32 countDelta) +{ + text_run_array *copy = AllocRunArray(countDelta, NULL); + if (copy != NULL) { + for (int32 i = 0; i < countDelta; i++) { + copy->runs[i].offset = orig->runs[i].offset; + copy->runs[i].font = orig->runs[i].font; + copy->runs[i].color = orig->runs[i].color; + } + } + return copy; +} + + +/* static */ +void +BTextView::FreeRunArray(text_run_array *array) +{ + // Call destructors explicitly + for (int32 i = 0; i < array->count; i++) + array->runs[i].font.~BFont(); + + free(array); +} + + +/* static */ void * BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize) { @@ -2643,6 +2694,7 @@ BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize) } +/* static */ text_run_array * BTextView::UnflattenRunArray(const void *data, int32 *outSize) { @@ -2660,35 +2712,14 @@ BTextView::UnflattenRunArray(const void *data, int32 *outSize) return NULL; } - int32 size = sizeof(text_run_array) + (array->count - 1) * sizeof(text_run); - - text_run_array *run_array = (text_run_array *)malloc(size); - if (run_array == NULL) { - *outSize = 0; + + text_run_array *run_array = AllocRunArray(array->count, outSize); + if (run_array == NULL) return NULL; - } - - run_array->count = array->count; for (int32 i = 0; i < array->count; i++) { - run_array->runs[i].offset = array->styles[i].offset; - - // TODO: Here we are leaking memory. - // We should use placement new instead - // new (&run_array->runs[i].font) BFont(); - // The reason we're calling the constructor explicitly is - // that the text_run_array() is allocated with malloc. It can't - // be allocated with new due to its nature: see its definition - // on the top of TextView.h - - // Note that BFont doesn't have a destructor. - // If it had one, our whole RunArray()/SetRunArray() api - // would have to be changed, as it doesn't fit with the fact - // that we'd have to call the BFont's destructor. Or, as Waldemar - // suggested, we'd have to provide a "free_text_run_array()" method - // which would take care of calling the destructors. - - run_array->runs[i].font = new BFont; + run_array->runs[i].offset = array->styles[i].offset; + run_array->runs[i].font.SetFamilyAndStyle(array->styles[i].family, array->styles[i].style); run_array->runs[i].font.SetSize(array->styles[i].size); @@ -2701,9 +2732,6 @@ BTextView::UnflattenRunArray(const void *data, int32 *outSize) run_array->runs[i].color.alpha = array->styles[i].alpha; } - if (outSize) - *outSize = size; - return run_array; } @@ -2803,7 +2831,7 @@ BTextView::GetDragParameters(BMessage *drag, BBitmap **bitmap, BPoint *point, BH drag->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE, styles, size); - free(styles); + FreeRunArray(styles); } if (bitmap != NULL)