HaikuDepot: Remove Custom List

Closes #15534

Change-Id: I23fa60145607c3e8f25552f24c5e2c630b940537
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3758
Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
Andrew Lindesay 2021-03-01 23:02:30 +13:00
parent 0b69420bc8
commit dfbcbde1e1
18 changed files with 268 additions and 827 deletions

View File

@ -1,408 +0,0 @@
/*
* Copyright 2009-2013, Stephan Aßmus <superstippi@gmx.de>
* Copyright 2018, Andrew Lindesay <apl@lindesay.co.nz>
* All rights reserved. Distributed under the terms of the MIT License.
*/
#ifndef LIST_H
#define LIST_H
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <SupportDefs.h>
#define BINARY_SEARCH_LINEAR_THRESHOLD 4
template <typename ItemType, bool PlainOldData, uint32 BlockSize = 8>
class List {
typedef List<ItemType, PlainOldData, BlockSize> SelfType;
typedef int32 (*CompareItemFn)(const ItemType& one, const ItemType& two);
typedef int32 (*CompareContextFn)(const void* context,
const ItemType& item);
public:
List()
:
fItems(NULL),
fCount(0),
fAllocatedCount(0),
fCompareItemsFunction(NULL),
fCompareContextFunction(NULL)
{
}
List(CompareItemFn compareItemsFunction,
CompareContextFn compareContextFunction)
:
fItems(NULL),
fCount(0),
fAllocatedCount(0),
fCompareItemsFunction(compareItemsFunction),
fCompareContextFunction(compareContextFunction)
{
}
List(const SelfType& other)
:
fItems(NULL),
fCount(0),
fAllocatedCount(0),
fCompareItemsFunction(other.fCompareItemsFunction),
fCompareContextFunction(other.fCompareContextFunction)
{
_AddAllVerbatim(other);
}
virtual ~List()
{
if (!PlainOldData) {
// Make sure to call destructors of old objects.
_Resize(0);
}
free(fItems);
}
SelfType& operator=(const SelfType& other)
{
if (this != &other)
_AddAllVerbatim(other);
return *this;
}
bool operator==(const SelfType& other) const
{
if (this == &other)
return true;
if (fCount != other.fCount)
return false;
if (fCount == 0)
return true;
if (PlainOldData) {
return memcmp(fItems, other.fItems,
fCount * sizeof(ItemType)) == 0;
} else {
for (uint32 i = 0; i < other.fCount; i++) {
if (ItemAtFast(i) != other.ItemAtFast(i))
return false;
}
}
return true;
}
bool operator!=(const SelfType& other) const
{
return !(*this == other);
}
inline void Clear()
{
_Resize(0);
}
inline bool IsEmpty() const
{
return fCount == 0;
}
inline int32 CountItems() const
{
return fCount;
}
/*! Note that the use of this method will depend on the list being sorted.
*/
inline int32 Search(const void* context) const
{
if (fCount == 0 || fCompareContextFunction == NULL)
return -1;
return _BinarySearchBounded(context, 0, fCount - 1);
}
/*! This function will add the item into the list. If the list is sorted
then the item will be insert in order. If the list is not sorted then
the item will be inserted at the end of the list.
*/
inline bool Add(const ItemType& copyFrom)
{
if (fCompareItemsFunction != NULL) {
return _AddOrdered(copyFrom);
}
return _AddTail(copyFrom);
}
inline bool Add(const ItemType& copyFrom, int32 index)
{
// if the list is sorted then ignore the index and just insert in
// order.
if (fCompareItemsFunction != NULL) {
return _AddOrdered(copyFrom);
}
return _AddAtIndex(copyFrom, index);
}
inline bool Remove()
{
if (fCount > 0) {
_Resize(fCount - 1);
return true;
}
return false;
}
inline bool Remove(int32 index)
{
if (index < 0 || index >= (int32)fCount)
return false;
if (!PlainOldData) {
ItemType* object = fItems + index;
object->~ItemType();
}
int32 nextIndex = index + 1;
if ((int32)fCount > nextIndex) {
memcpy(fItems + index, fItems + nextIndex,
(fCount - nextIndex) * sizeof(ItemType));
}
fCount--;
return true;
}
inline bool Remove(const ItemType& item)
{
return Remove(IndexOf(item));
}
inline bool Replace(int32 index, const ItemType& copyFrom)
{
if (fCompareItemsFunction != NULL) {
bool result = Remove(index);
_AddOrdered(copyFrom);
return result;
}
if (index < 0 || index >= (int32)fCount)
return false;
ItemType* item = fItems + index;
// Initialize the new object from the original.
if (!PlainOldData) {
item->~ItemType();
new (item) ItemType(copyFrom);
} else
*item = copyFrom;
return true;
}
inline const ItemType& ItemAt(int32 index) const
{
if (index < 0 || index >= (int32)fCount)
return fNullItem;
return ItemAtFast(index);
}
inline const ItemType& ItemAtFast(int32 index) const
{
return *(fItems + index);
}
inline const ItemType& LastItem() const
{
if (fCount == 0)
return fNullItem;
return ItemAt((int32)fCount - 1);
}
inline int32 IndexOf(const ItemType& item) const
{
for (uint32 i = 0; i < fCount; i++) {
if (ItemAtFast(i) == item)
return i;
}
return -1;
}
inline bool Contains(const ItemType& item) const
{
return IndexOf(item) >= 0;
}
private:
inline int32 _BinarySearchLinearBounded(
const void* context,
int32 start, int32 end) const
{
for(int32 i = start; i <= end; i++) {
if (fCompareContextFunction(context, ItemAtFast(i)) == 0)
return i;
}
return -1;
}
inline int32 _BinarySearchBounded(
const void* context, int32 start, int32 end) const
{
if (end - start < BINARY_SEARCH_LINEAR_THRESHOLD)
return _BinarySearchLinearBounded(context, start, end);
int32 mid = start + ((end - start) >> 1);
if (fCompareContextFunction(context, ItemAtFast(mid)) >= 0)
return _BinarySearchBounded(context, mid, end);
return _BinarySearchBounded(context, start, mid - 1);
}
inline void _AddAllVerbatim(const SelfType& other)
{
if (PlainOldData) {
if (_Resize(other.fCount))
memcpy(fItems, other.fItems, fCount * sizeof(ItemType));
} else {
// Make sure to call destructors of old objects.
// NOTE: Another option would be to use
// ItemType::operator=(const ItemType& other), but then
// we would need to be careful which objects are already
// initialized. Also ItemType would be required to implement the
// operator, while doing it this way requires only a copy
// constructor.
_Resize(0);
for (uint32 i = 0; i < other.fCount; i++) {
if (!Add(other.ItemAtFast(i)))
break;
}
}
}
inline bool _AddOrderedLinearBounded(
const ItemType& copyFrom, int32 start, int32 end)
{
for(int32 i = start; i <= (end + 1); i++) {
bool greaterBefore = (i == start)
|| (fCompareItemsFunction(copyFrom, ItemAtFast(i - 1)) > 0);
if (greaterBefore) {
bool lessAfter = (i == end + 1)
|| (fCompareItemsFunction(copyFrom, ItemAtFast(i)) <= 0);
if (lessAfter)
return _AddAtIndex(copyFrom, i);
}
}
printf("illegal state; unable to insert item into list\n");
exit(EXIT_FAILURE);
}
inline bool _AddOrderedBounded(
const ItemType& copyFrom, int32 start, int32 end)
{
if(end - start < BINARY_SEARCH_LINEAR_THRESHOLD)
return _AddOrderedLinearBounded(copyFrom, start, end);
int32 mid = start + ((end - start) >> 1);
if (fCompareItemsFunction(copyFrom, ItemAtFast(mid)) >= 0)
return _AddOrderedBounded(copyFrom, mid, end);
return _AddOrderedBounded(copyFrom, start, mid - 1);
}
inline bool _AddTail(const ItemType& copyFrom)
{
if (_Resize(fCount + 1)) {
ItemType* item = fItems + fCount - 1;
// Initialize the new object from the original.
if (!PlainOldData)
new (item) ItemType(copyFrom);
else
*item = copyFrom;
return true;
}
return false;
}
inline bool _AddAtIndex(const ItemType& copyFrom, int32 index)
{
if (index < 0 || index > (int32)fCount)
return false;
if (!_Resize(fCount + 1))
return false;
int32 nextIndex = index + 1;
if ((int32)fCount > nextIndex)
memmove(fItems + nextIndex, fItems + index,
(fCount - nextIndex) * sizeof(ItemType));
ItemType* item = fItems + index;
if (!PlainOldData)
new (item) ItemType(copyFrom);
else
*item = copyFrom;
return true;
}
inline bool _AddOrdered(const ItemType& copyFrom)
{
// special case
if (fCount == 0
|| fCompareItemsFunction(copyFrom, ItemAtFast(fCount - 1)) > 0) {
return _AddTail(copyFrom);
}
return _AddOrderedBounded(copyFrom, 0, fCount - 1);
}
inline bool _Resize(uint32 count)
{
if (count > fAllocatedCount) {
uint32 allocationCount = (count + BlockSize - 1)
/ BlockSize * BlockSize;
ItemType* items = reinterpret_cast<ItemType*>(
realloc(fItems, allocationCount * sizeof(ItemType)));
if (items == NULL)
return false;
fItems = items;
fAllocatedCount = allocationCount;
} else if (count < fCount) {
if (!PlainOldData) {
// Uninit old objects so that we can re-use them when
// appending objects without the need to re-allocate.
for (uint32 i = count; i < fCount; i++) {
ItemType* object = fItems + i;
object->~ItemType();
}
}
}
fCount = count;
return true;
}
ItemType* fItems;
ItemType fNullItem;
uint32 fCount;
uint32 fAllocatedCount;
CompareItemFn fCompareItemsFunction;
CompareContextFn fCompareContextFunction;
};
#endif // LIST_H

