core/AVSMap.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | /* | ||
| 3 | This program is free software; you can redistribute it and /or modify | ||
| 4 | it under the terms of the GNU General Public License as published by | ||
| 5 | the Free Software Foundation. | ||
| 6 | |||
| 7 | This program is distributed in the hope that it will be useful, | ||
| 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the | ||
| 10 | GNU General Public License for more details. | ||
| 11 | |||
| 12 | You should have received a copy of the GNU General Public License | ||
| 13 | along with this program; if not, write to the Free Software | ||
| 14 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 15 | |||
| 16 | Helper structures for frame properties a.k.a VSMap. | ||
| 17 | Based on VapourSynth API4, copyright (c) Fredrik Mellbin | ||
| 18 | |||
| 19 | */ | ||
| 20 | #include <map> | ||
| 21 | #include <mutex> | ||
| 22 | #include <string> | ||
| 23 | #include "avisynth.h" | ||
| 24 | #include <atomic> | ||
| 25 | #include <vector> | ||
| 26 | #include <memory> | ||
| 27 | #include <cassert> | ||
| 28 | |||
| 29 | // VS node ~ Avisynth clip, VSMap-AVSMap | ||
| 30 | // See also in Avisynth.cpp | ||
| 31 | |||
| 32 | // INTRUSIVE_PTR_H | ||
| 33 | |||
| 34 | #include <algorithm> | ||
| 35 | |||
| 36 | template<typename T> | ||
| 37 | class vs_intrusive_ptr { | ||
| 38 | private: | ||
| 39 | T* obj; | ||
| 40 | public: | ||
| 41 | 1963 | vs_intrusive_ptr(T* ptr = nullptr, bool add_ref = false) noexcept { | |
| 42 | 1963 | obj = ptr; | |
| 43 |
2/8vs_intrusive_ptr<VSArrayBase>::vs_intrusive_ptr(VSArrayBase*, bool):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 222 times.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
vs_intrusive_ptr<VSMapStorage>::vs_intrusive_ptr(VSMapStorage*, bool):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 1741 times.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
|
1963 | if (add_ref && obj) |
| 44 | ✗ | obj->add_ref(); | |
| 45 | 1963 | } | |
| 46 | |||
| 47 | 244 | vs_intrusive_ptr(const vs_intrusive_ptr& ptr) noexcept { | |
| 48 | 244 | obj = ptr.obj; | |
| 49 |
1/4vs_intrusive_ptr<VSArrayBase>::vs_intrusive_ptr(vs_intrusive_ptr<VSArrayBase> const&):
✓ Branch 2 → 3 taken 244 times.
✗ Branch 2 → 4 not taken.
vs_intrusive_ptr<VSMapStorage>::vs_intrusive_ptr(vs_intrusive_ptr<VSMapStorage> const&):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
|
244 | if (obj) |
| 50 | 244 | obj->add_ref(); | |
| 51 | 244 | } | |
| 52 | |||
| 53 | vs_intrusive_ptr(vs_intrusive_ptr&& ptr) noexcept { | ||
| 54 | obj = ptr.obj; | ||
| 55 | ptr.obj = nullptr; | ||
| 56 | } | ||
| 57 | |||
| 58 | 2207 | ~vs_intrusive_ptr() noexcept { | |
| 59 |
2/4vs_intrusive_ptr<VSArrayBase>::~vs_intrusive_ptr():
✓ Branch 2 → 3 taken 466 times.
✗ Branch 2 → 4 not taken.
vs_intrusive_ptr<VSMapStorage>::~vs_intrusive_ptr():
✓ Branch 2 → 3 taken 1741 times.
✗ Branch 2 → 4 not taken.
|
2207 | if (obj) |
| 60 | 2207 | obj->release(); | |
| 61 | 2207 | } | |
| 62 | |||
| 63 | 801 | vs_intrusive_ptr& operator=(vs_intrusive_ptr const& ptr) noexcept { | |
| 64 |
2/4vs_intrusive_ptr<VSArrayBase>::operator=(vs_intrusive_ptr<VSArrayBase> const&):
✓ Branch 2 → 3 taken 19 times.
✗ Branch 2 → 4 not taken.
vs_intrusive_ptr<VSMapStorage>::operator=(vs_intrusive_ptr<VSMapStorage> const&):
✓ Branch 2 → 3 taken 782 times.
✗ Branch 2 → 4 not taken.
|
801 | if (obj) |
| 65 | 801 | obj->release(); | |
| 66 | 801 | obj = ptr.obj; | |
| 67 |
2/4vs_intrusive_ptr<VSArrayBase>::operator=(vs_intrusive_ptr<VSArrayBase> const&):
✓ Branch 4 → 5 taken 19 times.
✗ Branch 4 → 6 not taken.
vs_intrusive_ptr<VSMapStorage>::operator=(vs_intrusive_ptr<VSMapStorage> const&):
✓ Branch 4 → 5 taken 782 times.
✗ Branch 4 → 6 not taken.
|
801 | if (obj) |
| 68 | 801 | obj->add_ref(); | |
| 69 | 801 | return *this; | |
| 70 | } | ||
| 71 | |||
| 72 | 2409 | T* operator->() const noexcept { | |
| 73 | 2409 | return obj; | |
| 74 | } | ||
| 75 | |||
| 76 | 115 | T& operator*() const noexcept { | |
| 77 | 115 | return *obj; | |
| 78 | } | ||
| 79 | |||
| 80 | operator bool() const noexcept { | ||
| 81 | return !!obj; | ||
| 82 | } | ||
| 83 | |||
| 84 | 282 | T* get() const noexcept { | |
| 85 | 282 | return obj; | |
| 86 | } | ||
| 87 | |||
| 88 | void reset() noexcept { | ||
| 89 | if (obj) { | ||
| 90 | obj->release(); | ||
| 91 | obj = nullptr; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | void swap(vs_intrusive_ptr& ptr) noexcept { | ||
| 96 | std::swap(obj, ptr.obj); | ||
| 97 | } | ||
| 98 | }; | ||
| 99 | |||
| 100 | #define AVS_NOEXCEPT noexcept | ||
| 101 | |||
| 102 | // enums for frame property functions | ||
| 103 | |||
| 104 | // VS: typedef enum VSPropertyType | ||
| 105 | typedef enum AVSPropertyType { | ||
| 106 | PROPERTYTYPE_UNSET = 0, // ptUnset = 0, | ||
| 107 | PROPERTYTYPE_INT = 1, // ptInt = 1, | ||
| 108 | PROPERTYTYPE_FLOAT = 2, // ptFloat = 2, | ||
| 109 | PROPERTYTYPE_DATA = 3, // ptData = 3, | ||
| 110 | // ptFunction = 4, // Avisynth: functions not supported here | ||
| 111 | PROPERTYTYPE_CLIP = 5, // ptVideoNode = 5, | ||
| 112 | // ptAudioNode = 6, // Avisynth: no special audio clip | ||
| 113 | PROPERTYTYPE_FRAME = 7, // ptVideoFrame = 7, | ||
| 114 | // ptAudioFrame = 8 // Avisynth: no special audio frame | ||
| 115 | } AVSPropertyType; | ||
| 116 | |||
| 117 | class VSArrayBase { | ||
| 118 | protected: | ||
| 119 | std::atomic<long> refcount; | ||
| 120 | AVSPropertyType ftype; | ||
| 121 | size_t fsize = 0; | ||
| 122 | 222 | explicit VSArrayBase(AVSPropertyType type) : refcount(1), ftype(type) {} | |
| 123 | 222 | virtual ~VSArrayBase() {} | |
| 124 | public: | ||
| 125 | 153 | AVSPropertyType type() const { | |
| 126 | 153 | return ftype; | |
| 127 | } | ||
| 128 | |||
| 129 | 279 | size_t size() const { | |
| 130 | 279 | return fsize; | |
| 131 | } | ||
| 132 | |||
| 133 | 1 | bool unique() const noexcept { | |
| 134 | 1 | return (refcount == 1); | |
| 135 | } | ||
| 136 | |||
| 137 | 263 | void add_ref() noexcept { | |
| 138 | 263 | ++refcount; | |
| 139 | 263 | } | |
| 140 | |||
| 141 | 485 | void release() noexcept { | |
| 142 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 485 times.
|
485 | assert(refcount > 0); |
| 143 |
2/2✓ Branch 6 → 7 taken 222 times.
✓ Branch 6 → 9 taken 263 times.
|
485 | if (--refcount == 0) |
| 144 |
1/2✓ Branch 7 → 8 taken 222 times.
✗ Branch 7 → 9 not taken.
|
222 | delete this; |
| 145 | 485 | } | |
| 146 | |||
| 147 | virtual VSArrayBase* copy() const noexcept = 0; | ||
| 148 | }; | ||
| 149 | |||
| 150 | typedef vs_intrusive_ptr<VSArrayBase> PVSArrayBase; | ||
| 151 | |||
| 152 | template<typename T, AVSPropertyType propType> | ||
| 153 | class VSArray final : public VSArrayBase { | ||
| 154 | private: | ||
| 155 | T singleData = {}; | ||
| 156 | std::vector<T> data; | ||
| 157 | public: | ||
| 158 | 222 | explicit VSArray() noexcept : VSArrayBase(propType) {} | |
| 159 | |||
| 160 | ✗ | explicit VSArray(const VSArray& other) noexcept : VSArrayBase(other.ftype) { | |
| 161 | ✗ | fsize = other.fsize; | |
| 162 | ✗ | if (fsize == 1) | |
| 163 | ✗ | singleData = other.singleData; | |
| 164 | ✗ | else if (fsize > 1) | |
| 165 | ✗ | data = other.data; | |
| 166 | ✗ | } | |
| 167 | |||
| 168 | ✗ | explicit VSArray(const T* val, size_t count) noexcept : VSArrayBase(propType) { // only enable for POD types | |
| 169 | ✗ | fsize = count; | |
| 170 | ✗ | if (count == 1) { | |
| 171 | ✗ | singleData = *val; | |
| 172 | } | ||
| 173 | else { | ||
| 174 | ✗ | data.resize(count); | |
| 175 | ✗ | memcpy(data.data(), val, sizeof(T) * count); | |
| 176 | } | ||
| 177 | ✗ | } | |
| 178 | |||
| 179 | ✗ | virtual VSArrayBase* copy() const noexcept { | |
| 180 | ✗ | return new VSArray(*this); | |
| 181 | } | ||
| 182 | |||
| 183 | ✗ | const T* getDataPointer() const noexcept { // only enable for POD types | |
| 184 | ✗ | if (fsize == 1) | |
| 185 | ✗ | return &singleData; | |
| 186 | else | ||
| 187 | ✗ | return data.data(); | |
| 188 | } | ||
| 189 | |||
| 190 | 223 | void push_back(const T& val) noexcept { | |
| 191 |
3/10VSArray<PVideoFrame, (AVSPropertyType)7>::push_back(PVideoFrame const&):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
VSArray<PClip, (AVSPropertyType)5>::push_back(PClip const&):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
VSArray<VSMapData, (AVSPropertyType)3>::push_back(VSMapData const&):
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 1 time.
VSArray<double, (AVSPropertyType)2>::push_back(double const&):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
VSArray<long, (AVSPropertyType)1>::push_back(long const&):
✓ Branch 2 → 3 taken 221 times.
✗ Branch 2 → 4 not taken.
|
223 | if (fsize == 0) { |
| 192 | 222 | singleData = val; | |
| 193 | } | ||
| 194 |
1/10VSArray<PVideoFrame, (AVSPropertyType)7>::push_back(PVideoFrame const&):
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 10 not taken.
VSArray<PClip, (AVSPropertyType)5>::push_back(PClip const&):
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 10 not taken.
VSArray<VSMapData, (AVSPropertyType)3>::push_back(VSMapData const&):
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 10 not taken.
VSArray<double, (AVSPropertyType)2>::push_back(double const&):
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 10 not taken.
VSArray<long, (AVSPropertyType)1>::push_back(long const&):
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 10 not taken.
|
1 | else if (fsize == 1) { |
| 195 | 1 | data.reserve(8); | |
| 196 | 2 | data.push_back(std::move(singleData)); | |
| 197 | 1 | data.push_back(val); | |
| 198 | } | ||
| 199 | else { | ||
| 200 | ✗ | if (data.capacity() == data.size()) | |
| 201 | ✗ | data.reserve(data.capacity() * 2); | |
| 202 | ✗ | data.push_back(val); | |
| 203 | } | ||
| 204 | 223 | fsize++; | |
| 205 | 223 | } | |
| 206 | |||
| 207 | 151 | const T& at(size_t pos) const noexcept { | |
| 208 |
2/10VSArray<PVideoFrame, (AVSPropertyType)7>::at(unsigned long) const:
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
VSArray<PClip, (AVSPropertyType)5>::at(unsigned long) const:
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
VSArray<VSMapData, (AVSPropertyType)3>::at(unsigned long) const:
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
VSArray<double, (AVSPropertyType)2>::at(unsigned long) const:
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
VSArray<long, (AVSPropertyType)1>::at(unsigned long) const:
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 150 times.
|
151 | assert(pos < fsize); |
| 209 |
2/10VSArray<PVideoFrame, (AVSPropertyType)7>::at(unsigned long) const:
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
VSArray<PClip, (AVSPropertyType)5>::at(unsigned long) const:
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
VSArray<VSMapData, (AVSPropertyType)3>::at(unsigned long) const:
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
VSArray<double, (AVSPropertyType)2>::at(unsigned long) const:
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
VSArray<long, (AVSPropertyType)1>::at(unsigned long) const:
✓ Branch 4 → 5 taken 150 times.
✗ Branch 4 → 6 not taken.
|
151 | if (fsize == 1) |
| 210 | 150 | return singleData; | |
| 211 | else | ||
| 212 | 1 | return data.at(pos); | |
| 213 | } | ||
| 214 | }; | ||
| 215 | |||
| 216 | // variant types | ||
| 217 | class VSMapData { | ||
| 218 | public: | ||
| 219 | AVSPropDataTypeHint typeHint; | ||
| 220 | std::string data; | ||
| 221 | }; | ||
| 222 | |||
| 223 | typedef VSArray<int64_t, AVSPropertyType::PROPERTYTYPE_INT> VSIntArray; // ptInt | ||
| 224 | typedef VSArray<double, AVSPropertyType::PROPERTYTYPE_FLOAT> VSFloatArray; // ptFloat | ||
| 225 | typedef VSArray<VSMapData, AVSPropertyType::PROPERTYTYPE_DATA> VSDataArray; // ptData | ||
| 226 | typedef VSArray<PClip, AVSPropertyType::PROPERTYTYPE_CLIP> VSVideoNodeArray; // ptVideoNode | ||
| 227 | typedef VSArray<PVideoFrame, AVSPropertyType::PROPERTYTYPE_FRAME> VSVideoFrameArray; // ptVideoFrame | ||
| 228 | //typedef VSArray<PFunction, ptFunction> VSFunctionArray; | ||
| 229 | |||
| 230 | |||
| 231 | typedef std::vector<int64_t> IntList; | ||
| 232 | typedef std::vector<double> FloatList; | ||
| 233 | typedef std::vector<VSMapData> DataList; | ||
| 234 | typedef std::vector<PClip> ClipList; | ||
| 235 | typedef std::vector<PVideoFrame> FrameList; | ||
| 236 | //typedef std::vector<PFunction> FuncList; | ||
| 237 | |||
| 238 | |||
| 239 | class VSMapStorage { | ||
| 240 | private: | ||
| 241 | std::atomic<long> refcount; | ||
| 242 | public: | ||
| 243 | std::map<std::string, PVSArrayBase> data; | ||
| 244 | bool error; | ||
| 245 | |||
| 246 | 1626 | explicit VSMapStorage() : refcount(1), error(false) {} | |
| 247 | |||
| 248 | 115 | explicit VSMapStorage(const VSMapStorage& s) : refcount(1), data(s.data), error(s.error) { | |
| 249 | 115 | } | |
| 250 | |||
| 251 | 6 | void clear() noexcept { | |
| 252 | 6 | data.clear(); | |
| 253 | 6 | error = false; | |
| 254 | 6 | } | |
| 255 | |||
| 256 | 344 | bool unique() noexcept { | |
| 257 | 344 | return (refcount == 1); | |
| 258 | }; | ||
| 259 | |||
| 260 | 782 | void add_ref() noexcept { | |
| 261 | 782 | ++refcount; | |
| 262 | 782 | } | |
| 263 | |||
| 264 | 2523 | void release() noexcept { | |
| 265 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2523 times.
|
2523 | assert(refcount > 0); |
| 266 |
2/2✓ Branch 6 → 7 taken 1741 times.
✓ Branch 6 → 10 taken 782 times.
|
2523 | if (--refcount == 0) |
| 267 |
1/2✓ Branch 7 → 8 taken 1741 times.
✗ Branch 7 → 10 not taken.
|
1741 | delete this; |
| 268 | 2523 | } | |
| 269 | }; | ||
| 270 | |||
| 271 | typedef vs_intrusive_ptr<VSMapStorage> PVSMapStorage; | ||
| 272 | |||
| 273 | // This one is referenced in avisynth.h. | ||
| 274 | // For avoiding dual plugin name collisions, renamed VSMap->AVSMap | ||
| 275 | struct AVSMap { | ||
| 276 | private: | ||
| 277 | PVSMapStorage data; | ||
| 278 | public: | ||
| 279 |
4/12✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1583 times.
✓ Branch 4 → 5 taken 1583 times.
✗ Branch 4 → 11 not taken.
✓ Branch 7 → 8 taken 1583 times.
✗ Branch 7 → 10 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 1583 times.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 14 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
|
1583 | AVSMap(const AVSMap* map = nullptr) : data(map ? map->data : new VSMapStorage()) { |
| 280 | 1583 | } | |
| 281 | |||
| 282 | 624 | AVSMap& operator=(const AVSMap& map) { | |
| 283 | 624 | data = map.data; | |
| 284 | 624 | return *this; | |
| 285 | } | ||
| 286 | |||
| 287 | 295 | bool detach() { | |
| 288 |
2/2✓ Branch 4 → 5 taken 115 times.
✓ Branch 4 → 14 taken 180 times.
|
295 | if (!data->unique()) { |
| 289 |
3/8✓ Branch 5 → 6 taken 115 times.
✗ Branch 5 → 19 not taken.
✓ Branch 7 → 8 taken 115 times.
✗ Branch 7 → 16 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 115 times.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
|
115 | data = new VSMapStorage(*data); |
| 290 | 115 | return true; | |
| 291 | } | ||
| 292 | 180 | return false; | |
| 293 | } | ||
| 294 | |||
| 295 | 369 | VSArrayBase* find(const std::string& key) const { | |
| 296 |
1/2✓ Branch 3 → 4 taken 369 times.
✗ Branch 3 → 14 not taken.
|
369 | auto it = data->data.find(key); |
| 297 |
2/2✓ Branch 7 → 8 taken 88 times.
✓ Branch 7 → 9 taken 281 times.
|
369 | return (it == data->data.end()) ? nullptr : it->second.get(); |
| 298 | } | ||
| 299 | |||
| 300 | 1 | VSArrayBase* detach(const std::string& key) { | |
| 301 |
1/2✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 26 not taken.
|
1 | detach(); |
| 302 |
1/2✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 26 not taken.
|
1 | auto it = data->data.find(key); |
| 303 |
1/2✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 23 not taken.
|
1 | if (it != data->data.end()) { |
| 304 |
1/2✗ Branch 12 → 13 not taken.
✓ Branch 12 → 21 taken 1 time.
|
1 | if (!it->second->unique()) |
| 305 | ✗ | it->second = it->second->copy(); | |
| 306 | 1 | return it->second.get(); | |
| 307 | } | ||
| 308 | ✗ | return nullptr; | |
| 309 | } | ||
| 310 | |||
| 311 | 122 | bool erase(const std::string& key) { | |
| 312 |
1/2✓ Branch 3 → 4 taken 122 times.
✗ Branch 3 → 18 not taken.
|
122 | auto it = data->data.find(key); |
| 313 |
2/2✓ Branch 7 → 8 taken 72 times.
✓ Branch 7 → 15 taken 50 times.
|
122 | if (it != data->data.end()) { |
| 314 |
3/4✓ Branch 8 → 9 taken 72 times.
✗ Branch 8 → 18 not taken.
✓ Branch 9 → 10 taken 70 times.
✓ Branch 9 → 12 taken 2 times.
|
72 | if (detach()) |
| 315 |
1/2✓ Branch 11 → 12 taken 70 times.
✗ Branch 11 → 18 not taken.
|
70 | it = data->data.find(key); |
| 316 |
1/2✓ Branch 13 → 14 taken 72 times.
✗ Branch 13 → 18 not taken.
|
72 | data->data.erase(it); |
| 317 | 72 | return true; | |
| 318 | } | ||
| 319 | 50 | return false; | |
| 320 | } | ||
| 321 | |||
| 322 | 222 | void insert(const std::string& key, VSArrayBase* val) { | |
| 323 |
1/2✓ Branch 2 → 3 taken 222 times.
✗ Branch 2 → 23 not taken.
|
222 | detach(); |
| 324 |
1/2✓ Branch 4 → 5 taken 222 times.
✗ Branch 4 → 23 not taken.
|
222 | auto it = data->data.find(key); |
| 325 |
2/2✓ Branch 8 → 9 taken 19 times.
✓ Branch 8 → 14 taken 203 times.
|
222 | if (it != data->data.end()) { |
| 326 | 19 | it->second = val; | |
| 327 | } | ||
| 328 | else { | ||
| 329 |
2/4✓ Branch 15 → 16 taken 203 times.
✗ Branch 15 → 22 not taken.
✓ Branch 16 → 17 taken 203 times.
✗ Branch 16 → 20 not taken.
|
203 | data->data.insert(std::make_pair(key, val)); |
| 330 | } | ||
| 331 | 222 | } | |
| 332 | |||
| 333 | void copy(const AVSMap* src) { | ||
| 334 | if (src == this) | ||
| 335 | return; | ||
| 336 | |||
| 337 | detach(); | ||
| 338 | for (auto& iter : src->data->data) | ||
| 339 | data->data[iter.first] = iter.second; | ||
| 340 | } | ||
| 341 | |||
| 342 | 133 | size_t size() const { | |
| 343 | 133 | return data->data.size(); | |
| 344 | } | ||
| 345 | |||
| 346 | 49 | void clear() { | |
| 347 |
2/2✓ Branch 4 → 5 taken 6 times.
✓ Branch 4 → 7 taken 43 times.
|
49 | if (data->unique()) |
| 348 | 6 | data->clear(); | |
| 349 | else | ||
| 350 |
2/4✓ Branch 7 → 8 taken 43 times.
✗ Branch 7 → 16 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 43 times.
|
43 | data = new VSMapStorage(); |
| 351 | 49 | } | |
| 352 | |||
| 353 | 1 | const char* key(size_t n) const { | |
| 354 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
|
1 | if (n >= size()) |
| 355 | ✗ | return nullptr; | |
| 356 | 1 | auto iter = data->data.cbegin(); | |
| 357 | std::advance(iter, n); | ||
| 358 | 1 | return iter->first.c_str(); | |
| 359 | } | ||
| 360 | |||
| 361 | void setError(const std::string& errMsg) { | ||
| 362 | clear(); | ||
| 363 | VSDataArray* arr = new VSDataArray(); | ||
| 364 | arr->push_back({ AVSPropDataTypeHint::PROPDATATYPEHINT_UTF8, errMsg }); // dtUtf8 | ||
| 365 | data->data.insert(std::make_pair("_Error", arr)); | ||
| 366 | data->error = true; | ||
| 367 | } | ||
| 368 | |||
| 369 | 151 | bool hasError() const { | |
| 370 | 151 | return data->error; | |
| 371 | } | ||
| 372 | |||
| 373 | const char* getErrorMessage() const { | ||
| 374 | if (data->error) { | ||
| 375 | return reinterpret_cast<VSDataArray*>(data->data.at("_Error").get())->at(0).data.c_str(); | ||
| 376 | } | ||
| 377 | else { | ||
| 378 | return nullptr; | ||
| 379 | } | ||
| 380 | } | ||
| 381 | |||
| 382 | //bool isV3Compatible() const noexcept; // VS special | ||
| 383 | }; | ||
| 384 |