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
This commit is contained in:
Stefano Ceccherini 2006-02-03 21:22:00 +00:00
parent fbca7b0cfd
commit e333843348
2 changed files with 78 additions and 48 deletions

View File

@ -236,10 +236,12 @@ virtual void GetPreferredSize(float *width, float *height);
virtual void AllAttached(); virtual void AllAttached();
virtual void AllDetached(); virtual void AllDetached();
static void* FlattenRunArray(const text_run_array *inArray,
int32 *outSize = NULL); static text_run_array* AllocRunArray(int32 entryCount, int32 *outSize = NULL);
static text_run_array* UnflattenRunArray(const void *data, static text_run_array* CopyRunArray(const text_run_array *orig, int32 countDelta = 0);
int32 *outSize = NULL); 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: protected:
virtual void InsertText(const char *inText, virtual void InsertText(const char *inText,

View File

@ -23,6 +23,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <new>
#include <Application.h> #include <Application.h>
#include <Beep.h> #include <Beep.h>
@ -274,7 +275,7 @@ BTextView::BTextView(BMessage *archive)
text_run_array *runArray = UnflattenRunArray(flattenedRun, (int32 *)&runSize); text_run_array *runArray = UnflattenRunArray(flattenedRun, (int32 *)&runSize);
if (runArray) { if (runArray) {
SetRunArray(0, TextLength(), runArray); SetRunArray(0, TextLength(), runArray);
free(runArray); FreeRunArray(runArray);
} }
} }
@ -351,7 +352,7 @@ BTextView::Archive(BMessage *data, bool deep) const
} else } else
err = B_NO_MEMORY; err = B_NO_MEMORY;
free(runArray); FreeRunArray(runArray);
return err; return err;
} }
@ -1337,7 +1338,7 @@ BTextView::Copy(BClipboard *clipboard)
text_run_array *runArray = RunArray(fSelStart, fSelEnd, &size); text_run_array *runArray = RunArray(fSelStart, fSelEnd, &size);
clip->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE, clip->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE,
runArray, size); runArray, size);
free(runArray); FreeRunArray(runArray);
} }
clipboard->Commit(); clipboard->Commit();
} }
@ -1647,16 +1648,10 @@ BTextView::RunArray(int32 startOffset, int32 endOffset, int32 *outSize) const
if (styleRange == NULL) if (styleRange == NULL)
return NULL; return NULL;
text_run_array *res = (text_run_array *)malloc(sizeof(int32) text_run_array *res = AllocRunArray(styleRange->count, outSize);
+ (sizeof(text_run) * styleRange->count));
if (!res) { if (!res)
if (outSize)
*outSize = 0;
return NULL; return NULL;
}
res->count = styleRange->count;
for (int32 i = 0; i < res->count; i++) { for (int32 i = 0; i < res->count; i++) {
res->runs[i].offset = styleRange->runs[i].offset; 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; res->runs[i].color = styleRange->runs[i].style.color;
} }
if (outSize != NULL)
*outSize = sizeof(int32) + (sizeof(text_run) * res->count);
return res; 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 * void *
BTextView::FlattenRunArray(const text_run_array *inArray, int32 *outSize) 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 * text_run_array *
BTextView::UnflattenRunArray(const void *data, int32 *outSize) BTextView::UnflattenRunArray(const void *data, int32 *outSize)
{ {
@ -2660,35 +2712,14 @@ BTextView::UnflattenRunArray(const void *data, int32 *outSize)
return NULL; return NULL;
} }
int32 size = sizeof(text_run_array) + (array->count - 1) * sizeof(text_run);
text_run_array *run_array = AllocRunArray(array->count, outSize);
text_run_array *run_array = (text_run_array *)malloc(size); if (run_array == NULL)
if (run_array == NULL) {
*outSize = 0;
return NULL; return NULL;
}
run_array->count = array->count;
for (int32 i = 0; i < array->count; i++) { for (int32 i = 0; i < array->count; i++) {
run_array->runs[i].offset = array->styles[i].offset; 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].font.SetFamilyAndStyle(array->styles[i].family, run_array->runs[i].font.SetFamilyAndStyle(array->styles[i].family,
array->styles[i].style); array->styles[i].style);
run_array->runs[i].font.SetSize(array->styles[i].size); 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; run_array->runs[i].color.alpha = array->styles[i].alpha;
} }
if (outSize)
*outSize = size;
return run_array; 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, drag->AddData("application/x-vnd.Be-text_run_array", B_MIME_TYPE,
styles, size); styles, size);
free(styles); FreeRunArray(styles);
} }
if (bitmap != NULL) if (bitmap != NULL)