View File

@ -252,16 +252,13 @@ PackageIconTarRepository::GetIcon(const BString& pkgName, BitmapSize size,
else { else {
HashString key = _ToIconCacheKey(pkgName, actualSize); HashString key = _ToIconCacheKey(pkgName, actualSize);
// TODO; need to implement an LRU cache so that not too many icons are
// in memory at the same time.
if (!fIconCache.ContainsKey(key)) { if (!fIconCache.ContainsKey(key)) {
result = _CreateIconFromTarOffset(iconDataTarOffset, bitmap); result = _CreateIconFromTarOffset(iconDataTarOffset, bitmap);
if (result == B_OK) if (result == B_OK)
fIconCache.Put(key, bitmap); fIconCache.Put(key, bitmap);
else { else {
HDERROR("failure to read image for package [%s] at offset %" HDERROR("failure to read image for package [%s] at offset %"
B_PRIdSSIZE, pkgName.String(), iconDataTarOffset); B_PRIdOFF, pkgName.String(), iconDataTarOffset);
fIconCache.Put(key, sDefaultIcon); fIconCache.Put(key, sDefaultIcon);
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2017-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@ -247,8 +247,6 @@ ServerHelper::GetFailuresFromJsonRpcError(
ValidationFailures& failures, BMessage& responseEnvelopeMessage) ValidationFailures& failures, BMessage& responseEnvelopeMessage)
{ {
BMessage errorMessage; BMessage errorMessage;
int32 errorCode = WebAppInterface::ErrorCodeFromResponse(
responseEnvelopeMessage);
if (responseEnvelopeMessage.FindMessage("error", &errorMessage) == B_OK) { if (responseEnvelopeMessage.FindMessage("error", &errorMessage) == B_OK) {
BMessage dataMessage; BMessage dataMessage;

View File

@ -95,9 +95,9 @@ get_char_classification(uint32 charCode)
inline bool inline bool
can_end_line(const GlyphInfoList& glyphInfos, int offset) can_end_line(const std::vector<GlyphInfo>& glyphInfos, int offset)
{ {
int count = glyphInfos.CountItems(); int count = static_cast<int>(glyphInfos.size());
if (offset == count - 1) if (offset == count - 1)
return true; return true;
@ -105,14 +105,14 @@ can_end_line(const GlyphInfoList& glyphInfos, int offset)
if (offset < 0 || offset > count) if (offset < 0 || offset > count)
return false; return false;
uint32 charCode = glyphInfos.ItemAtFast(offset).charCode; uint32 charCode = glyphInfos[offset].charCode;
uint32 classification = get_char_classification(charCode); uint32 classification = get_char_classification(charCode);
// wrapping is always allowed at end of text and at newlines // wrapping is always allowed at end of text and at newlines
if (classification == CHAR_CLASS_END_OF_TEXT || charCode == '\n') if (classification == CHAR_CLASS_END_OF_TEXT || charCode == '\n')
return true; return true;
uint32 nextCharCode = glyphInfos.ItemAtFast(offset + 1).charCode; uint32 nextCharCode = glyphInfos[offset + 1].charCode;
uint32 nextClassification = get_char_classification(nextCharCode); uint32 nextClassification = get_char_classification(nextCharCode);
// never separate a punctuation char from its preceding word // never separate a punctuation char from its preceding word
@ -241,8 +241,8 @@ ParagraphLayout::Height()
float height = 0.0f; float height = 0.0f;
if (fLineInfos.CountItems() > 0) { if (!fLineInfos.empty()) {
const LineInfo& lastLine = fLineInfos.LastItem(); const LineInfo& lastLine = fLineInfos[fLineInfos.size() - 1];
height = lastLine.y + lastLine.height; height = lastLine.y + lastLine.height;
} }
@ -255,9 +255,9 @@ ParagraphLayout::Draw(BView* view, const BPoint& offset)
{ {
_ValidateLayout(); _ValidateLayout();
int lineCount = fLineInfos.CountItems(); int lineCount = static_cast<int>(fLineInfos.size());
for (int i = 0; i < lineCount; i++) { for (int i = 0; i < lineCount; i++) {
const LineInfo& line = fLineInfos.ItemAtFast(i); const LineInfo& line = fLineInfos[i];
_DrawLine(view, offset, line); _DrawLine(view, offset, line);
} }
@ -268,7 +268,7 @@ ParagraphLayout::Draw(BView* view, const BPoint& offset)
BPoint bulletPos(offset); BPoint bulletPos(offset);
bulletPos.x += fParagraphStyle.FirstLineInset() bulletPos.x += fParagraphStyle.FirstLineInset()
+ fParagraphStyle.LineInset(); + fParagraphStyle.LineInset();
bulletPos.y += fLineInfos.ItemAt(0).maxAscent; bulletPos.y += fLineInfos[0].maxAscent;
view->DrawString(bullet.String(), bulletPos); view->DrawString(bullet.String(), bulletPos);
} }
} }
@ -277,7 +277,7 @@ ParagraphLayout::Draw(BView* view, const BPoint& offset)
int32 int32
ParagraphLayout::CountGlyphs() const ParagraphLayout::CountGlyphs() const
{ {
return fGlyphInfos.CountItems(); return static_cast<int32>(fGlyphInfos.size());
} }
@ -285,7 +285,7 @@ int32
ParagraphLayout::CountLines() ParagraphLayout::CountLines()
{ {
_ValidateLayout(); _ValidateLayout();
return fLineInfos.CountItems(); return static_cast<int32>(fLineInfos.size());
} }
@ -294,18 +294,18 @@ ParagraphLayout::LineIndexForOffset(int32 textOffset)
{ {
_ValidateLayout(); _ValidateLayout();
if (fGlyphInfos.CountItems() == 0) if (fGlyphInfos.empty())
return 0; return 0;
if (textOffset >= fGlyphInfos.CountItems()) { if (textOffset >= static_cast<int32>(fGlyphInfos.size())) {
const GlyphInfo& glyph = fGlyphInfos.LastItem(); const GlyphInfo& glyph = fGlyphInfos[fGlyphInfos.size() - 1];
return glyph.lineIndex; return glyph.lineIndex;
} }
if (textOffset < 0) if (textOffset < 0)
textOffset = 0; textOffset = 0;
const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset); const GlyphInfo& glyph = fGlyphInfos[textOffset];
return glyph.lineIndex; return glyph.lineIndex;
} }
@ -317,10 +317,11 @@ ParagraphLayout::FirstOffsetOnLine(int32 lineIndex)
if (lineIndex < 0) if (lineIndex < 0)
lineIndex = 0; lineIndex = 0;
if (lineIndex >= fLineInfos.CountItems()) int32 countLineInfos = static_cast<int32>(fLineInfos.size());
lineIndex = fLineInfos.CountItems() - 1; if (lineIndex >= countLineInfos)
lineIndex = countLineInfos - 1;
return fLineInfos.ItemAt(lineIndex).textOffset; return fLineInfos[lineIndex].textOffset;
} }
@ -332,10 +333,10 @@ ParagraphLayout::LastOffsetOnLine(int32 lineIndex)
if (lineIndex < 0) if (lineIndex < 0)
lineIndex = 0; lineIndex = 0;
if (lineIndex >= fLineInfos.CountItems() - 1) if (lineIndex >= static_cast<int32>(fLineInfos.size()) - 1)
return CountGlyphs() - 1; return CountGlyphs() - 1;
return fLineInfos.ItemAt(lineIndex + 1).textOffset - 1; return fLineInfos[lineIndex + 1].textOffset - 1;
} }
@ -345,27 +346,28 @@ ParagraphLayout::GetLineBounds(int32 lineIndex, float& x1, float& y1,
{ {
_ValidateLayout(); _ValidateLayout();
if (fGlyphInfos.CountItems() == 0) { if (fGlyphInfos.empty()) {
_GetEmptyLayoutBounds(x1, y1, x2, y2); _GetEmptyLayoutBounds(x1, y1, x2, y2);
return; return;
} }
if (lineIndex < 0) if (lineIndex < 0)
lineIndex = 0; lineIndex = 0;
if (lineIndex >= fLineInfos.CountItems()) int32 countLineInfos = static_cast<int32>(fLineInfos.size());
lineIndex = fLineInfos.CountItems() - 1; if (lineIndex >= countLineInfos)
lineIndex = countLineInfos - 1;
const LineInfo& lineInfo = fLineInfos.ItemAt(lineIndex); const LineInfo& lineInfo = fLineInfos[lineIndex];
int32 firstGlyphIndex = lineInfo.textOffset; int32 firstGlyphIndex = lineInfo.textOffset;
int32 lastGlyphIndex; int32 lastGlyphIndex;
if (lineIndex < fLineInfos.CountItems() - 1) if (lineIndex < countLineInfos - 1)
lastGlyphIndex = fLineInfos.ItemAt(lineIndex + 1).textOffset - 1; lastGlyphIndex = fLineInfos[lineIndex + 1].textOffset - 1;
else else
lastGlyphIndex = fGlyphInfos.CountItems() - 1; lastGlyphIndex = static_cast<int32>(fGlyphInfos.size()) - 1;
const GlyphInfo& firstInfo = fGlyphInfos.ItemAtFast(firstGlyphIndex); const GlyphInfo& firstInfo = fGlyphInfos[firstGlyphIndex];
const GlyphInfo& lastInfo = fGlyphInfos.ItemAtFast(lastGlyphIndex); const GlyphInfo& lastInfo = fGlyphInfos[lastGlyphIndex];
x1 = firstInfo.x; x1 = firstInfo.x;
y1 = lineInfo.y; y1 = lineInfo.y;
@ -380,14 +382,14 @@ ParagraphLayout::GetTextBounds(int32 textOffset, float& x1, float& y1,
{ {
_ValidateLayout(); _ValidateLayout();
if (fGlyphInfos.CountItems() == 0) { if (fGlyphInfos.empty()) {
_GetEmptyLayoutBounds(x1, y1, x2, y2); _GetEmptyLayoutBounds(x1, y1, x2, y2);
return; return;
} }
if (textOffset >= fGlyphInfos.CountItems()) { if (textOffset >= static_cast<int32>(fGlyphInfos.size())) {
const GlyphInfo& glyph = fGlyphInfos.LastItem(); const GlyphInfo& glyph = fGlyphInfos[fGlyphInfos.size() - 1];
const LineInfo& line = fLineInfos.ItemAt(glyph.lineIndex); const LineInfo& line = fLineInfos[glyph.lineIndex];
x1 = glyph.x + glyph.width; x1 = glyph.x + glyph.width;
x2 = x1; x2 = x1;
@ -400,8 +402,8 @@ ParagraphLayout::GetTextBounds(int32 textOffset, float& x1, float& y1,
if (textOffset < 0) if (textOffset < 0)
textOffset = 0; textOffset = 0;
const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset); const GlyphInfo& glyph = fGlyphInfos[textOffset];
const LineInfo& line = fLineInfos.ItemAt(glyph.lineIndex); const LineInfo& line = fLineInfos[glyph.lineIndex];
x1 = glyph.x; x1 = glyph.x;
x2 = x1 + glyph.width; x2 = x1 + glyph.width;
@ -417,19 +419,19 @@ ParagraphLayout::TextOffsetAt(float x, float y, bool& rightOfCenter)
rightOfCenter = false; rightOfCenter = false;
int32 lineCount = fLineInfos.CountItems(); int32 lineCount = static_cast<int32>(fLineInfos.size());
if (fGlyphInfos.CountItems() == 0 || lineCount == 0 if (fGlyphInfos.empty() || lineCount == 0
|| fLineInfos.ItemAtFast(0).y > y) { || fLineInfos[0].y > y) {
// Above first line or empty text // Above first line or empty text
return 0; return 0;
} }
int32 lineIndex = 0; int32 lineIndex = 0;
if (floorf(fLineInfos.LastItem().y LineInfo lastLineInfo = fLineInfos[fLineInfos.size() - 1];
+ fLineInfos.LastItem().height + 0.5) > y) { if (floorf(lastLineInfo.y + lastLineInfo.height + 0.5) > y) {
// TODO: Optimize, can binary search line here: // TODO: Optimize, can binary search line here:
for (; lineIndex < lineCount; lineIndex++) { for (; lineIndex < lineCount; lineIndex++) {
const LineInfo& line = fLineInfos.ItemAtFast(lineIndex); const LineInfo& line = fLineInfos[lineIndex];
float lineBottom = floorf(line.y + line.height + 0.5); float lineBottom = floorf(line.y + line.height + 0.5);
if (lineBottom > y) if (lineBottom > y)
break; break;
@ -439,17 +441,17 @@ ParagraphLayout::TextOffsetAt(float x, float y, bool& rightOfCenter)
} }
// Found line // Found line
const LineInfo& line = fLineInfos.ItemAtFast(lineIndex); const LineInfo& line = fLineInfos[lineIndex];
int32 textOffset = line.textOffset; int32 textOffset = line.textOffset;
int32 end; int32 end;
if (lineIndex < lineCount - 1) if (lineIndex < lineCount - 1)
end = fLineInfos.ItemAtFast(lineIndex + 1).textOffset - 1; end = fLineInfos[lineIndex + 1].textOffset - 1;
else else
end = fGlyphInfos.CountItems() - 1; end = fGlyphInfos.size() - 1;
// TODO: Optimize, can binary search offset here: // TODO: Optimize, can binary search offset here:
for (; textOffset <= end; textOffset++) { for (; textOffset <= end; textOffset++) {
const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset); const GlyphInfo& glyph = fGlyphInfos[textOffset];
float x1 = glyph.x; float x1 = glyph.x;
if (x1 > x) if (x1 > x)
return textOffset; return textOffset;
@ -461,7 +463,7 @@ ParagraphLayout::TextOffsetAt(float x, float y, bool& rightOfCenter)
// x2 in case the line is justified. // x2 in case the line is justified.
float x3; float x3;
if (textOffset < end - 1) if (textOffset < end - 1)
x3 = fGlyphInfos.ItemAtFast(textOffset + 1).x; x3 = fGlyphInfos[textOffset + 1].x;
else else
x3 = x2; x3 = x2;
@ -473,7 +475,7 @@ ParagraphLayout::TextOffsetAt(float x, float y, bool& rightOfCenter)
// Account for trailing line break at end of line, the // Account for trailing line break at end of line, the
// returned offset should be before that. // returned offset should be before that.
rightOfCenter = fGlyphInfos.ItemAtFast(end).charCode != '\n'; rightOfCenter = fGlyphInfos[end].charCode != '\n';
return end; return end;
} }
@ -485,7 +487,7 @@ ParagraphLayout::TextOffsetAt(float x, float y, bool& rightOfCenter)
void void
ParagraphLayout::_Init() ParagraphLayout::_Init()
{ {
fGlyphInfos.Clear(); fGlyphInfos.clear();
std::vector<TextSpan>::const_iterator it; std::vector<TextSpan>::const_iterator it;
for (it = fTextSpans.begin(); it != fTextSpans.end(); it++) { for (it = fTextSpans.begin(); it != fTextSpans.end(); it++) {
@ -512,7 +514,7 @@ ParagraphLayout::_ValidateLayout()
void void
ParagraphLayout::_Layout() ParagraphLayout::_Layout()
{ {
fLineInfos.Clear(); fLineInfos.clear();
const Bullet& bullet = fParagraphStyle.Bullet(); const Bullet& bullet = fParagraphStyle.Bullet();
@ -522,9 +524,9 @@ ParagraphLayout::_Layout()
int lineIndex = 0; int lineIndex = 0;
int lineStart = 0; int lineStart = 0;
int glyphCount = fGlyphInfos.CountItems(); int glyphCount = static_cast<int>(fGlyphInfos.size());
for (int i = 0; i < glyphCount; i++) { for (int i = 0; i < glyphCount; i++) {
GlyphInfo glyph = fGlyphInfos.ItemAtFast(i); GlyphInfo glyph = fGlyphInfos[i];
uint32 charClassification = get_char_classification(glyph.charCode); uint32 charClassification = get_char_classification(glyph.charCode);
@ -565,9 +567,9 @@ ParagraphLayout::_Layout()
nextLine = true; nextLine = true;
lineBreak = true; lineBreak = true;
glyph.x = x; glyph.x = x;
fGlyphInfos.Replace(i, glyph); fGlyphInfos[i] = glyph;
} else if (fWidth > 0.0f && x + advanceX > fWidth) { } else if (fWidth > 0.0f && x + advanceX > fWidth) {
fGlyphInfos.Replace(i, glyph); fGlyphInfos[i] = glyph;
if (charClassification == CHAR_CLASS_WHITESPACE) { if (charClassification == CHAR_CLASS_WHITESPACE) {
advanceX = 0.0f; advanceX = 0.0f;
} else if (i > lineStart) { } else if (i > lineStart) {
@ -587,7 +589,7 @@ ParagraphLayout::_Layout()
// Adjust the glyph info to point at the changed buffer // Adjust the glyph info to point at the changed buffer
// position // position
glyph = fGlyphInfos.ItemAtFast(i); glyph = fGlyphInfos[i];
advanceX = glyph.width; advanceX = glyph.width;
} else { } else {
// Just break where we are. // Just break where we are.
@ -623,7 +625,7 @@ ParagraphLayout::_Layout()
if (!lineBreak && i < glyphCount) { if (!lineBreak && i < glyphCount) {
glyph.x = x; glyph.x = x;
fGlyphInfos.Replace(i, glyph); fGlyphInfos[i] = glyph;
} }
x += advanceX; x += advanceX;
@ -649,7 +651,7 @@ ParagraphLayout::_ApplyAlignment()
if (alignment == ALIGN_LEFT && !justify) if (alignment == ALIGN_LEFT && !justify)
return; return;
int glyphCount = fGlyphInfos.CountItems(); int glyphCount = static_cast<int>(fGlyphInfos.size());
if (glyphCount == 0) if (glyphCount == 0)
return; return;
@ -663,7 +665,7 @@ ParagraphLayout::_ApplyAlignment()
// the position of the character determines the available space to be // the position of the character determines the available space to be
// distributed (spaceLeft). // distributed (spaceLeft).
for (int i = glyphCount - 1; i >= 0; i--) { for (int i = glyphCount - 1; i >= 0; i--) {
GlyphInfo glyph = fGlyphInfos.ItemAtFast(i); GlyphInfo glyph = fGlyphInfos[i];
if (glyph.lineIndex != lineIndex) { if (glyph.lineIndex != lineIndex) {
bool lineBreak = glyph.charCode == '\n' || i == glyphCount - 1; bool lineBreak = glyph.charCode == '\n' || i == glyphCount - 1;
@ -695,7 +697,7 @@ ParagraphLayout::_ApplyAlignment()
int charCount = 0; int charCount = 0;
int spaceCount = 0; int spaceCount = 0;
for (int j = i; j >= 0; j--) { for (int j = i; j >= 0; j--) {
const GlyphInfo& previousGlyph = fGlyphInfos.ItemAtFast(j); const GlyphInfo& previousGlyph = fGlyphInfos[j];
if (previousGlyph.lineIndex != lineIndex) { if (previousGlyph.lineIndex != lineIndex) {
j++; j++;
break; break;
@ -737,11 +739,11 @@ ParagraphLayout::_ApplyAlignment()
if (charCount > 0) if (charCount > 0)
charSpace = spaceLeftForChars / charCount; charSpace = spaceLeftForChars / charCount;
LineInfo line = fLineInfos.ItemAtFast(lineIndex); LineInfo line = fLineInfos[lineIndex];
line.extraGlyphSpacing = charSpace; line.extraGlyphSpacing = charSpace;
line.extraWhiteSpacing = whiteSpace; line.extraWhiteSpacing = whiteSpace;
fLineInfos.Replace(lineIndex, line); fLineInfos[lineIndex] = line;
} }
} }
@ -754,7 +756,7 @@ ParagraphLayout::_ApplyAlignment()
unsigned classification = get_char_classification(glyph.charCode); unsigned classification = get_char_classification(glyph.charCode);
if (i < glyphCount - 1) { if (i < glyphCount - 1) {
GlyphInfo nextGlyph = fGlyphInfos.ItemAtFast(i + 1); GlyphInfo nextGlyph = fGlyphInfos[i + 1];
if (nextGlyph.lineIndex == lineIndex) { if (nextGlyph.lineIndex == lineIndex) {
uint32 nextClassification uint32 nextClassification
= get_char_classification(nextGlyph.charCode); = get_char_classification(nextGlyph.charCode);
@ -765,12 +767,12 @@ ParagraphLayout::_ApplyAlignment()
// character // character
float shift = (nextGlyph.x - glyph.x) - glyph.width; float shift = (nextGlyph.x - glyph.x) - glyph.width;
nextGlyph.x -= shift; nextGlyph.x -= shift;
fGlyphInfos.Replace(i + 1, nextGlyph); fGlyphInfos[i + 1] = nextGlyph;
} }
} }
} }
fGlyphInfos.Replace(i, glyph); fGlyphInfos[i] = glyph;
// The shift (spaceLeft) is reduced depending on the character // The shift (spaceLeft) is reduced depending on the character
// classification. // classification.
@ -830,7 +832,16 @@ ParagraphLayout::_AppendGlyphInfo(uint32 charCode, float width,
width += style.GlyphSpacing(); width += style.GlyphSpacing();
return fGlyphInfos.Add(GlyphInfo(charCode, 0.0f, width, 0)); try {
fGlyphInfos.push_back(GlyphInfo(charCode, 0.0f, width, 0));
}
catch (std::bad_alloc& ba) {
fprintf(stderr, "bad_alloc occurred adding glyph info to a "
"paragraph\n");
return false;
}
return true;
} }
@ -846,9 +857,9 @@ ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex,
for (int i = lineStart; i <= lineEnd; i++) { for (int i = lineStart; i <= lineEnd; i++) {
// Mark line index in glyph // Mark line index in glyph
GlyphInfo glyph = fGlyphInfos.ItemAtFast(i); GlyphInfo glyph = fGlyphInfos[i];
glyph.lineIndex = lineIndex; glyph.lineIndex = lineIndex;
fGlyphInfos.Replace(i, glyph); fGlyphInfos[i] = glyph;
// See if the next sub-span needs to be added to the LineInfo // See if the next sub-span needs to be added to the LineInfo
bool addSpan = false; bool addSpan = false;
@ -870,7 +881,7 @@ ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex,
} }
} }
if (fGlyphInfos.CountItems() == 0 && !fTextSpans.empty()) { if (fGlyphInfos.empty() && !fTextSpans.empty()) {
// When the layout contains no glyphs, but there is at least one // When the layout contains no glyphs, but there is at least one
// TextSpan in the paragraph, use the font info from that span // TextSpan in the paragraph, use the font info from that span
// to calculate the height of the first LineInfo. // to calculate the height of the first LineInfo.
@ -881,7 +892,15 @@ ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex,
lineHeight = line.height; lineHeight = line.height;
return fLineInfos.Add(line); try {
fLineInfos.push_back(line);
}
catch (std::bad_alloc& ba) {
fprintf(stderr, "bad_alloc occurred adding line to line infos\n");
return false;
}
return true;
} }
@ -928,8 +947,8 @@ ParagraphLayout::_DrawSpan(BView* view, BPoint offset,
if (text.Length() == 0) if (text.Length() == 0)
return; return;
const GlyphInfo& glyph = fGlyphInfos.ItemAtFast(textOffset); const GlyphInfo& glyph = fGlyphInfos[textOffset];
const LineInfo& line = fLineInfos.ItemAtFast(glyph.lineIndex); const LineInfo& line = fLineInfos[glyph.lineIndex];
offset.x += glyph.x; offset.x += glyph.x;
offset.y += line.y + line.maxAscent; offset.y += line.y + line.maxAscent;
@ -957,7 +976,7 @@ void
ParagraphLayout::_GetEmptyLayoutBounds(float& x1, float& y1, float& x2, ParagraphLayout::_GetEmptyLayoutBounds(float& x1, float& y1, float& x2,
float& y2) const float& y2) const
{ {
if (fLineInfos.CountItems() == 0) { if (fLineInfos.empty()) {
x1 = 0.0f; x1 = 0.0f;
y1 = 0.0f; y1 = 0.0f;
x2 = 0.0f; x2 = 0.0f;
@ -972,7 +991,7 @@ ParagraphLayout::_GetEmptyLayoutBounds(float& x1, float& y1, float& x2,
x1 = fParagraphStyle.LineInset() + fParagraphStyle.FirstLineInset() x1 = fParagraphStyle.LineInset() + fParagraphStyle.FirstLineInset()
+ bullet.Spacing(); + bullet.Spacing();
x2 = x1; x2 = x1;
const LineInfo& lineInfo = fLineInfos.ItemAt(0); const LineInfo& lineInfo = fLineInfos[0];
y1 = lineInfo.y; y1 = lineInfo.y;
y2 = lineInfo.y + lineInfo.height; y2 = lineInfo.y + lineInfo.height;
} }

View File

@ -81,9 +81,6 @@ public:
}; };
typedef List<GlyphInfo, false> GlyphInfoList;
class LineInfo { class LineInfo {
public: public:
LineInfo() LineInfo()
@ -173,9 +170,6 @@ public:
}; };
typedef List<LineInfo, false> LineInfoList;
class ParagraphLayout : public BReferenceable { class ParagraphLayout : public BReferenceable {
public: public:
ParagraphLayout(); ParagraphLayout();
@ -249,8 +243,10 @@ private:
float fWidth; float fWidth;
bool fLayoutValid; bool fLayoutValid;
GlyphInfoList fGlyphInfos; std::vector<GlyphInfo>
LineInfoList fLineInfos; fGlyphInfos;
std::vector<LineInfo>
fLineInfos;
}; };

View File

@ -194,7 +194,14 @@ TextDocument::ParagraphStyleAt(int32 textOffset) const
int32 int32
TextDocument::CountParagraphs() const TextDocument::CountParagraphs() const
{ {
return fParagraphs.CountItems(); return fParagraphs.size();
}
const Paragraph&
TextDocument::ParagraphAtIndex(int32 index) const
{
return fParagraphs[index];
} }
@ -205,9 +212,9 @@ TextDocument::ParagraphIndexFor(int32 textOffset, int32& paragraphOffset) const
// that knew there text offset in the document. // that knew there text offset in the document.
int32 textLength = 0; int32 textLength = 0;
paragraphOffset = 0; paragraphOffset = 0;
int32 count = fParagraphs.CountItems(); int32 count = fParagraphs.size();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
const Paragraph& paragraph = fParagraphs.ItemAtFast(i); const Paragraph& paragraph = fParagraphs[i];
int32 paragraphLength = paragraph.Length(); int32 paragraphLength = paragraph.Length();
textLength += paragraphLength; textLength += paragraphLength;
if (textLength > textOffset if (textLength > textOffset
@ -225,7 +232,7 @@ TextDocument::ParagraphAt(int32 textOffset, int32& paragraphOffset) const
{ {
int32 index = ParagraphIndexFor(textOffset, paragraphOffset); int32 index = ParagraphIndexFor(textOffset, paragraphOffset);
if (index >= 0) if (index >= 0)
return fParagraphs.ItemAtFast(index); return fParagraphs[index];
return fEmptyLastParagraph; return fEmptyLastParagraph;
} }
@ -234,8 +241,8 @@ TextDocument::ParagraphAt(int32 textOffset, int32& paragraphOffset) const
const Paragraph& const Paragraph&
TextDocument::ParagraphAt(int32 index) const TextDocument::ParagraphAt(int32 index) const
{ {
if (index >= 0 && index < fParagraphs.CountItems()) if (index >= 0 && index < static_cast<int32>(fParagraphs.size()))
return fParagraphs.ItemAtFast(index); return fParagraphs[index];
return fEmptyLastParagraph; return fEmptyLastParagraph;
} }
@ -243,7 +250,15 @@ TextDocument::ParagraphAt(int32 index) const
bool bool
TextDocument::Append(const Paragraph& paragraph) TextDocument::Append(const Paragraph& paragraph)
{ {
return fParagraphs.Add(paragraph); try {
fParagraphs.push_back(paragraph);
}
catch (std::bad_alloc& ba) {
fprintf(stderr, "bad_alloc when adding a paragraph to a text "
"document\n");
return false;
}
return true;
} }
@ -253,9 +268,9 @@ TextDocument::Length() const
// TODO: Could be O(1) if the Paragraphs were wrapped in classes that // TODO: Could be O(1) if the Paragraphs were wrapped in classes that
// knew their text offset in the document. // knew their text offset in the document.
int32 textLength = 0; int32 textLength = 0;
int32 count = fParagraphs.CountItems(); int32 count = fParagraphs.size();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
const Paragraph& paragraph = fParagraphs.ItemAtFast(i); const Paragraph& paragraph = fParagraphs[i];
textLength += paragraph.Length(); textLength += paragraph.Length();
} }
return textLength; return textLength;
@ -277,9 +292,9 @@ TextDocument::Text(int32 start, int32 length) const
BString text; BString text;
int32 count = fParagraphs.CountItems(); int32 count = fParagraphs.size();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
const Paragraph& paragraph = fParagraphs.ItemAtFast(i); const Paragraph& paragraph = fParagraphs[i];
int32 paragraphLength = paragraph.Length(); int32 paragraphLength = paragraph.Length();
if (paragraphLength == 0) if (paragraphLength == 0)
continue; continue;
@ -319,9 +334,9 @@ TextDocument::SubDocument(int32 start, int32 length) const
if (start < 0) if (start < 0)
start = 0; start = 0;
int32 count = fParagraphs.CountItems(); int32 count = fParagraphs.size();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
const Paragraph& paragraph = fParagraphs.ItemAtFast(i); const Paragraph& paragraph = fParagraphs[i];
int32 paragraphLength = paragraph.Length(); int32 paragraphLength = paragraph.Length();
if (paragraphLength == 0) if (paragraphLength == 0)
continue; continue;
@ -355,14 +370,14 @@ TextDocument::SubDocument(int32 start, int32 length) const
void void
TextDocument::PrintToStream() const TextDocument::PrintToStream() const
{ {
int32 paragraphCount = fParagraphs.CountItems(); int32 paragraphCount = fParagraphs.size();
if (paragraphCount == 0) { if (paragraphCount == 0) {
printf("<document/>\n"); printf("<document/>\n");
return; return;
} }
printf("<document>\n"); printf("<document>\n");
for (int32 i = 0; i < paragraphCount; i++) { for (int32 i = 0; i < paragraphCount; i++) {
fParagraphs.ItemAtFast(i).PrintToStream(); fParagraphs[i].PrintToStream();
} }
printf("</document>\n"); printf("</document>\n");
} }
@ -413,28 +428,46 @@ TextDocument::NormalizeText(const BString& text,
bool bool
TextDocument::AddListener(TextListenerRef listener) TextDocument::AddListener(TextListenerRef listener)
{ {
return fTextListeners.Add(listener); try {
fTextListeners.push_back(listener);
}
catch (std::bad_alloc& ba) {
fprintf(stderr, "bad_alloc when adding a listener to a text "
"document\n");
return false;
}
return true;
} }
bool bool
TextDocument::RemoveListener(TextListenerRef listener) TextDocument::RemoveListener(TextListenerRef listener)
{ {
return fTextListeners.Remove(listener); std::remove(fTextListeners.begin(), fTextListeners.end(), listener);
return true;
} }
bool bool
TextDocument::AddUndoListener(UndoableEditListenerRef listener) TextDocument::AddUndoListener(UndoableEditListenerRef listener)
{ {
return fUndoListeners.Add(listener); try {
fUndoListeners.push_back(listener);
}
catch (std::bad_alloc& ba) {
fprintf(stderr, "bad_alloc when adding an undo listener to a text "
"document\n");
return false;
}
return true;
} }
bool bool
TextDocument::RemoveUndoListener(UndoableEditListenerRef listener) TextDocument::RemoveUndoListener(UndoableEditListenerRef listener)
{ {
return fUndoListeners.Remove(listener); std::remove(fUndoListeners.begin(), fUndoListeners.end(), listener);
return true;
} }
@ -494,7 +527,7 @@ TextDocument::_Insert(int32 textOffset, TextDocumentRef document,
} }
} }
fParagraphs.Remove(index); fParagraphs.erase(fParagraphs.begin() + index);
// Append first paragraph in other document to first part of // Append first paragraph in other document to first part of
// paragraph at insert position // paragraph at insert position
@ -510,16 +543,25 @@ TextDocument::_Insert(int32 textOffset, TextDocumentRef document,
} }
// Insert the first paragraph-part again to the document // Insert the first paragraph-part again to the document
if (!fParagraphs.Add(paragraph1, index)) try {
fParagraphs.insert(fParagraphs.begin() + index, paragraph1);
}
catch (std::bad_alloc& ba) {
return B_NO_MEMORY; return B_NO_MEMORY;
}
paragraphCount++; paragraphCount++;
// Insert the other document's paragraph save for the last one // Insert the other document's paragraph save for the last one
for (int32 i = 1; i < document->CountParagraphs() - 1; i++) { for (int32 i = 1; i < document->CountParagraphs() - 1; i++) {
const Paragraph& otherParagraph = document->ParagraphAt(i); const Paragraph& otherParagraph = document->ParagraphAt(i);
// TODO: Import/map CharacterStyles and ParagraphStyle // TODO: Import/map CharacterStyles and ParagraphStyle
if (!fParagraphs.Add(otherParagraph, ++index)) index++;
try {
fParagraphs.insert(fParagraphs.begin() + index, otherParagraph);
}
catch (std::bad_alloc& ba) {
return B_NO_MEMORY; return B_NO_MEMORY;
}
paragraphCount++; paragraphCount++;
} }
@ -528,8 +570,13 @@ TextDocument::_Insert(int32 textOffset, TextDocumentRef document,
const Paragraph& otherParagraph = document->ParagraphAt(lastIndex); const Paragraph& otherParagraph = document->ParagraphAt(lastIndex);
if (otherParagraph.EndsWith("\n")) { if (otherParagraph.EndsWith("\n")) {
// TODO: Import/map CharacterStyles and ParagraphStyle // TODO: Import/map CharacterStyles and ParagraphStyle
if (!fParagraphs.Add(otherParagraph, ++index)) index++;
try {
fParagraphs.insert(fParagraphs.begin() + index, otherParagraph);
}
catch (std::bad_alloc& ba) {
return B_NO_MEMORY; return B_NO_MEMORY;
}
} else { } else {
int32 spanCount = otherParagraph.CountTextSpans(); int32 spanCount = otherParagraph.CountTextSpans();
for (int32 i = 0; i < spanCount; i++) { for (int32 i = 0; i < spanCount; i++) {
@ -553,8 +600,13 @@ TextDocument::_Insert(int32 textOffset, TextDocumentRef document,
return B_NO_MEMORY; return B_NO_MEMORY;
} }
if (!fParagraphs.Add(paragraph2, ++index)) index++;
try {
fParagraphs.insert(fParagraphs.begin() + index, paragraph2);
}
catch (std::bad_alloc& ba) {
return B_NO_MEMORY; return B_NO_MEMORY;
}
paragraphCount++; paragraphCount++;
} else { } else {
@ -568,9 +620,7 @@ TextDocument::_Insert(int32 textOffset, TextDocumentRef document,
textOffset += span.CountChars(); textOffset += span.CountChars();
} }
if (!fParagraphs.Replace(index, paragraph)) fParagraphs[index] = paragraph;
return B_NO_MEMORY;
paragraphCount++; paragraphCount++;
} }
@ -612,7 +662,7 @@ TextDocument::_Remove(int32 textOffset, int32 length, int32& index,
} }
if (textOffset == paragraphLength && length == 0 if (textOffset == paragraphLength && length == 0
&& index + 1 < fParagraphs.CountItems()) { && index + 1 < static_cast<int32>(fParagraphs.size())) {
// Line break between paragraphs got removed. Shift the next // Line break between paragraphs got removed. Shift the next
// paragraph's text spans into the resulting one. // paragraph's text spans into the resulting one.
@ -622,13 +672,13 @@ TextDocument::_Remove(int32 textOffset, int32 length, int32& index,
const TextSpan& span = paragraph.TextSpanAtIndex(i); const TextSpan& span = paragraph.TextSpanAtIndex(i);
resultParagraph.Append(span); resultParagraph.Append(span);
} }
fParagraphs.Remove(index + 1); fParagraphs.erase(fParagraphs.begin() + (index + 1));
paragraphCount++; paragraphCount++;
} }
textOffset = 0; textOffset = 0;
while (length > 0 && index + 1 < fParagraphs.CountItems()) { while (length > 0 && index + 1 < static_cast<int32>(fParagraphs.size())) {
paragraphCount++; paragraphCount++;
const Paragraph& paragraph = ParagraphAt(index + 1); const Paragraph& paragraph = ParagraphAt(index + 1);
paragraphLength = paragraph.Length(); paragraphLength = paragraph.Length();
@ -637,12 +687,12 @@ TextDocument::_Remove(int32 textOffset, int32 length, int32& index,
// transfered to the result parahraph. // transfered to the result parahraph.
if (length >= paragraphLength) { if (length >= paragraphLength) {
length -= paragraphLength; length -= paragraphLength;
fParagraphs.Remove(index); fParagraphs.erase(fParagraphs.begin() + index);
} else { } else {
// Last paragraph reached // Last paragraph reached
int32 removedLength = std::min(length, paragraphLength); int32 removedLength = std::min(length, paragraphLength);
Paragraph newParagraph(paragraph); Paragraph newParagraph(paragraph);
fParagraphs.Remove(index + 1); fParagraphs.erase(fParagraphs.begin() + (index + 1));
if (!newParagraph.Remove(0, removedLength)) if (!newParagraph.Remove(0, removedLength))
return B_NO_MEMORY; return B_NO_MEMORY;
@ -658,7 +708,7 @@ TextDocument::_Remove(int32 textOffset, int32 length, int32& index,
} }
} }
fParagraphs.Replace(index, resultParagraph); fParagraphs[index] = resultParagraph;
return B_OK; return B_OK;
} }
@ -672,10 +722,11 @@ TextDocument::_NotifyTextChanging(TextChangingEvent& event) const
{ {
// Copy listener list to have a stable list in case listeners // Copy listener list to have a stable list in case listeners
// are added/removed from within the notification hook. // are added/removed from within the notification hook.
TextListenerList listeners(fTextListeners); std::vector<TextListenerRef> listeners(fTextListeners);
int32 count = listeners.CountItems();
int32 count = listeners.size();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
const TextListenerRef& listener = listeners.ItemAtFast(i); const TextListenerRef& listener = listeners[i];
if (!listener.IsSet()) if (!listener.IsSet())
continue; continue;
listener->TextChanging(event); listener->TextChanging(event);
@ -690,10 +741,10 @@ TextDocument::_NotifyTextChanged(const TextChangedEvent& event) const
{ {
// Copy listener list to have a stable list in case listeners // Copy listener list to have a stable list in case listeners
// are added/removed from within the notification hook. // are added/removed from within the notification hook.
TextListenerList listeners(fTextListeners); std::vector<TextListenerRef> listeners(fTextListeners);
int32 count = listeners.CountItems(); int32 count = listeners.size();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
const TextListenerRef& listener = listeners.ItemAtFast(i); const TextListenerRef& listener = listeners[i];
if (!listener.IsSet()) if (!listener.IsSet())
continue; continue;
listener->TextChanged(event); listener->TextChanged(event);
@ -706,10 +757,10 @@ TextDocument::_NotifyUndoableEditHappened(const UndoableEditRef& edit) const
{ {
// Copy listener list to have a stable list in case listeners // Copy listener list to have a stable list in case listeners
// are added/removed from within the notification hook. // are added/removed from within the notification hook.
UndoListenerList listeners(fUndoListeners); std::vector<UndoableEditListenerRef> listeners(fUndoListeners);
int32 count = listeners.CountItems(); int32 count = listeners.size();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
const UndoableEditListenerRef& listener = listeners.ItemAtFast(i); const UndoableEditListenerRef& listener = listeners[i];
if (!listener.IsSet()) if (!listener.IsSet())
continue; continue;
listener->UndoableEditHappened(this, edit); listener->UndoableEditHappened(this, edit);

View File

@ -14,10 +14,6 @@
#include "UndoableEditListener.h" #include "UndoableEditListener.h"
typedef List<Paragraph, false> ParagraphList;
typedef List<TextListenerRef, false> TextListenerList;
typedef List<UndoableEditListenerRef, false> UndoListenerList;
class TextDocument; class TextDocument;
typedef BReference<TextDocument> TextDocumentRef; typedef BReference<TextDocument> TextDocumentRef;
@ -60,11 +56,8 @@ public:
const CharacterStyle& CharacterStyleAt(int32 textOffset) const; const CharacterStyle& CharacterStyleAt(int32 textOffset) const;
const ParagraphStyle& ParagraphStyleAt(int32 textOffset) const; const ParagraphStyle& ParagraphStyleAt(int32 textOffset) const;
// Paragraph access
const ParagraphList& Paragraphs() const
{ return fParagraphs; }
int32 CountParagraphs() const; int32 CountParagraphs() const;
const Paragraph& ParagraphAtIndex(int32 index) const;
int32 ParagraphIndexFor(int32 textOffset, int32 ParagraphIndexFor(int32 textOffset,
int32& paragraphOffset) const; int32& paragraphOffset) const;
@ -117,12 +110,15 @@ private:
const UndoableEditRef& edit) const; const UndoableEditRef& edit) const;
private: private:
ParagraphList fParagraphs; std::vector<Paragraph>
fParagraphs;
Paragraph fEmptyLastParagraph; Paragraph fEmptyLastParagraph;
CharacterStyle fDefaultCharacterStyle; CharacterStyle fDefaultCharacterStyle;
TextListenerList fTextListeners; std::vector<TextListenerRef>
UndoListenerList fUndoListeners; fTextListeners;
std::vector<UndoableEditListenerRef>
fUndoListeners;
}; };

View File

@ -113,7 +113,7 @@ void
TextDocumentLayout::Invalidate() TextDocumentLayout::Invalidate()
{ {
if (fDocument.IsSet()) if (fDocument.IsSet())
InvalidateParagraphs(0, fDocument->Paragraphs().CountItems()); InvalidateParagraphs(0, fDocument->CountParagraphs());
} }
@ -125,24 +125,28 @@ TextDocumentLayout::InvalidateParagraphs(int32 start, int32 count)
fLayoutValid = false; fLayoutValid = false;
const ParagraphList& paragraphs = fDocument->Paragraphs();
while (count > 0) { while (count > 0) {
if (start >= paragraphs.CountItems()) const int32 paragraphCount = fDocument->CountParagraphs();
if (start >= paragraphCount)
break; break;
const Paragraph& paragraph = paragraphs.ItemAtFast(start); const Paragraph& paragraph = fDocument->ParagraphAtIndex(start);
if (start >= fParagraphLayouts.CountItems()) { if (start >= static_cast<int32>(fParagraphLayouts.size())) {
ParagraphLayoutRef layout(new(std::nothrow) ParagraphLayout( ParagraphLayoutRef layout(new(std::nothrow) ParagraphLayout(
paragraph), true); paragraph), true);
if (!layout.IsSet() if (!layout.IsSet()) {
|| !fParagraphLayouts.Add(ParagraphLayoutInfo(0.0f, layout))) {
fprintf(stderr, "TextDocumentLayout::InvalidateParagraphs() - " fprintf(stderr, "TextDocumentLayout::InvalidateParagraphs() - "
"out of memory\n"); "out of memory\n");
return; return;
} }
try {
fParagraphLayouts.push_back(ParagraphLayoutInfo(0.0f, layout));
}
catch (std::bad_alloc& ba) {
fprintf(stderr, "bad_alloc when invalidating paragraphs\n");
return;
}
} else { } else {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast( const ParagraphLayoutInfo& info = fParagraphLayouts[start];
start);
info.layout->SetParagraph(paragraph); info.layout->SetParagraph(paragraph);
} }
@ -151,8 +155,9 @@ TextDocumentLayout::InvalidateParagraphs(int32 start, int32 count)
} }
// Remove any extra paragraph layouts // Remove any extra paragraph layouts
while (paragraphs.CountItems() < fParagraphLayouts.CountItems()) while (fDocument->CountParagraphs()
fParagraphLayouts.Remove(fParagraphLayouts.CountItems() - 1); < static_cast<int32>(fParagraphLayouts.size()))
fParagraphLayouts.erase(fParagraphLayouts.end() - 1);
} }
@ -173,8 +178,9 @@ TextDocumentLayout::Height()
float height = 0.0f; float height = 0.0f;
if (fParagraphLayouts.CountItems() > 0) { if (fParagraphLayouts.size() > 0) {
const ParagraphLayoutInfo& lastLayout = fParagraphLayouts.LastItem(); const ParagraphLayoutInfo& lastLayout
= fParagraphLayouts[fParagraphLayouts.size() - 1];
height = lastLayout.y + lastLayout.layout->Height(); height = lastLayout.y + lastLayout.layout->Height();
} }
@ -188,9 +194,9 @@ TextDocumentLayout::Draw(BView* view, const BPoint& offset,
{ {
_ValidateLayout(); _ValidateLayout();
int layoutCount = fParagraphLayouts.CountItems(); int layoutCount = fParagraphLayouts.size();
for (int i = 0; i < layoutCount; i++) { for (int i = 0; i < layoutCount; i++) {
const ParagraphLayoutInfo& layout = fParagraphLayouts.ItemAtFast(i); const ParagraphLayoutInfo& layout = fParagraphLayouts[i];
BPoint location(offset.x, offset.y + layout.y); BPoint location(offset.x, offset.y + layout.y);
if (location.y > updateRect.bottom) if (location.y > updateRect.bottom)
break; break;
@ -207,10 +213,10 @@ TextDocumentLayout::LineIndexForOffset(int32 textOffset)
if (index >= 0) { if (index >= 0) {
int32 lineIndex = 0; int32 lineIndex = 0;
for (int32 i = 0; i < index; i++) { for (int32 i = 0; i < index; i++) {
lineIndex += fParagraphLayouts.ItemAtFast(i).layout->CountLines(); lineIndex += fParagraphLayouts[i].layout->CountLines();
} }
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(index); const ParagraphLayoutInfo& info = fParagraphLayouts[index];
return lineIndex + info.layout->LineIndexForOffset(textOffset); return lineIndex + info.layout->LineIndexForOffset(textOffset);
} }
@ -224,7 +230,7 @@ TextDocumentLayout::FirstOffsetOnLine(int32 lineIndex)
int32 paragraphOffset; int32 paragraphOffset;
int32 index = _ParagraphLayoutIndexForLineIndex(lineIndex, paragraphOffset); int32 index = _ParagraphLayoutIndexForLineIndex(lineIndex, paragraphOffset);
if (index >= 0) { if (index >= 0) {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(index); const ParagraphLayoutInfo& info = fParagraphLayouts[index];
return info.layout->FirstOffsetOnLine(lineIndex) + paragraphOffset; return info.layout->FirstOffsetOnLine(lineIndex) + paragraphOffset;
} }
@ -238,7 +244,7 @@ TextDocumentLayout::LastOffsetOnLine(int32 lineIndex)
int32 paragraphOffset; int32 paragraphOffset;
int32 index = _ParagraphLayoutIndexForLineIndex(lineIndex, paragraphOffset); int32 index = _ParagraphLayoutIndexForLineIndex(lineIndex, paragraphOffset);
if (index >= 0) { if (index >= 0) {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(index); const ParagraphLayoutInfo& info = fParagraphLayouts[index];
return info.layout->LastOffsetOnLine(lineIndex) + paragraphOffset; return info.layout->LastOffsetOnLine(lineIndex) + paragraphOffset;
} }
@ -253,9 +259,9 @@ TextDocumentLayout::CountLines()
int32 lineCount = 0; int32 lineCount = 0;
int32 count = fParagraphLayouts.CountItems(); int32 count = fParagraphLayouts.size();
for (int32 i = 0; i < count; i++) { for (int32 i = 0; i < count; i++) {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(i); const ParagraphLayoutInfo& info = fParagraphLayouts[i];
lineCount += info.layout->CountLines(); lineCount += info.layout->CountLines();
} }
@ -270,7 +276,7 @@ TextDocumentLayout::GetLineBounds(int32 lineIndex, float& x1, float& y1,
int32 paragraphOffset; int32 paragraphOffset;
int32 index = _ParagraphLayoutIndexForLineIndex(lineIndex, paragraphOffset); int32 index = _ParagraphLayoutIndexForLineIndex(lineIndex, paragraphOffset);
if (index >= 0) { if (index >= 0) {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(index); const ParagraphLayoutInfo& info = fParagraphLayouts[index];
info.layout->GetLineBounds(lineIndex, x1, y1, x2, y2); info.layout->GetLineBounds(lineIndex, x1, y1, x2, y2);
y1 += info.y; y1 += info.y;
y2 += info.y; y2 += info.y;
@ -290,7 +296,7 @@ TextDocumentLayout::GetTextBounds(int32 textOffset, float& x1, float& y1,
{ {
int32 index = _ParagraphLayoutIndexForOffset(textOffset); int32 index = _ParagraphLayoutIndexForOffset(textOffset);
if (index >= 0) { if (index >= 0) {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(index); const ParagraphLayoutInfo& info = fParagraphLayouts[index];
info.layout->GetTextBounds(textOffset, x1, y1, x2, y2); info.layout->GetTextBounds(textOffset, x1, y1, x2, y2);
y1 += info.y; y1 += info.y;
y2 += info.y; y2 += info.y;
@ -312,9 +318,9 @@ TextDocumentLayout::TextOffsetAt(float x, float y, bool& rightOfCenter)
int32 textOffset = 0; int32 textOffset = 0;
rightOfCenter = false; rightOfCenter = false;
int32 paragraphs = fParagraphLayouts.CountItems(); int32 paragraphs = fParagraphLayouts.size();
for (int32 i = 0; i < paragraphs; i++) { for (int32 i = 0; i < paragraphs; i++) {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(i); const ParagraphLayoutInfo& info = fParagraphLayouts[i];
if (y > info.y + info.layout->Height()) { if (y > info.y + info.layout->Height()) {
textOffset += info.layout->CountGlyphs(); textOffset += info.layout->CountGlyphs();
continue; continue;
@ -343,23 +349,28 @@ TextDocumentLayout::_ValidateLayout()
void void
TextDocumentLayout::_Init() TextDocumentLayout::_Init()
{ {
fParagraphLayouts.Clear(); fParagraphLayouts.clear();
if (!fDocument.IsSet()) if (!fDocument.IsSet())
return; return;
const ParagraphList& paragraphs = fDocument->Paragraphs(); int paragraphCount = fDocument->CountParagraphs();
int paragraphCount = paragraphs.CountItems();
for (int i = 0; i < paragraphCount; i++) { for (int i = 0; i < paragraphCount; i++) {
const Paragraph& paragraph = paragraphs.ItemAtFast(i); const Paragraph& paragraph = fDocument->ParagraphAtIndex(i);
ParagraphLayoutRef layout(new(std::nothrow) ParagraphLayout(paragraph), ParagraphLayoutRef layout(new(std::nothrow) ParagraphLayout(paragraph),
true); true);
if (!layout.IsSet() if (!layout.IsSet()) {
|| !fParagraphLayouts.Add(ParagraphLayoutInfo(0.0f, layout))) {
fprintf(stderr, "TextDocumentLayout::_Layout() - out of memory\n"); fprintf(stderr, "TextDocumentLayout::_Layout() - out of memory\n");
return; return;
} }
try {
fParagraphLayouts.push_back(ParagraphLayoutInfo(0.0f, layout));
}
catch (std::bad_alloc& ba) {
fprintf(stderr, "bad_alloc when inititalizing the text document "
"layout\n");
return;
}
} }
} }
@ -369,15 +380,15 @@ TextDocumentLayout::_Layout()
{ {
float y = 0.0f; float y = 0.0f;
int layoutCount = fParagraphLayouts.CountItems(); int layoutCount = fParagraphLayouts.size();
for (int i = 0; i < layoutCount; i++) { for (int i = 0; i < layoutCount; i++) {
ParagraphLayoutInfo info = fParagraphLayouts.ItemAtFast(i); ParagraphLayoutInfo info = fParagraphLayouts[i];
const ParagraphStyle& style = info.layout->Style(); const ParagraphStyle& style = info.layout->Style();
if (i > 0) if (i > 0)
y += style.SpacingTop(); y += style.SpacingTop();
fParagraphLayouts.Replace(i, ParagraphLayoutInfo(y, info.layout)); fParagraphLayouts[i] = ParagraphLayoutInfo(y, info.layout);
info.layout->SetWidth(fWidth); info.layout->SetWidth(fWidth);
y += info.layout->Height() + style.SpacingBottom(); y += info.layout->Height() + style.SpacingBottom();
@ -390,9 +401,9 @@ TextDocumentLayout::_ParagraphLayoutIndexForOffset(int32& textOffset)
{ {
_ValidateLayout(); _ValidateLayout();
int32 paragraphs = fParagraphLayouts.CountItems(); int32 paragraphs = fParagraphLayouts.size();
for (int32 i = 0; i < paragraphs - 1; i++) { for (int32 i = 0; i < paragraphs - 1; i++) {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(i); const ParagraphLayoutInfo& info = fParagraphLayouts[i];
int32 length = info.layout->CountGlyphs(); int32 length = info.layout->CountGlyphs();
if (textOffset >= length) { if (textOffset >= length) {
@ -404,7 +415,8 @@ TextDocumentLayout::_ParagraphLayoutIndexForOffset(int32& textOffset)
} }
if (paragraphs > 0) { if (paragraphs > 0) {
const ParagraphLayoutInfo& info = fParagraphLayouts.LastItem(); const ParagraphLayoutInfo& info
= fParagraphLayouts[fParagraphLayouts.size() - 1];
// Return last paragraph if the textOffset is still within or // Return last paragraph if the textOffset is still within or
// exactly behind the last valid offset in that paragraph. // exactly behind the last valid offset in that paragraph.
@ -423,9 +435,9 @@ TextDocumentLayout::_ParagraphLayoutIndexForLineIndex(int32& lineIndex,
_ValidateLayout(); _ValidateLayout();
paragraphOffset = 0; paragraphOffset = 0;
int32 paragraphs = fParagraphLayouts.CountItems(); int32 paragraphs = fParagraphLayouts.size();
for (int32 i = 0; i < paragraphs; i++) { for (int32 i = 0; i < paragraphs; i++) {
const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(i); const ParagraphLayoutInfo& info = fParagraphLayouts[i];
int32 lineCount = info.layout->CountLines(); int32 lineCount = info.layout->CountLines();
if (lineIndex >= lineCount) { if (lineIndex >= lineCount) {

View File

@ -63,9 +63,6 @@ public:
}; };
typedef List<ParagraphLayoutInfo, false> ParagraphLayoutList;
class TextDocumentLayout : public BReferenceable { class TextDocumentLayout : public BReferenceable {
public: public:
TextDocumentLayout(); TextDocumentLayout();
@ -125,7 +122,8 @@ private:
TextDocumentRef fDocument; TextDocumentRef fDocument;
TextListenerRef fTextListener; TextListenerRef fTextListener;
ParagraphLayoutList fParagraphLayouts; std::vector<ParagraphLayoutInfo>
fParagraphLayouts;
}; };

View File

@ -591,9 +591,9 @@ private:
return true; return true;
if (actions.size() != fPackageActions.size()) if (actions.size() != fPackageActions.size())
return true; return true;
if (fButtons.CountItems() != actions.size()) if (fButtons.CountItems() != static_cast<int32>(actions.size()))
return true; return true;
for (int i = 0; (i < actions.size()); i++) { for (int i = 0; i < static_cast<int32>(actions.size()); i++) {
if (actions[i]->Type() != fPackageActions[i]->Type()) if (actions[i]->Type() != fPackageActions[i]->Type())
return true; return true;
} }

View File

@ -1,6 +1,6 @@
/* /*
* Copyright 2014, Stephan Aßmus <superstippi@gmx.de>. * Copyright 2014, Stephan Aßmus <superstippi@gmx.de>.
* Copyright 2019-2020, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@ -854,8 +854,8 @@ UserLoginWindow::_UnpackCaptcha(BMessage& responsePayload, Captcha& captcha)
if (result == B_OK) if (result == B_OK)
result = resultMessage.FindString("pngImageDataBase64", &pngImageDataBase64); result = resultMessage.FindString("pngImageDataBase64", &pngImageDataBase64);
ssize_t encodedSize; ssize_t encodedSize = 0;
ssize_t decodedSize; ssize_t decodedSize = 0;
if (result == B_OK) { if (result == B_OK) {
encodedSize = pngImageDataBase64.Length(); encodedSize = pngImageDataBase64.Length();
decodedSize = (encodedSize * 3 + 3) / 4; decodedSize = (encodedSize * 3 + 3) / 4;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2020, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2019-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@ -484,7 +484,6 @@ UserUsageConditionsWindow::_ExpectedIntroductionTextHeight(
float insetBottom; float insetBottom;
introductionTextView->GetInsets(NULL, &insetTop, NULL, &insetBottom); introductionTextView->GetInsets(NULL, &insetTop, NULL, &insetBottom);
BSize introductionSize;
font_height fh; font_height fh;
be_plain_font->GetHeight(&fh); be_plain_font->GetHeight(&fh);
return ((fh.ascent + fh.descent + fh.leading) * LINES_INTRODUCTION_TEXT) return ((fh.ascent + fh.descent + fh.leading) * LINES_INTRODUCTION_TEXT)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017-2020, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2017-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@ -23,6 +23,11 @@ LoggingUrlProtocolListener::LoggingUrlProtocolListener(
} }
LoggingUrlProtocolListener::~LoggingUrlProtocolListener()
{
}
void void
LoggingUrlProtocolListener::BytesWritten(BUrlRequest* caller, LoggingUrlProtocolListener::BytesWritten(BUrlRequest* caller,
size_t bytesWritten) size_t bytesWritten)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>. * Copyright 2017-2021, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License. * All rights reserved. Distributed under the terms of the MIT License.
*/ */
@ -16,6 +16,7 @@ public:
LoggingUrlProtocolListener( LoggingUrlProtocolListener(
BString traceLoggingIdentifier, BString traceLoggingIdentifier,
bool traceLogging); bool traceLogging);
virtual ~LoggingUrlProtocolListener();
size_t ContentLength(); size_t ContentLength();

View File

@ -13,7 +13,6 @@
#include "ValidationUtilsTest.h" #include "ValidationUtilsTest.h"
#include "StorageUtilsTest.h" #include "StorageUtilsTest.h"
#include "TarArchiveServiceTest.h" #include "TarArchiveServiceTest.h"
#include "ListTest.h"
BTestSuite* BTestSuite*
@ -25,7 +24,6 @@ getTestSuite()
DumpExportRepositoryJsonListenerTest::AddTests(*suite); DumpExportRepositoryJsonListenerTest::AddTests(*suite);
ValidationFailureTest::AddTests(*suite); ValidationFailureTest::AddTests(*suite);
ValidationUtilsTest::AddTests(*suite); ValidationUtilsTest::AddTests(*suite);
ListTest::AddTests(*suite);
StorageUtilsTest::AddTests(*suite); StorageUtilsTest::AddTests(*suite);
TarArchiveServiceTest::AddTests(*suite); TarArchiveServiceTest::AddTests(*suite);

View File

@ -40,8 +40,6 @@ UnitTestLib haikudepottest.so :
DumpExportRepositoryJsonListener.cpp DumpExportRepositoryJsonListener.cpp
DumpExportRepositoryJsonListenerTest.cpp DumpExportRepositoryJsonListenerTest.cpp
ListTest.cpp
Logger.cpp Logger.cpp
StandardMetaData.cpp StandardMetaData.cpp

View File

@ -1,193 +0,0 @@
/*
* Copyright 2017-2018, Andrew Lindesay <apl@lindesay.co.nz>.
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "ListTest.h"
#include <stdio.h>
#include <AutoDeleter.h>
#include <Json.h>
#include <cppunit/TestCaller.h>
#include <cppunit/TestSuite.h>
#include "List.h"
ListTest::ListTest()
{
}
ListTest::~ListTest()
{
}
static int32 CompareStrings(const BString& a, const BString& b)
{
return a.Compare(b);
}
static int32 CompareWithContextString(const void* context, const BString& str)
{
const char* contextString = static_cast<const char*>(context);
return -1 * str.Compare(contextString);
}
/*! This tests the insertion of various letters into the list and the subsequent
search for those values later using a binary search.
*/
void
ListTest::TestBinarySearch()
{
List<BString, false> list(&CompareStrings, &CompareWithContextString);
BString tmp;
for(char c = 'a'; c <= 'z'; c++) {
tmp.SetToFormat("%c", c);
list.Add(tmp);
}
// ----------------------
int32 aIndex = list.Search("a");
int32 hIndex = list.Search("h");
int32 uIndex = list.Search("u");
int32 zIndex = list.Search("z");
int32 ampersandIndex = list.Search("&");
// ----------------------
CPPUNIT_ASSERT_EQUAL(0, aIndex);
CPPUNIT_ASSERT_EQUAL(7, hIndex);
CPPUNIT_ASSERT_EQUAL(20, uIndex);
CPPUNIT_ASSERT_EQUAL(25, zIndex);
CPPUNIT_ASSERT_EQUAL(-1, ampersandIndex);
}
/*! In this test, a number of letters are added into a list. Later a check is
made to ensure that the letters were added in order.
*/
void
ListTest::TestAddOrdered()
{
List<BString, false> list(&CompareStrings, NULL);
// ----------------------
list.Add(BString("p")); //1
list.Add(BString("o"));
list.Add(BString("n"));
list.Add(BString("s"));
list.Add(BString("b")); //5
list.Add(BString("y"));
list.Add(BString("r"));
list.Add(BString("d"));
list.Add(BString("i"));
list.Add(BString("k")); //10
list.Add(BString("t"));
list.Add(BString("e"));
list.Add(BString("a"));
list.Add(BString("u"));
list.Add(BString("z")); // 15
list.Add(BString("q"));
// ----------------------
CPPUNIT_ASSERT_EQUAL_MESSAGE("expected count of package infos",
16, list.CountItems());
CPPUNIT_ASSERT_EQUAL(BString("a"), list.ItemAt(0));
CPPUNIT_ASSERT_EQUAL(BString("b"), list.ItemAt(1));
CPPUNIT_ASSERT_EQUAL(BString("d"), list.ItemAt(2));
CPPUNIT_ASSERT_EQUAL(BString("e"), list.ItemAt(3));
CPPUNIT_ASSERT_EQUAL(BString("i"), list.ItemAt(4));
CPPUNIT_ASSERT_EQUAL(BString("k"), list.ItemAt(5));
CPPUNIT_ASSERT_EQUAL(BString("n"), list.ItemAt(6));
CPPUNIT_ASSERT_EQUAL(BString("o"), list.ItemAt(7));
CPPUNIT_ASSERT_EQUAL(BString("p"), list.ItemAt(8));
CPPUNIT_ASSERT_EQUAL(BString("q"), list.ItemAt(9));
CPPUNIT_ASSERT_EQUAL(BString("r"), list.ItemAt(10));
CPPUNIT_ASSERT_EQUAL(BString("s"), list.ItemAt(11));
CPPUNIT_ASSERT_EQUAL(BString("t"), list.ItemAt(12));
CPPUNIT_ASSERT_EQUAL(BString("u"), list.ItemAt(13));
CPPUNIT_ASSERT_EQUAL(BString("y"), list.ItemAt(14));
CPPUNIT_ASSERT_EQUAL(BString("z"), list.ItemAt(15));
}
/*! This test will add a number of letters to a list which has no ordering. The
letters should then appear in the list in the order of insertion.
*/
void
ListTest::TestAddUnordered()
{
List<BString, false> list;
// ----------------------
list.Add(BString("b"));
list.Add(BString("e"));
list.Add(BString("t"));
list.Add(BString("h"));
list.Add(BString("e"));
list.Add(BString("l"));
list.Add(BString("l"));
list.Add(BString("s"));
list.Add(BString("b"));
list.Add(BString("e"));
list.Add(BString("a"));
list.Add(BString("c"));
list.Add(BString("h"));
// ----------------------
CPPUNIT_ASSERT_EQUAL_MESSAGE("expected count of package infos",
13, list.CountItems());
CPPUNIT_ASSERT_EQUAL(BString("b"), list.ItemAt(0));
CPPUNIT_ASSERT_EQUAL(BString("e"), list.ItemAt(1));
CPPUNIT_ASSERT_EQUAL(BString("t"), list.ItemAt(2));
CPPUNIT_ASSERT_EQUAL(BString("h"), list.ItemAt(3));
CPPUNIT_ASSERT_EQUAL(BString("e"), list.ItemAt(4));
CPPUNIT_ASSERT_EQUAL(BString("l"), list.ItemAt(5));
CPPUNIT_ASSERT_EQUAL(BString("l"), list.ItemAt(6));
CPPUNIT_ASSERT_EQUAL(BString("s"), list.ItemAt(7));
CPPUNIT_ASSERT_EQUAL(BString("b"), list.ItemAt(8));
CPPUNIT_ASSERT_EQUAL(BString("e"), list.ItemAt(9));
CPPUNIT_ASSERT_EQUAL(BString("a"), list.ItemAt(10));
CPPUNIT_ASSERT_EQUAL(BString("c"), list.ItemAt(11));
CPPUNIT_ASSERT_EQUAL(BString("h"), list.ItemAt(12));
}
/*static*/ void
ListTest::AddTests(BTestSuite& parent)
{
CppUnit::TestSuite& suite = *new CppUnit::TestSuite(
"ListTest");
suite.addTest(
new CppUnit::TestCaller<ListTest>(
"ListTest::TestAddOrdered",
&ListTest::TestAddOrdered));
suite.addTest(
new CppUnit::TestCaller<ListTest>(
"ListTest::TestBinarySearch",
&ListTest::TestBinarySearch));
suite.addTest(
new CppUnit::TestCaller<ListTest>(
"ListTest::TestAddUnordered",
&ListTest::TestAddUnordered));
parent.addTest("ListTest", &suite);
}

View File

@ -1,26 +0,0 @@
/*
* Copyright 2017-2018, Andrew Lindesay <apl@lindesay.co.nz>
* Distributed under the terms of the MIT License.
*/
#ifndef LIST_TEST_H
#define LIST_TEST_H
#include <TestCase.h>
#include <TestSuite.h>
class ListTest : public CppUnit::TestCase {
public:
ListTest();
virtual ~ListTest();
void TestAddOrdered();
void TestBinarySearch();
void TestAddUnordered();
static void AddTests(BTestSuite& suite);
};
#endif // LIST_TEST_H