1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkData_DEFINED
9#define SkData_DEFINED
10
11#include <stdio.h>
12
13#include "SkRefCnt.h"
14
15class SkStream;
16
17/**
18 *  SkData holds an immutable data buffer. Not only is the data immutable,
19 *  but the actual ptr that is returned (by data() or bytes()) is guaranteed
20 *  to always be the same for the life of this instance.
21 */
22class SK_API SkData : public SkRefCnt {
23public:
24    /**
25     *  Returns the number of bytes stored.
26     */
27    size_t size() const { return fSize; }
28
29    bool isEmpty() const { return 0 == fSize; }
30
31    /**
32     *  Returns the ptr to the data.
33     */
34    const void* data() const { return fPtr; }
35
36    /**
37     *  Like data(), returns a read-only ptr into the data, but in this case
38     *  it is cast to uint8_t*, to make it easy to add an offset to it.
39     */
40    const uint8_t* bytes() const {
41        return reinterpret_cast<const uint8_t*>(fPtr);
42    }
43
44    /**
45     *  USE WITH CAUTION.
46     *  This call will assert that the refcnt is 1, as a precaution against modifying the
47     *  contents when another client/thread has access to the data.
48     */
49    void* writable_data() {
50        if (fSize) {
51            // only assert we're unique if we're not empty
52            SkASSERT(this->unique());
53        }
54        return fPtr;
55    }
56
57    /**
58     *  Helper to copy a range of the data into a caller-provided buffer.
59     *  Returns the actual number of bytes copied, after clamping offset and
60     *  length to the size of the data. If buffer is NULL, it is ignored, and
61     *  only the computed number of bytes is returned.
62     */
63    size_t copyRange(size_t offset, size_t length, void* buffer) const;
64
65    /**
66     *  Returns true if these two objects have the same length and contents,
67     *  effectively returning 0 == memcmp(...)
68     */
69    bool equals(const SkData* other) const;
70
71    /**
72     *  Function that, if provided, will be called when the SkData goes out
73     *  of scope, allowing for custom allocation/freeing of the data's contents.
74     */
75    typedef void (*ReleaseProc)(const void* ptr, void* context);
76
77    /**
78     *  Create a new dataref by copying the specified data
79     */
80    static SkData* NewWithCopy(const void* data, size_t length);
81
82    /**
83     *  Create a new data with uninitialized contents. The caller should call writable_data()
84     *  to write into the buffer, but this must be done before another ref() is made.
85     */
86    static SkData* NewUninitialized(size_t length);
87
88    /**
89     *  Create a new dataref by copying the specified c-string
90     *  (a null-terminated array of bytes). The returned SkData will have size()
91     *  equal to strlen(cstr) + 1. If cstr is NULL, it will be treated the same
92     *  as "".
93     */
94    static SkData* NewWithCString(const char cstr[]);
95
96    /**
97     *  Create a new dataref, taking the ptr as is, and using the
98     *  releaseproc to free it. The proc may be NULL.
99     */
100    static SkData* NewWithProc(const void* ptr, size_t length, ReleaseProc proc, void* context);
101
102    /**
103     *  Call this when the data parameter is already const and will outlive the lifetime of the
104     *  SkData. Suitable for with const globals.
105     */
106    static SkData* NewWithoutCopy(const void* data, size_t length) {
107        return NewWithProc(data, length, DummyReleaseProc, NULL);
108    }
109
110    /**
111     *  Create a new dataref from a pointer allocated by malloc. The Data object
112     *  takes ownership of that allocation, and will handling calling sk_free.
113     */
114    static SkData* NewFromMalloc(const void* data, size_t length);
115
116    /**
117     *  Create a new dataref the file with the specified path.
118     *  If the file cannot be opened, this returns NULL.
119     */
120    static SkData* NewFromFileName(const char path[]);
121
122    /**
123     *  Create a new dataref from a stdio FILE.
124     *  This does not take ownership of the FILE, nor close it.
125     *  The caller is free to close the FILE at its convenience.
126     *  The FILE must be open for reading only.
127     *  Returns NULL on failure.
128     */
129    static SkData* NewFromFILE(FILE* f);
130
131    /**
132     *  Create a new dataref from a file descriptor.
133     *  This does not take ownership of the file descriptor, nor close it.
134     *  The caller is free to close the file descriptor at its convenience.
135     *  The file descriptor must be open for reading only.
136     *  Returns NULL on failure.
137     */
138    static SkData* NewFromFD(int fd);
139
140    /**
141     *  Attempt to read size bytes into a SkData. If the read succeeds, return the data,
142     *  else return NULL. Either way the stream's cursor may have been changed as a result
143     *  of calling read().
144     */
145    static SkData* NewFromStream(SkStream*, size_t size);
146
147    /**
148     *  Create a new dataref using a subset of the data in the specified
149     *  src dataref.
150     */
151    static SkData* NewSubset(const SkData* src, size_t offset, size_t length);
152
153    /**
154     *  Returns a new empty dataref (or a reference to a shared empty dataref).
155     *  New or shared, the caller must see that unref() is eventually called.
156     */
157    static SkData* NewEmpty();
158
159private:
160    ReleaseProc fReleaseProc;
161    void*       fReleaseProcContext;
162    void*       fPtr;
163    size_t      fSize;
164
165    SkData(const void* ptr, size_t size, ReleaseProc, void* context);
166    explicit SkData(size_t size);   // inplace new/delete
167    virtual ~SkData();
168
169
170    // Objects of this type are sometimes created in a custom fashion using sk_malloc_throw and
171    // therefore must be sk_freed. We overload new to also call sk_malloc_throw so that memory
172    // can be unconditionally released using sk_free in an overloaded delete. Overloading regular
173    // new means we must also overload placement new.
174    void* operator new(size_t size) { return sk_malloc_throw(size); }
175    void* operator new(size_t, void* p) { return p; }
176    void operator delete(void* p) { sk_free(p); }
177
178    // Called the first time someone calls NewEmpty to initialize the singleton.
179    friend SkData* sk_new_empty_data();
180
181    // shared internal factory
182    static SkData* PrivateNewWithCopy(const void* srcOrNull, size_t length);
183
184    static void DummyReleaseProc(const void*, void*) {}
185
186    typedef SkRefCnt INHERITED;
187};
188
189/** Typedef of SkAutoTUnref<SkData> for automatically unref-ing a SkData. */
190typedef SkAutoTUnref<SkData> SkAutoDataUnref;
191
192#endif
193