summaryrefslogtreecommitdiff
path: root/Magick++/lib/Blob.cpp
blob: 96b97ec6f528c8a4ec44c18110ad3087ebe90045 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// This may look like C code, but it is really -*- C++ -*-
//
// Copyright Bob Friesenhahn, 1999, 2000, 2001, 2002, 2004
//
// Implementation of Blob
//

#define MAGICKCORE_IMPLEMENTATION  1
#define MAGICK_PLUSPLUS_IMPLEMENTATION 1

#include "Magick++/Include.h"
#include "Magick++/Blob.h"
#include "Magick++/BlobRef.h"

#include <string.h>

//
// Implementation of Magick::Blob
//

// Default constructor
Magick::Blob::Blob ( void )
  : _blobRef(new Magick::BlobRef( 0, 0 ))
{
}

// Construct with data
Magick::Blob::Blob ( const void* data_, size_t length_ )
  : _blobRef(new Magick::BlobRef( data_, length_ ))
{
}

// Copy constructor (reference counted)
Magick::Blob::Blob ( const Magick::Blob& blob_ )
  : _blobRef(blob_._blobRef)
{
  // Increase reference count
  Lock( &_blobRef->_mutexLock );
  ++_blobRef->_refCount;
}

// Destructor (reference counted)
Magick::Blob::~Blob ()
{
  bool doDelete = false;
  {
    Lock( &_blobRef->_mutexLock );
    if ( --_blobRef->_refCount == 0 )
      doDelete = true;
  }

  if ( doDelete )
    {
      // Delete old blob reference with associated data
      delete _blobRef;
    }
  _blobRef=0;
}

// Assignment operator (reference counted)
Magick::Blob& Magick::Blob::operator= ( const Magick::Blob& blob_ )
{
  if(this != &blob_)
    {
      {
        Lock( &blob_._blobRef->_mutexLock );
        ++blob_._blobRef->_refCount;
      }
      bool doDelete = false;
      {
        Lock( &_blobRef->_mutexLock );
        if ( --_blobRef->_refCount == 0 )
          doDelete = true;
      }
      if ( doDelete )
        {
          delete _blobRef;
        }
      _blobRef = blob_._blobRef;
    }
  return *this;
}

// Update object contents from Base64-encoded string representation.
void Magick::Blob::base64 ( const std::string base64_ )
{
  size_t length;

  unsigned char *decoded =
    Base64Decode( base64_.c_str(), &length );

  if(decoded)
    updateNoCopy( static_cast<void*>(decoded), length,
                  Magick::Blob::MallocAllocator );
}

// Return Base64-encoded string representation.
std::string Magick::Blob::base64 ( void )
{
  size_t encoded_length = 0;

  char *encoded =
    Base64Encode(static_cast<const unsigned char*>(data()), length(), &encoded_length);

  if(encoded)
    {
      std::string result(encoded,encoded_length);
      encoded=(char *) RelinquishMagickMemory(encoded);
      return result;
    }

  return std::string();
}

// Update object contents, making a copy of the supplied data.
// Any existing data in the object is deallocated.
void Magick::Blob::update ( const void* data_, size_t length_ )
{
  bool doDelete = false;
  {
    Lock( &_blobRef->_mutexLock );
    if ( --_blobRef->_refCount == 0 )
      doDelete = true;
  }
  if ( doDelete )
    {
      // Delete old blob reference with associated data
      delete _blobRef;
    }

  _blobRef = new Magick::BlobRef( data_, length_ );
}

// Update object contents, using supplied pointer directly (no copy)
// Any existing data in the object is deallocated.  The user must
// ensure that the pointer supplied is not deleted or otherwise
// modified after it has been supplied to this method.
void Magick::Blob::updateNoCopy ( void* data_, size_t length_,
                                  Magick::Blob::Allocator allocator_  )
{
  bool doDelete = false;
  {
    Lock( &_blobRef->_mutexLock );
    if ( --_blobRef->_refCount == 0 )
      doDelete = true;
  }
  if ( doDelete )
    {
      // Delete old blob reference with associated data
      delete _blobRef;
    }
  _blobRef = new Magick::BlobRef( 0, 0 );
  _blobRef->_data   = data_;
  _blobRef->_length = length_;
  _blobRef->_allocator = allocator_;
}

// Obtain pointer to data
const void* Magick::Blob::data( void ) const
{
  return _blobRef->_data;
}

// Obtain data length
size_t Magick::Blob::length( void ) const
{
  return _blobRef->_length;
}