netwerk/cache/nsCacheMetaData.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/cache/nsCacheMetaData.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,162 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + *
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "nsCacheMetaData.h"
    1.11 +#include "nsICacheEntryDescriptor.h"
    1.12 +
    1.13 +const char *
    1.14 +nsCacheMetaData::GetElement(const char * key)
    1.15 +{
    1.16 +    const char * data = mBuffer;
    1.17 +    const char * limit = mBuffer + mMetaSize;
    1.18 +
    1.19 +    while (data < limit) {
    1.20 +        // Point to the value part
    1.21 +        const char * value = data + strlen(data) + 1;
    1.22 +        NS_ABORT_IF_FALSE(value < limit, "Cache Metadata corrupted");
    1.23 +        if (strcmp(data, key) == 0)
    1.24 +            return value;
    1.25 +
    1.26 +        // Skip value part
    1.27 +        data = value + strlen(value) + 1;
    1.28 +    }
    1.29 +    NS_ABORT_IF_FALSE(data == limit, "Metadata corrupted");
    1.30 +    return nullptr;
    1.31 +}
    1.32 +
    1.33 +
    1.34 +nsresult
    1.35 +nsCacheMetaData::SetElement(const char * key,
    1.36 +                            const char * value)
    1.37 +{
    1.38 +    const uint32_t keySize = strlen(key) + 1;
    1.39 +    char * pos = (char *)GetElement(key);
    1.40 +
    1.41 +    if (!value) {
    1.42 +        // No value means remove the key/value pair completely, if existing
    1.43 +        if (pos) {
    1.44 +            uint32_t oldValueSize = strlen(pos) + 1;
    1.45 +            uint32_t offset = pos - mBuffer;
    1.46 +            uint32_t remainder = mMetaSize - (offset + oldValueSize);
    1.47 +
    1.48 +            memmove(pos - keySize, pos + oldValueSize, remainder);
    1.49 +            mMetaSize -= keySize + oldValueSize;
    1.50 +        }
    1.51 +        return NS_OK;
    1.52 +    }
    1.53 +
    1.54 +    const uint32_t valueSize = strlen(value) + 1;
    1.55 +    uint32_t newSize = mMetaSize + valueSize;
    1.56 +    if (pos) {
    1.57 +        const uint32_t oldValueSize = strlen(pos) + 1;
    1.58 +        const uint32_t offset = pos - mBuffer;
    1.59 +        const uint32_t remainder = mMetaSize - (offset + oldValueSize);
    1.60 +
    1.61 +        // Update the value in place
    1.62 +        newSize -= oldValueSize;
    1.63 +        nsresult rv = EnsureBuffer(newSize);
    1.64 +        NS_ENSURE_SUCCESS(rv, rv);
    1.65 +
    1.66 +        // Move the remainder to the right place
    1.67 +        pos = mBuffer + offset;
    1.68 +        memmove(pos + valueSize, pos + oldValueSize, remainder);
    1.69 +    } else {
    1.70 +        // allocate new meta data element
    1.71 +        newSize += keySize;
    1.72 +        nsresult rv = EnsureBuffer(newSize);
    1.73 +        NS_ENSURE_SUCCESS(rv, rv);
    1.74 +
    1.75 +        // Add after last element
    1.76 +        pos = mBuffer + mMetaSize;
    1.77 +        memcpy(pos, key, keySize);
    1.78 +        pos += keySize;
    1.79 +    }
    1.80 +
    1.81 +    // Update value
    1.82 +    memcpy(pos, value, valueSize);
    1.83 +    mMetaSize = newSize;
    1.84 +
    1.85 +    return NS_OK;
    1.86 +}
    1.87 +
    1.88 +nsresult
    1.89 +nsCacheMetaData::FlattenMetaData(char * buffer, uint32_t bufSize)
    1.90 +{
    1.91 +    if (mMetaSize > bufSize) {
    1.92 +        NS_ERROR("buffer size too small for meta data.");
    1.93 +        return NS_ERROR_OUT_OF_MEMORY;
    1.94 +    }
    1.95 +
    1.96 +    memcpy(buffer, mBuffer, mMetaSize);
    1.97 +    return NS_OK;
    1.98 +}
    1.99 +
   1.100 +nsresult
   1.101 +nsCacheMetaData::UnflattenMetaData(const char * data, uint32_t size)
   1.102 +{
   1.103 +    if (data && size) {
   1.104 +        // Check if the metadata ends with a zero byte.
   1.105 +        if (data[size-1] != '\0') {
   1.106 +            NS_ERROR("Cache MetaData is not null terminated");
   1.107 +            return NS_ERROR_ILLEGAL_VALUE;
   1.108 +        }
   1.109 +        // Check that there are an even number of zero bytes
   1.110 +        // to match the pattern { key \0 value \0 }
   1.111 +        bool odd = false;
   1.112 +        for (uint32_t i = 0; i < size; i++) {
   1.113 +            if (data[i] == '\0') 
   1.114 +                odd = !odd;
   1.115 +        }
   1.116 +        if (odd) {
   1.117 +            NS_ERROR("Cache MetaData is malformed");
   1.118 +            return NS_ERROR_ILLEGAL_VALUE;
   1.119 +        }
   1.120 +
   1.121 +        nsresult rv = EnsureBuffer(size);
   1.122 +        NS_ENSURE_SUCCESS(rv, rv);
   1.123 +
   1.124 +        memcpy(mBuffer, data, size);
   1.125 +        mMetaSize = size;
   1.126 +    }
   1.127 +    return NS_OK;
   1.128 +}
   1.129 +
   1.130 +nsresult
   1.131 +nsCacheMetaData::VisitElements(nsICacheMetaDataVisitor * visitor)
   1.132 +{
   1.133 +    const char * data = mBuffer;
   1.134 +    const char * limit = mBuffer + mMetaSize;
   1.135 +
   1.136 +    while (data < limit) {
   1.137 +        const char * key = data;
   1.138 +        // Skip key part
   1.139 +        data += strlen(data) + 1;
   1.140 +        NS_ABORT_IF_FALSE(data < limit, "Metadata corrupted");
   1.141 +        bool keepGoing;
   1.142 +        nsresult rv = visitor->VisitMetaDataElement(key, data, &keepGoing);
   1.143 +        if (NS_FAILED(rv) || !keepGoing)
   1.144 +            return NS_OK;
   1.145 +
   1.146 +        // Skip value part
   1.147 +        data += strlen(data) + 1;
   1.148 +    }
   1.149 +    NS_ABORT_IF_FALSE(data == limit, "Metadata corrupted");
   1.150 +    return NS_OK;
   1.151 +}
   1.152 +
   1.153 +nsresult
   1.154 +nsCacheMetaData::EnsureBuffer(uint32_t bufSize)
   1.155 +{
   1.156 +    if (mBufferSize < bufSize) {
   1.157 +        char * buf = (char *)moz_realloc(mBuffer, bufSize);
   1.158 +        if (!buf) {
   1.159 +            return NS_ERROR_OUT_OF_MEMORY;
   1.160 +        }
   1.161 +        mBuffer = buf;
   1.162 +        mBufferSize = bufSize;
   1.163 +    }
   1.164 +    return NS_OK;
   1.165 +}        

mercurial