From f934095ba93ea218eafe8492dc7e760de5a337cb Mon Sep 17 00:00:00 2001 From: achmizs Date: Tue, 22 Dec 2015 17:20:33 -0500 Subject: [PATCH] Initial commit --- NSData+SA_NSDataExtensions.h | 90 ++++++++++++++++++++++++++++++++++++ NSData+SA_NSDataExtensions.m | 78 +++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 NSData+SA_NSDataExtensions.h create mode 100644 NSData+SA_NSDataExtensions.m diff --git a/NSData+SA_NSDataExtensions.h b/NSData+SA_NSDataExtensions.h new file mode 100644 index 0000000..3515dc4 --- /dev/null +++ b/NSData+SA_NSDataExtensions.h @@ -0,0 +1,90 @@ +// +// NSData+SA_NSDataExtensions.h +// +// Copyright (c) 2015 Said Achmiz. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#import + +/** \category NSData+SA_NSDataExtensions + * @brief Adds several utility methods to NSData. + */ +@interface NSData (SA_NSDataExtensions) + +// NOTE on stripping nulls from the ends of byte arrays. +// +// If you strip a null from the end of an array which is something other than +// a null-terminated C string (such as, for example, the bytes representing a +// UTF-16 string), and thereby cause yourself difficulties, you have only +// yourself to blame. Be sure that you know what your NSData objects are +// supposed to contain! + +/** Returns YES if the last byte of the stored data is null, NO otherwise. + */ +@property (readonly, getter=isNullTerminated) BOOL nullTerminated; + +/** Returns the stored bytes as a null-terminated C string (byte array). + + If the stored data is already null-terminated, the returned pointer will + be a pointer to the bytes managed by the receiver. If it is not already + null-terminated, the returned pointer will point to bytes managed by a + copy of the receiver (and the bytes of the copy will be null-terminated). + */ +@property (readonly) const char *SA_terminatedCString; + +/** Returns data containing the stored bytes as a null-terminated C string + (byte array). + + If the stored data is already null-terminated, this method simply returns + the receiver. If it is not already null-terminated, this method returns a + reference to a fresh copy of the receiver (a copy that contains a + null-terminated byte array, of course). + */ +@property (readonly) NSData *SA_dataWithTerminatedCString; + +/** Returns the stored bytes as an non-null-terminated byte array. + + If the stored data was not null-terminated to begin with, the returned + pointer will be a pointer to the bytes managed by the receiver. If the + stored data was null-terminated, the returned pointer will point to bytes + managed by a copy of the receiver (and the bytes of the copy will not be + null-terminated; but see NOTE). + + NOTE: If the receiver's *last* byte is null, the bytes pointed to by the + returned pointer will have that null stripped; but if there are any more + null bytes prior to that last null, they will remain untouched! + */ +@property (readonly) const char *SA_unterminatedByteString; + +/** Returns data containing the stored bytes as a non-null-terminated byte + array. + + If the stored data was not null-terminated to begin with, this method simply + returns the receiver. If the stored data was null-terminated, this method + returns a reference to a fresh copy of the receiver (a copy that contains a + non-null-terminated byte array, of course; but see NOTE). + + NOTE: If the receiver's *last* byte is null, the bytes managed by the + returned object will have that null stripped; but if there are any more + null bytes prior to that last null, they will remain untouched! + */ +@property (readonly) NSData *SA_dataWithUnterminatedByteString; + +@end diff --git a/NSData+SA_NSDataExtensions.m b/NSData+SA_NSDataExtensions.m new file mode 100644 index 0000000..c1e8477 --- /dev/null +++ b/NSData+SA_NSDataExtensions.m @@ -0,0 +1,78 @@ +// +// NSData+SA_NSDataExtensions.h +// +// Copyright (c) 2015 Said Achmiz. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#import "NSData+SA_NSDataExtensions.h" + +@implementation NSData (SA_NSDataExtensions) + +-(BOOL)isNullTerminated +{ + return (((char*) self.bytes)[self.length - 1] == '\0'); +} + +-(const char *)SA_terminatedCString +{ + return self.SA_dataWithTerminatedCString.bytes; +} + +-(NSData *)SA_dataWithTerminatedCString +{ + if(self.length == 0) + { + return [NSData dataWithBytes:"\0" length:1]; + } + else if(self.isNullTerminated) + { + return self; + } + else + { + char* terminated_string_buffer = malloc(self.length + 1); + [self getBytes:terminated_string_buffer length:self.length]; + terminated_string_buffer[self.length] = '\0'; + + return [NSData dataWithBytesNoCopy:terminated_string_buffer length:self.length + 1 freeWhenDone:YES]; + } +} + +-(const char *)SA_unterminatedByteString +{ + return self.SA_dataWithUnterminatedByteString.bytes; +} + +-(NSData *)SA_dataWithUnterminatedByteString +{ + if(self.length == 0 || self.isNullTerminated == NO) + { + return self; + } + else + { + char* unterminated_string_buffer = malloc(self.length - 1); + [self getBytes:unterminated_string_buffer length:self.length - 1]; + + return [NSData dataWithBytesNoCopy:unterminated_string_buffer length:self.length - 1 freeWhenDone:YES]; + } +} + +@end