OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * |
| 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are |
| 6 * met: |
| 7 * |
| 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. |
| 14 * * Neither the name of Google Inc. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. |
| 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ |
| 30 |
| 31 #include "config.h" |
| 32 #include "BlobItem.h" |
| 33 |
| 34 #include "FileSystem.h" |
| 35 #include "UUID.h" |
| 36 |
| 37 namespace WebCore { |
| 38 |
| 39 #if ENABLE(BLOB_SLICE) |
| 40 static const double invalidModificationTime = 0; |
| 41 |
| 42 double getFileSnapshotModificationTime(const String& path) |
| 43 { |
| 44 // FIXME: synchronized file call |
| 45 time_t modificationTime; |
| 46 if (getFileModificationTime(path, modificationTime)) |
| 47 return static_cast<double>(modificationTime); |
| 48 return invalidModificationTime; |
| 49 } |
| 50 #endif // ENABLE(BLOB_SLICE) |
| 51 |
| 52 // DataBlobItem ---------------------------------------------------------------- |
| 53 |
| 54 #if ENABLE(BLOB_SLICE) |
| 55 PassRefPtr<BlobItem> DataBlobItem::slice(long long start, long long length) |
| 56 { |
| 57 ASSERT(start >= 0 && length >= 0); |
| 58 ASSERT(static_cast<unsigned long long>(start) < size()); |
| 59 if (!start && size() <= static_cast<unsigned long long>(length)) |
| 60 return this; |
| 61 if (static_cast<unsigned long long>(start + length) > size()) |
| 62 length = size() - start; |
| 63 return DataRangeBlobItem::create(this, start, length); |
| 64 } |
| 65 #endif // ENABLE(BLOB_SLICE) |
| 66 |
| 67 // FileBlobItem ---------------------------------------------------------------- |
| 68 |
| 69 PassRefPtr<BlobItem> FileBlobItem::create(const String& path) |
| 70 { |
| 71 return adoptRef(static_cast<BlobItem*>(new FileBlobItem(path))); |
| 72 } |
| 73 |
| 74 FileBlobItem::FileBlobItem(const String& path) |
| 75 : m_path(path) |
| 76 , m_fileName(pathGetFileName(m_path)) |
| 77 { |
| 78 } |
| 79 |
| 80 unsigned long long FileBlobItem::size() const |
| 81 { |
| 82 // FIXME: synchronized file call |
| 83 long long size; |
| 84 if (!getFileSize(m_path, size)) |
| 85 return 0; |
| 86 return static_cast<unsigned long long>(size); |
| 87 } |
| 88 |
| 89 #if ENABLE(BLOB_SLICE) |
| 90 PassRefPtr<BlobItem> FileBlobItem::slice(long long start, long long length) |
| 91 { |
| 92 ASSERT(start >= 0 && length >= 0); |
| 93 ASSERT(static_cast<unsigned long long>(start) < size()); |
| 94 if (!start && size() <= static_cast<unsigned long long>(length)) |
| 95 return this; |
| 96 const FileRangeBlobItem* fileRangeItem = toFileRangeBlobItem(); |
| 97 double modificationTime = fileRangeItem ? fileRangeItem->snapshotModificatio
nTime() : getFileSnapshotModificationTime(path()); |
| 98 return FileRangeBlobItem::create(path(), start, length, modificationTime); |
| 99 } |
| 100 #endif // ENABLE(BLOB_SLICE) |
| 101 |
| 102 // StringBlobItem -------------------------------------------------------------- |
| 103 |
| 104 PassRefPtr<BlobItem> StringBlobItem::create(const String& text, LineEnding endin
g, TextEncoding encoding) |
| 105 { |
| 106 return adoptRef(static_cast<BlobItem*>(new StringBlobItem(text, ending, enco
ding))); |
| 107 } |
| 108 |
| 109 PassRefPtr<BlobItem> StringBlobItem::create(const CString& text) |
| 110 { |
| 111 return adoptRef(static_cast<BlobItem*>(new StringBlobItem(text))); |
| 112 } |
| 113 |
| 114 StringBlobItem::StringBlobItem(const String& text, LineEnding ending, TextEncodi
ng encoding) |
| 115 : m_data(StringBlobItem::convertToCString(text, ending, encoding)) |
| 116 { |
| 117 } |
| 118 |
| 119 StringBlobItem::StringBlobItem(const CString& text) |
| 120 : m_data(text) |
| 121 { |
| 122 } |
| 123 |
| 124 CString StringBlobItem::convertToCString(const String& text, LineEnding ending,
TextEncoding encoding) |
| 125 { |
| 126 CString from = encoding.encode(text.characters(), text.length(), EntitiesFor
Unencodables); |
| 127 CString result = from; |
| 128 |
| 129 if (ending == EndingTransparent) |
| 130 return result; |
| 131 |
| 132 const char* endingChars = (ending == EndingCRLF) ? "\r\n" : ((ending == Endi
ngCR) ? "\r" : "\n"); |
| 133 |
| 134 int endingLength = (ending == EndingCRLF) ? 2 : 1; |
| 135 int needFix = 0; |
| 136 |
| 137 // Calculate the final length. |
| 138 int calculatedLength = from.length(); |
| 139 const char* p = from.data(); |
| 140 while (char c = *p++) { |
| 141 if (c == '\r') { |
| 142 // Safe to look ahead because of trailing '\0'. |
| 143 if (*p == '\n' && ending != EndingCRLF) { |
| 144 calculatedLength += (endingLength - 2); |
| 145 ++needFix; |
| 146 } else if (ending != EndingCR) { |
| 147 calculatedLength += (endingLength - 1); |
| 148 ++needFix; |
| 149 } |
| 150 } else if (c == '\n' && ending != EndingLF) { |
| 151 calculatedLength += (endingLength - 1); |
| 152 ++needFix; |
| 153 } |
| 154 } |
| 155 |
| 156 if (!needFix) |
| 157 return result; |
| 158 |
| 159 // Convert the endings and create a data buffer. |
| 160 p = from.data(); |
| 161 char* q; |
| 162 result = CString::newUninitialized(calculatedLength, q); |
| 163 while (char c = *p++) { |
| 164 if (c == '\r') { |
| 165 if (*p == '\n' && ending != EndingCRLF) { |
| 166 memcpy(q, endingChars, endingLength); |
| 167 q += endingLength; |
| 168 } else if (*p != '\n' && ending != EndingCR) { |
| 169 memcpy(q, endingChars, endingLength); |
| 170 q += endingLength; |
| 171 } |
| 172 } else if (c == '\n' && ending != EndingLF) { |
| 173 memcpy(q, endingChars, endingLength); |
| 174 q += endingLength; |
| 175 } else { |
| 176 // Leave other characters alone. |
| 177 *q++ = c; |
| 178 } |
| 179 } |
| 180 return result; |
| 181 } |
| 182 |
| 183 // ByteArrayBlobItem ---------------------------------------------------------- |
| 184 |
| 185 PassRefPtr<BlobItem> ByteArrayBlobItem::create(const char* data, size_t size) |
| 186 { |
| 187 return adoptRef(static_cast<BlobItem*>(new ByteArrayBlobItem(data, size))); |
| 188 } |
| 189 |
| 190 ByteArrayBlobItem::ByteArrayBlobItem(const char* data, size_t size) |
| 191 { |
| 192 m_bytesArray.append(data, size); |
| 193 } |
| 194 |
| 195 #if ENABLE(BLOB_SLICE) |
| 196 |
| 197 // DataRangeBlobItem ----------------------------------------------------------- |
| 198 |
| 199 PassRefPtr<BlobItem> DataRangeBlobItem::create(PassRefPtr<DataBlobItem> item, lo
ng long start, long long length) |
| 200 { |
| 201 return adoptRef(static_cast<BlobItem*>(new DataRangeBlobItem(item, start, le
ngth))); |
| 202 } |
| 203 |
| 204 DataRangeBlobItem::DataRangeBlobItem(PassRefPtr<DataBlobItem> item, long long st
art, long long length) |
| 205 : m_length(length) |
| 206 { |
| 207 const DataRangeBlobItem* rangeItem = m_item->toDataRangeBlobItem(); |
| 208 if (rangeItem) { |
| 209 m_item = rangeItem->m_item; |
| 210 m_start = start + rangeItem->m_start; |
| 211 ASSERT(!m_item->toDataRangeBlobItem()); |
| 212 ASSERT(static_cast<unsigned long long>(m_start + m_length) <= m_item->si
ze()); |
| 213 } else { |
| 214 m_item = item; |
| 215 m_start = start; |
| 216 } |
| 217 } |
| 218 |
| 219 const char* DataRangeBlobItem::data() const |
| 220 { |
| 221 return m_item->data() + m_start; |
| 222 } |
| 223 |
| 224 // FileRangeBlobItem ----------------------------------------------------------- |
| 225 |
| 226 PassRefPtr<BlobItem> FileRangeBlobItem::create(const String& path, long long sta
rt, long long length, double snapshotModificationTime) |
| 227 { |
| 228 return adoptRef(static_cast<BlobItem*>(new FileRangeBlobItem(path, start, le
ngth, snapshotModificationTime))); |
| 229 } |
| 230 |
| 231 FileRangeBlobItem::FileRangeBlobItem(const String& path, long long start, long l
ong length, double modificationTime) |
| 232 : FileBlobItem(path) |
| 233 , m_start(start) |
| 234 , m_length(length) |
| 235 , m_snapshotModificationTime(modificationTime) |
| 236 { |
| 237 m_uniqueName = "Blob" + createCanonicalUUIDString(); |
| 238 m_uniqueName.replace("-", ""); // For safty, remove '-' from the filename sn
ce some servers may not like it. |
| 239 } |
| 240 |
| 241 #endif // ENABLE(BLOB_SLICE) |
| 242 |
| 243 } // namespace WebCore |
OLD | NEW |