1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
63a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com */
73a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
83a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com#ifndef SkData_DEFINED
93a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com#define SkData_DEFINED
103a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
11da30055b296faa5a100e474e0406ef4296c14241reed@google.com#include "SkRefCnt.h"
123a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
139711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.orgstruct SkFILE;
149594da111dc1c36c1912eb61207aaa54c17ea550reedclass SkStream;
159711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org
163a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com/**
173a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com *  SkData holds an immutable data buffer. Not only is the data immutable,
183a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com *  but the actual ptr that is returned (by data() or bytes()) is guaranteed
193a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com *  to always be the same for the life of this instance.
203a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com */
21da30055b296faa5a100e474e0406ef4296c14241reed@google.comclass SK_API SkData : public SkRefCnt {
223a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.compublic:
2315e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com    SK_DECLARE_INST_COUNT(SkData)
2415e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
253a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
263a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Returns the number of bytes stored.
273a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
283a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    size_t size() const { return fSize; }
293a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
30dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com    bool isEmpty() const { return 0 == fSize; }
31dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com
323a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
333a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Returns the ptr to the data.
343a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
353a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    const void* data() const { return fPtr; }
363a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
373a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
383a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Like data(), returns a read-only ptr into the data, but in this case
393a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  it is cast to uint8_t*, to make it easy to add an offset to it.
403a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
413a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    const uint8_t* bytes() const {
423a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com        return reinterpret_cast<const uint8_t*>(fPtr);
433a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    }
443a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
453a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
4633a30503d76fdd989358cedd78445ba96bb809ddreed     *  USE WITH CAUTION.
4733a30503d76fdd989358cedd78445ba96bb809ddreed     *  This call will assert that the refcnt is 1, as a precaution against modifying the
4833a30503d76fdd989358cedd78445ba96bb809ddreed     *  contents when another client/thread has access to the data.
4933a30503d76fdd989358cedd78445ba96bb809ddreed     */
5033a30503d76fdd989358cedd78445ba96bb809ddreed    void* writable_data() {
5133a30503d76fdd989358cedd78445ba96bb809ddreed        if (fSize) {
5233a30503d76fdd989358cedd78445ba96bb809ddreed            // only assert we're unique if we're not empty
5333a30503d76fdd989358cedd78445ba96bb809ddreed            SkASSERT(this->unique());
5433a30503d76fdd989358cedd78445ba96bb809ddreed        }
5533a30503d76fdd989358cedd78445ba96bb809ddreed        return fPtr;
5633a30503d76fdd989358cedd78445ba96bb809ddreed    }
5733a30503d76fdd989358cedd78445ba96bb809ddreed
5833a30503d76fdd989358cedd78445ba96bb809ddreed    /**
593a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Helper to copy a range of the data into a caller-provided buffer.
603a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Returns the actual number of bytes copied, after clamping offset and
613a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  length to the size of the data. If buffer is NULL, it is ignored, and
623a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  only the computed number of bytes is returned.
633a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
643a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    size_t copyRange(size_t offset, size_t length, void* buffer) const;
653a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
663a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
67dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com     *  Returns true if these two objects have the same length and contents,
68dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com     *  effectively returning 0 == memcmp(...)
69dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com     */
70dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com    bool equals(const SkData* other) const;
71dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com
72dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com    /**
733a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Function that, if provided, will be called when the SkData goes out
743a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  of scope, allowing for custom allocation/freeing of the data.
753a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
763a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    typedef void (*ReleaseProc)(const void* ptr, size_t length, void* context);
77fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
783a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
793a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Create a new dataref by copying the specified data
803a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
813a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    static SkData* NewWithCopy(const void* data, size_t length);
82fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
83dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com    /**
8433a30503d76fdd989358cedd78445ba96bb809ddreed     *  Create a new data with uninitialized contents. The caller should call writable_data()
8533a30503d76fdd989358cedd78445ba96bb809ddreed     *  to write into the buffer, but this must be done before another ref() is made.
8633a30503d76fdd989358cedd78445ba96bb809ddreed     */
8733a30503d76fdd989358cedd78445ba96bb809ddreed    static SkData* NewUninitialized(size_t length);
8833a30503d76fdd989358cedd78445ba96bb809ddreed
8933a30503d76fdd989358cedd78445ba96bb809ddreed    /**
90dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com     *  Create a new dataref by copying the specified c-string
91fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com     *  (a null-terminated array of bytes). The returned SkData will have size()
92fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com     *  equal to strlen(cstr) + 1. If cstr is NULL, it will be treated the same
93fd59d1200073604c0a5dafe14edbb6f3833e1c3dreed@google.com     *  as "".
94dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com     */
95dbc936dff3357f74fc60e124d912a2179b909b0dreed@google.com    static SkData* NewWithCString(const char cstr[]);
96fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
973a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
983a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Create a new dataref, taking the data ptr as is, and using the
993a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  releaseproc to free it. The proc may be NULL.
1003a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
10133a30503d76fdd989358cedd78445ba96bb809ddreed    static SkData* NewWithProc(const void* data, size_t length, ReleaseProc proc, void* context);
10233a30503d76fdd989358cedd78445ba96bb809ddreed
10333a30503d76fdd989358cedd78445ba96bb809ddreed    /**
10433a30503d76fdd989358cedd78445ba96bb809ddreed     *  Call this when the data parameter is already const and will outlive the lifetime of the
10533a30503d76fdd989358cedd78445ba96bb809ddreed     *  SkData. Suitable for with const globals.
10633a30503d76fdd989358cedd78445ba96bb809ddreed     */
10733a30503d76fdd989358cedd78445ba96bb809ddreed    static SkData* NewWithoutCopy(const void* data, size_t length) {
10833a30503d76fdd989358cedd78445ba96bb809ddreed        return NewWithProc(data, length, NULL, NULL);
10933a30503d76fdd989358cedd78445ba96bb809ddreed    }
1103a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
1113a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
1121f1db4cc5b62fc74efc01a4c92cbc1f7bddce241reed@google.com     *  Create a new dataref from a pointer allocated by malloc. The Data object
1131f1db4cc5b62fc74efc01a4c92cbc1f7bddce241reed@google.com     *  takes ownership of that allocation, and will handling calling sk_free.
1148a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com     */
1158a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    static SkData* NewFromMalloc(const void* data, size_t length);
1167fb5373fb76951b7e8b534f04d508dd51e21be6eskia.committer@gmail.com
117792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org    /**
118792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org     *  Create a new dataref the file with the specified path.
119792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org     *  If the file cannot be opened, this returns NULL.
120792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org     */
121792bbd14c63f217f2de0e6b2f8df99acb1928eeamike@reedtribe.org    static SkData* NewFromFileName(const char path[]);
1227fb5373fb76951b7e8b534f04d508dd51e21be6eskia.committer@gmail.com
1238a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com    /**
1249711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org     *  Create a new dataref from a SkFILE.
1259711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org     *  This does not take ownership of the SkFILE, nor close it.
12611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com     *  The caller is free to close the SkFILE at its convenience.
1279711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org     *  The SkFILE must be open for reading only.
1289711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org     *  Returns NULL on failure.
129e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com     */
1309711e446676e6bf84b3fff916fd1d7537933a110commit-bot@chromium.org    static SkData* NewFromFILE(SkFILE* f);
1318eaddb0089a170760e157646192813bd940c26e7skia.committer@gmail.com
132e1575aa21619e252f6c6514317041c32d00ce5a6reed@google.com    /**
13311c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com     *  Create a new dataref from a file descriptor.
13411c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com     *  This does not take ownership of the file descriptor, nor close it.
13511c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com     *  The caller is free to close the file descriptor at its convenience.
13611c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com     *  The file descriptor must be open for reading only.
13711c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com     *  Returns NULL on failure.
13811c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com     */
13911c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com    static SkData* NewFromFD(int fd);
14011f2b444500d552031fcae0b381a0770600400fdskia.committer@gmail.com
14111c9a55afd95078d14ab8cd7c1c5c0032af2a498bungeman@google.com    /**
1429594da111dc1c36c1912eb61207aaa54c17ea550reed     *  Attempt to read size bytes into a SkData. If the read succeeds, return the data,
1439594da111dc1c36c1912eb61207aaa54c17ea550reed     *  else return NULL. Either way the stream's cursor may have been changed as a result
1449594da111dc1c36c1912eb61207aaa54c17ea550reed     *  of calling read().
1459594da111dc1c36c1912eb61207aaa54c17ea550reed     */
1469594da111dc1c36c1912eb61207aaa54c17ea550reed    static SkData* NewFromStream(SkStream*, size_t size);
1479594da111dc1c36c1912eb61207aaa54c17ea550reed
1489594da111dc1c36c1912eb61207aaa54c17ea550reed    /**
1493a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Create a new dataref using a subset of the data in the specified
1503a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  src dataref.
1513a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
1523a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    static SkData* NewSubset(const SkData* src, size_t offset, size_t length);
1533a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
1543a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    /**
1553a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  Returns a new empty dataref (or a reference to a shared empty dataref).
1563a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     *  New or shared, the caller must see that unref() is eventually called.
1573a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com     */
1583a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    static SkData* NewEmpty();
1593a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
1603a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.comprivate:
1613a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    ReleaseProc fReleaseProc;
1623a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    void*       fReleaseProcContext;
1633a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
16433a30503d76fdd989358cedd78445ba96bb809ddreed    void*       fPtr;
1653a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    size_t      fSize;
1663a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
1673a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com    SkData(const void* ptr, size_t size, ReleaseProc, void* context);
16833a30503d76fdd989358cedd78445ba96bb809ddreed    SkData(size_t size);   // inplace new/delete
16959f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.com    virtual ~SkData();
17059f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.com
17133a30503d76fdd989358cedd78445ba96bb809ddreed    virtual void internal_dispose() const SK_OVERRIDE;
17233a30503d76fdd989358cedd78445ba96bb809ddreed
1731f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org    // Called the first time someone calls NewEmpty to initialize the singleton.
17497de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    static SkData* NewEmptyImpl();
17597de357270e54be53acb17e1cb4b4d5e25bacc01commit-bot@chromium.org    static void DeleteEmpty(SkData*);
1761f81fd6546c111e21bc665657e976b9d842192dfcommit-bot@chromium.org
17733a30503d76fdd989358cedd78445ba96bb809ddreed    // shared internal factory
17833a30503d76fdd989358cedd78445ba96bb809ddreed    static SkData* PrivateNewWithCopy(const void* srcOrNull, size_t length);
17933a30503d76fdd989358cedd78445ba96bb809ddreed
180da30055b296faa5a100e474e0406ef4296c14241reed@google.com    typedef SkRefCnt INHERITED;
1813a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com};
1823a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com
1836f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.com/** Typedef of SkAutoTUnref<SkData> for automatically unref-ing a SkData. */
1846f4cf2a19553b69d5bb10c5cd1005706a9fc6e22bungeman@google.comtypedef SkAutoTUnref<SkData> SkAutoDataUnref;
1858a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com
1863a31ac1cf5d7d37da5a77ce18c43a62bf0781154reed@google.com#endif
187