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.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8dde0956375e87027df2fdd80d430dd819c217aacreed@google.com#include "SkReader32.h"
9fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com#include "SkString.h"
1019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org#include "SkWriter32.h"
11fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com
12fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com/*
13fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com *  Strings are stored as: length[4-bytes] + string_data + '\0' + pad_to_mul_4
14fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com */
15dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
16dde0956375e87027df2fdd80d430dd819c217aacreed@google.comconst char* SkReader32::readString(size_t* outLen) {
171ac99c890b8afe957385a7625fd3b759f31be249commit-bot@chromium.org    size_t len = this->readU32();
18fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com    const void* ptr = this->peek();
19fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com
2019382421b916aab00be7265815ba4e2690adf2c9commit-bot@chromium.org    // skip over the string + '\0' and then pad to a multiple of 4
21fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com    size_t alignedSize = SkAlign4(len + 1);
22dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    this->skip(alignedSize);
23dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
24dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    if (outLen) {
25dde0956375e87027df2fdd80d430dd819c217aacreed@google.com        *outLen = len;
26dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    }
27dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    return (const char*)ptr;
28dde0956375e87027df2fdd80d430dd819c217aacreed@google.com}
29dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
30fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.comsize_t SkReader32::readIntoString(SkString* copy) {
31fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com    size_t len;
32fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com    const char* ptr = this->readString(&len);
33fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com    if (copy) {
34fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com        copy->set(ptr, len);
35fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com    }
36fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com    return len;
37fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com}
38fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com
39dde0956375e87027df2fdd80d430dd819c217aacreed@google.comvoid SkWriter32::writeString(const char str[], size_t len) {
4047fa13640b7c8615aa7aee0d5b1d63a7bd6ed44ecommit-bot@chromium.org    if (NULL == str) {
410038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com        str = "";
420038c12f337b7037ef698e2723099c7e3b19c4camtklein@google.com        len = 0;
4347fa13640b7c8615aa7aee0d5b1d63a7bd6ed44ecommit-bot@chromium.org    }
44dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    if ((long)len < 0) {
45dde0956375e87027df2fdd80d430dd819c217aacreed@google.com        len = strlen(str);
46dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    }
47536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org
48536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    // [ 4 byte len ] [ str ... ] [1 - 4 \0s]
49536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    uint32_t* ptr = this->reservePad(sizeof(uint32_t) + len + 1);
50f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org    *ptr = SkToU32(len);
51536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    char* chars = (char*)(ptr + 1);
52536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    memcpy(chars, str, len);
53536ac5e20c2ec2008993c0677ba8cbc5ae0f34cfcommit-bot@chromium.org    chars[len] = '\0';
54dde0956375e87027df2fdd80d430dd819c217aacreed@google.com}
55dde0956375e87027df2fdd80d430dd819c217aacreed@google.com
56dde0956375e87027df2fdd80d430dd819c217aacreed@google.comsize_t SkWriter32::WriteStringSize(const char* str, size_t len) {
57dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    if ((long)len < 0) {
58dde0956375e87027df2fdd80d430dd819c217aacreed@google.com        SkASSERT(str);
59dde0956375e87027df2fdd80d430dd819c217aacreed@google.com        len = strlen(str);
60dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    }
61fd0ffcf486a239d65b586bd638e5aaca907244dereed@google.com    const size_t lenBytes = 4;    // we use 4 bytes to record the length
62dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    // add 1 since we also write a terminating 0
63dde0956375e87027df2fdd80d430dd819c217aacreed@google.com    return SkAlign4(lenBytes + len + 1);
64dde0956375e87027df2fdd80d430dd819c217aacreed@google.com}
65046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org
66046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.orgvoid SkWriter32::growToAtLeast(size_t size) {
67a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org    const bool wasExternal = (fExternal != NULL) && (fData == fExternal);
68a87b21cd0041bac0d96b6836ac6e71a2dbcd4e10commit-bot@chromium.org
69ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    fCapacity = 4096 + SkTMax(size, fCapacity + (fCapacity / 2));
70ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    fInternal.realloc(fCapacity);
71ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org    fData = fInternal.get();
72ca21a00c736d05686c84ab874ce6a49008da6a76commit-bot@chromium.org
73046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    if (wasExternal) {
74046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        // we were external, so copy in the data
75046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org        memcpy(fData, fExternal, fUsed);
76046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org    }
77c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org}
78c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.org
79c30dcb9b128887c7e16afe32fdf35105cc42380bcommit-bot@chromium.orgSkData* SkWriter32::snapshotAsData() const {
804f358fc269077219c18f30f4752e3678a15c222amtklein    return SkData::NewWithCopy(fData, fUsed);
81046f1f6ff4b2b3f4571a9562e74f41e82419a4a1commit-bot@chromium.org}
82