summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Schleifer <js@heap.zone>2018-10-13 23:39:23 +0200
committerJonathan Schleifer <js@heap.zone>2018-10-13 23:39:23 +0200
commit7aeb90692680bb00802d9cb8b8f34d0f4b5a0b38 (patch)
tree3cfbce0384fda8db18375bba5d37c86cb21ff4c0
parent5a2030a9e063bd8edec7cb0beaa1cbfeec46d4cb (diff)
Add -[OFData subdataWithRange:]
-rw-r--r--src/OFData.h9
-rw-r--r--src/OFData.m19
-rw-r--r--src/OFMutableData.m11
-rw-r--r--tests/OFDataTests.m17
4 files changed, 55 insertions, 1 deletions
diff --git a/src/OFData.h b/src/OFData.h
index 3d95838f..f2f60b2b 100644
--- a/src/OFData.h
+++ b/src/OFData.h
@@ -42,6 +42,7 @@ enum {
unsigned char *_items;
size_t _count, _itemSize;
bool _freeWhenDone;
+ OFData *_parentData;
}
/*!
@@ -280,6 +281,14 @@ enum {
- (const void *)itemAtIndex: (size_t)index OF_RETURNS_INNER_POINTER;
/*!
+ * @brief Returns the data in the specified range as a new OFData.
+ *
+ * @param range The range of the data for the new data
+ * @return The data in the specified range as a new OFData
+ */
+- (OFData *)subdataWithRange: (of_range_t)range;
+
+/*!
* @brief Returns the range of the data.
*
* @param data The data to search for
diff --git a/src/OFData.m b/src/OFData.m
index d889fcc6..56c53b15 100644
--- a/src/OFData.m
+++ b/src/OFData.m
@@ -384,6 +384,8 @@ _references_to_categories_of_OFData(void)
if (_freeWhenDone)
free(_items);
+ [_parentData release];
+
[super dealloc];
}
@@ -500,6 +502,23 @@ _references_to_categories_of_OFData(void)
return hash;
}
+- (OFData *)subdataWithRange: (of_range_t)range
+{
+ OFData *ret;
+
+ if (range.length > SIZE_MAX - range.location ||
+ range.location + range.length > _count)
+ @throw [OFOutOfRangeException exception];
+
+ ret = [OFData dataWithItemsNoCopy: _items + (range.location * _itemSize)
+ itemSize: _itemSize
+ count: range.length
+ freeWhenDone: false];
+ ret->_parentData = [(_parentData != nil ? _parentData : self) copy];
+
+ return ret;
+}
+
- (OFString *)description
{
OFMutableString *ret = [OFMutableString stringWithString: @"<"];
diff --git a/src/OFMutableData.m b/src/OFMutableData.m
index 91ecacad..64bbc302 100644
--- a/src/OFMutableData.m
+++ b/src/OFMutableData.m
@@ -142,6 +142,17 @@
return self;
}
+- (OFData *)subdataWithRange: (of_range_t)range
+{
+ if (range.length > SIZE_MAX - range.location ||
+ range.location + range.length > _count)
+ @throw [OFOutOfRangeException exception];
+
+ return [OFData dataWithItems: _items + (range.location * _itemSize)
+ itemSize: _itemSize
+ count: range.length];
+}
+
- (void)addItem: (const void *)item
{
if (SIZE_MAX - _count < 1)
diff --git a/tests/OFDataTests.m b/tests/OFDataTests.m
index b7b6a363..7d4dca87 100644
--- a/tests/OFDataTests.m
+++ b/tests/OFDataTests.m
@@ -150,7 +150,7 @@ const char *str = "Hello!";
range: of_range(0, 1)])
EXPECT_EXCEPTION(
- @"-[rangeOfString:options:range:] failing on out of range",
+ @"-[rangeOfData:options:range:] failing on out of range",
OFOutOfRangeException,
[immutable rangeOfData: [OFData dataWithItems: ""
itemSize: 2
@@ -158,6 +158,21 @@ const char *str = "Hello!";
options: 0
range: of_range(8, 1)])
+ TEST(@"-[subdataWithRange:]",
+ [[immutable subdataWithRange: of_range(2, 4)]
+ isEqual: [OFData dataWithItems: "accdacaa"
+ itemSize: 2
+ count: 4]] &&
+ [[mutable subdataWithRange: of_range(2, 3)]
+ isEqual: [OFData dataWithItems: "cde"
+ count: 3]])
+
+ EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #1",
+ OFOutOfRangeException, [immutable subdataWithRange: of_range(7, 1)])
+
+ EXPECT_EXCEPTION(@"-[subdataWithRange:] failing on out of range #2",
+ OFOutOfRangeException, [mutable subdataWithRange: of_range(6, 1)])
+
TEST(@"-[MD5Hash]", [[mutable MD5Hash] isEqual: [@"abcde" MD5Hash]])
TEST(@"-[RIPEMD160Hash]", [[mutable RIPEMD160Hash]