aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/basetypes/MCData.cpp67
-rw-r--r--src/core/basetypes/MCData.h14
-rw-r--r--src/core/basetypes/MCDataMac.mm16
-rwxr-xr-xsrc/core/imap/MCIMAPSession.cpp8
4 files changed, 86 insertions, 19 deletions
diff --git a/src/core/basetypes/MCData.cpp b/src/core/basetypes/MCData.cpp
index 079344da..9c6d0cae 100644
--- a/src/core/basetypes/MCData.cpp
+++ b/src/core/basetypes/MCData.cpp
@@ -39,6 +39,25 @@ static int isPowerOfTwo (unsigned int x)
void Data::allocate(unsigned int length, bool force)
{
+ if (mExternallyAllocatedMemory) {
+ // We don't know how this memory was allocated.
+ // Possibly this memory is readonly.
+ // So we need fallback to malloc'ed implementation.
+
+ unsigned int bytes_len = 0;
+ char * bytes = NULL;
+ if (mBytes) {
+ bytes_len = mLength;
+ bytes = (char *) malloc(mLength);
+ memcpy(bytes, mBytes, mLength);
+ }
+
+ reset();
+ mBytes = bytes;
+ mLength = bytes_len;
+ mAllocated = bytes_len;
+ }
+
if (length <= mAllocated)
return;
@@ -62,37 +81,46 @@ void Data::allocate(unsigned int length, bool force)
void Data::reset()
{
- free(mBytes);
+ if (mExternallyAllocatedMemory) {
+ if (mBytes && mBytesDeallocator) {
+ mBytesDeallocator(mBytes, mLength);
+ }
+ } else {
+ free(mBytes);
+ }
+ init();
+}
+
+void Data::init()
+{
mAllocated = 0;
mLength = 0;
mBytes = NULL;
+ mExternallyAllocatedMemory = false;
+ mBytesDeallocator = NULL;
}
Data::Data()
{
- mBytes = NULL;
- reset();
+ init();
}
Data::Data(Data * otherData) : Object()
{
- mBytes = NULL;
- reset();
+ init();
appendData(otherData);
}
Data::Data(const char * bytes, unsigned int length)
{
- mBytes = NULL;
- reset();
+ init();
allocate(length, true);
appendBytes(bytes, length);
}
Data::Data(int capacity)
{
- mBytes = NULL;
- reset();
+ init();
allocate(capacity, true);
}
@@ -484,9 +512,19 @@ String * Data::charsetWithFilteredHTML(bool filterHTML, String * hintCharset)
#endif
}
+void Data::takeBytesOwnership(char * bytes, unsigned int length, BytesDeallocator bytesDeallocator)
+{
+ reset();
+ mBytes = bytes;
+ mLength = length;
+ mAllocated = length;
+ mExternallyAllocatedMemory = true;
+ mBytesDeallocator = bytesDeallocator;
+}
+
void Data::takeBytesOwnership(char * bytes, unsigned int length)
{
- free(mBytes);
+ reset();
mBytes = (char *) bytes;
mLength = length;
}
@@ -567,6 +605,10 @@ static size_t uudecode(char * text, size_t size)
return count;
}
+static void decodedPartDeallocator(char * decoded, unsigned int decoded_length) {
+ mailmime_decoded_part_free(decoded);
+};
+
Data * Data::decodedDataUsingEncoding(Encoding encoding)
{
const char * text;
@@ -606,8 +648,9 @@ Data * Data::decodedDataUsingEncoding(Encoding encoding)
cur_token = 0;
mailmime_part_parse(text, text_length, &cur_token,
mime_encoding, &decoded, &decoded_length);
- data = Data::dataWithBytes(decoded, (unsigned int) decoded_length);
- mailmime_decoded_part_free(decoded);
+
+ data = Data::data();
+ data->takeBytesOwnership(decoded, (unsigned int) decoded_length, decodedPartDeallocator);
return data;
}
case EncodingUUEncode:
diff --git a/src/core/basetypes/MCData.h b/src/core/basetypes/MCData.h
index 0bb1bc07..4151757e 100644
--- a/src/core/basetypes/MCData.h
+++ b/src/core/basetypes/MCData.h
@@ -16,7 +16,9 @@
namespace mailcore {
class String;
-
+
+ typedef void (*BytesDeallocator)(char * bytes, unsigned int length);
+
class MAILCORE_EXPORT Data : public Object {
public:
Data();
@@ -49,6 +51,13 @@ namespace mailcore {
public: // private
virtual String * charsetWithFilteredHTML(bool filterHTML, String * hintCharset = NULL);
+
+ /* Replace contents of Data instance with contents of a given bytes without extra copying.
+ Memory ownership transferred from client code to the Data instance.
+ Data destructor will call bytesDeallocator function for memory releasing.
+ */
+ void takeBytesOwnership(char * bytes, unsigned int length, BytesDeallocator bytesDeallocator);
+
#ifdef __APPLE__
virtual CFDataRef destructiveNSData();
#endif
@@ -66,7 +75,10 @@ namespace mailcore {
char * mBytes;
unsigned int mLength;
unsigned int mAllocated;
+ bool mExternallyAllocatedMemory;
+ BytesDeallocator mBytesDeallocator;
void allocate(unsigned int length, bool force = false);
+ void init();
void reset();
String * charsetWithFilteredHTMLWithoutHint(bool filterHTML);
void takeBytesOwnership(char * bytes, unsigned int length);
diff --git a/src/core/basetypes/MCDataMac.mm b/src/core/basetypes/MCDataMac.mm
index 8081b1f9..589e8b59 100644
--- a/src/core/basetypes/MCDataMac.mm
+++ b/src/core/basetypes/MCDataMac.mm
@@ -14,9 +14,17 @@ using namespace mailcore;
CFDataRef Data::destructiveNSData()
{
- NSData * result = [NSData dataWithBytesNoCopy:(void *) mBytes length:mLength];
- mBytes = NULL;
- mAllocated = 0;
- mLength = 0;
+ NSData * result;
+ if (mExternallyAllocatedMemory) {
+ BytesDeallocator deallocator = mBytesDeallocator;
+ result = [[[NSData alloc] initWithBytesNoCopy:mBytes length:mLength deallocator:^(void * bytes, NSUInteger length) {
+ if (deallocator) {
+ deallocator((char *)bytes, (unsigned int)length);
+ }
+ }] autorelease];
+ } else {
+ result = [NSData dataWithBytesNoCopy:(void *) mBytes length:mLength];
+ }
+ init();
return (CFDataRef) result;
}
diff --git a/src/core/imap/MCIMAPSession.cpp b/src/core/imap/MCIMAPSession.cpp
index c2cf43e6..fc06f505 100755
--- a/src/core/imap/MCIMAPSession.cpp
+++ b/src/core/imap/MCIMAPSession.cpp
@@ -2634,6 +2634,10 @@ Data * IMAPSession::fetchMessage(String * folder, bool identifier_is_uid, uint32
return data;
}
+static void nstringDeallocator(char * bytes, unsigned int length) {
+ mailimap_nstring_free(bytes);
+};
+
Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_uid,
uint32_t identifier, String * partID,
Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError)
@@ -2693,10 +2697,10 @@ Data * IMAPSession::fetchMessageAttachment(String * folder, bool identifier_is_u
return NULL;
}
- data = Data::dataWithBytes(text, (unsigned int) text_length);
+ data = Data::data();
+ data->takeBytesOwnership(text, (unsigned int) text_length, nstringDeallocator);
data = data->decodedDataUsingEncoding(encoding);
- mailimap_nstring_free(text);
* pError = ErrorNone;
return data;