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 | 1073 | vs_intrusive_ptr(T* ptr = nullptr, bool add_ref = false) noexcept { | |
| 42 | 1073 | obj = ptr; | |
| 43 |
2/8vs_intrusive_ptr<VSArrayBase>::vs_intrusive_ptr(VSArrayBase*, bool):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 81 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 992 times.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
|
1073 | if (add_ref && obj) |
| 44 | ✗ | obj->add_ref(); | |
| 45 | 1073 | } | |
| 46 | |||
| 47 | 10 | vs_intrusive_ptr(const vs_intrusive_ptr& ptr) noexcept { | |
| 48 | 10 | obj = ptr.obj; | |
| 49 |
1/4vs_intrusive_ptr<VSArrayBase>::vs_intrusive_ptr(vs_intrusive_ptr<VSArrayBase> const&):
✓ Branch 2 → 3 taken 10 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.
|
10 | if (obj) |
| 50 | 10 | obj->add_ref(); | |
| 51 | 10 | } | |
| 52 | |||
| 53 | vs_intrusive_ptr(vs_intrusive_ptr&& ptr) noexcept { | ||
| 54 | obj = ptr.obj; | ||
| 55 | ptr.obj = nullptr; | ||
| 56 | } | ||
| 57 | |||
| 58 | 1083 | ~vs_intrusive_ptr() noexcept { | |
| 59 |
2/4vs_intrusive_ptr<VSArrayBase>::~vs_intrusive_ptr():
✓ Branch 2 → 3 taken 91 times.
✗ Branch 2 → 4 not taken.
vs_intrusive_ptr<VSMapStorage>::~vs_intrusive_ptr():
✓ Branch 2 → 3 taken 992 times.
✗ Branch 2 → 4 not taken.
|
1083 | if (obj) |
| 60 | 1083 | obj->release(); | |
| 61 | 1083 | } | |
| 62 | |||
| 63 | 328 | 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 15 times.
✗ Branch 2 → 4 not taken.
vs_intrusive_ptr<VSMapStorage>::operator=(vs_intrusive_ptr<VSMapStorage> const&):
✓ Branch 2 → 3 taken 313 times.
✗ Branch 2 → 4 not taken.
|
328 | if (obj) |
| 65 | 328 | obj->release(); | |
| 66 | 328 | obj = ptr.obj; | |
| 67 |
2/4vs_intrusive_ptr<VSArrayBase>::operator=(vs_intrusive_ptr<VSArrayBase> const&):
✓ Branch 4 → 5 taken 15 times.
✗ Branch 4 → 6 not taken.
vs_intrusive_ptr<VSMapStorage>::operator=(vs_intrusive_ptr<VSMapStorage> const&):
✓ Branch 4 → 5 taken 313 times.
✗ Branch 4 → 6 not taken.
|
328 | if (obj) |
| 68 | 328 | obj->add_ref(); | |
| 69 | 328 | return *this; | |
| 70 | } | ||
| 71 | |||
| 72 | 736 | T* operator->() const noexcept { | |
| 73 | 736 | return obj; | |
| 74 | } | ||
| 75 | |||
| 76 | 27 | T& operator*() const noexcept { | |
| 77 | 27 | return *obj; | |
| 78 | } | ||
| 79 | |||
| 80 | operator bool() const noexcept { | ||
| 81 | return !!obj; | ||
| 82 | } | ||
| 83 | |||
| 84 | 74 | T* get() const noexcept { | |
| 85 | 74 | 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 | 81 | explicit VSArrayBase(AVSPropertyType type) : refcount(1), ftype(type) {} | |
| 123 | 81 | virtual ~VSArrayBase() {} | |
| 124 | public: | ||
| 125 | 44 | AVSPropertyType type() const { | |
| 126 | 44 | return ftype; | |
| 127 | } | ||
| 128 | |||
| 129 | 71 | size_t size() const { | |
| 130 | 71 | return fsize; | |
| 131 | } | ||
| 132 | |||
| 133 | 1 | bool unique() const noexcept { | |
| 134 | 1 | return (refcount == 1); | |
| 135 | } | ||
| 136 | |||
| 137 | 25 | void add_ref() noexcept { | |
| 138 | 25 | ++refcount; | |
| 139 | 25 | } | |
| 140 | |||
| 141 | 106 | void release() noexcept { | |
| 142 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 106 times.
|
106 | assert(refcount > 0); |
| 143 |
2/2✓ Branch 6 → 7 taken 81 times.
✓ Branch 6 → 9 taken 25 times.
|
106 | if (--refcount == 0) |
| 144 |
1/2✓ Branch 7 → 8 taken 81 times.
✗ Branch 7 → 9 not taken.
|
81 | delete this; |
| 145 | 106 | } | |
| 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 | 81 | 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 | 82 | 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 80 times.
✗ Branch 2 → 4 not taken.
|
82 | if (fsize == 0) { |
| 192 | 81 | 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 | 82 | fsize++; | |
| 205 | 82 | } | |
| 206 | |||
| 207 | 42 | 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 41 times.
|
42 | 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 41 times.
✗ Branch 4 → 6 not taken.
|
42 | if (fsize == 1) |
| 210 | 41 | 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 | 965 | explicit VSMapStorage() : refcount(1), error(false) {} | |
| 247 | |||
| 248 | 27 | explicit VSMapStorage(const VSMapStorage& s) : refcount(1), data(s.data), error(s.error) { | |
| 249 | 27 | } | |
| 250 | |||
| 251 | 2 | void clear() noexcept { | |
| 252 | 2 | data.clear(); | |
| 253 | 2 | error = false; | |
| 254 | 2 | } | |
| 255 | |||
| 256 | 96 | bool unique() noexcept { | |
| 257 | 96 | return (refcount == 1); | |
| 258 | }; | ||
| 259 | |||
| 260 | 313 | void add_ref() noexcept { | |
| 261 | 313 | ++refcount; | |
| 262 | 313 | } | |
| 263 | |||
| 264 | 1305 | void release() noexcept { | |
| 265 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1305 times.
|
1305 | assert(refcount > 0); |
| 266 |
2/2✓ Branch 6 → 7 taken 992 times.
✓ Branch 6 → 10 taken 313 times.
|
1305 | if (--refcount == 0) |
| 267 |
1/2✓ Branch 7 → 8 taken 992 times.
✗ Branch 7 → 10 not taken.
|
992 | delete this; |
| 268 | 1305 | } | |
| 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 955 times.
✓ Branch 4 → 5 taken 955 times.
✗ Branch 4 → 11 not taken.
✓ Branch 7 → 8 taken 955 times.
✗ Branch 7 → 10 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 955 times.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 14 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
|
955 | AVSMap(const AVSMap* map = nullptr) : data(map ? map->data : new VSMapStorage()) { |
| 280 | 955 | } | |
| 281 | |||
| 282 | 276 | AVSMap& operator=(const AVSMap& map) { | |
| 283 | 276 | data = map.data; | |
| 284 | 276 | return *this; | |
| 285 | } | ||
| 286 | |||
| 287 | 84 | bool detach() { | |
| 288 |
2/2✓ Branch 4 → 5 taken 27 times.
✓ Branch 4 → 14 taken 57 times.
|
84 | if (!data->unique()) { |
| 289 |
3/8✓ Branch 5 → 6 taken 27 times.
✗ Branch 5 → 19 not taken.
✓ Branch 7 → 8 taken 27 times.
✗ Branch 7 → 16 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 27 times.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
|
27 | data = new VSMapStorage(*data); |
| 290 | 27 | return true; | |
| 291 | } | ||
| 292 | 57 | return false; | |
| 293 | } | ||
| 294 | |||
| 295 | 121 | VSArrayBase* find(const std::string& key) const { | |
| 296 |
1/2✓ Branch 3 → 4 taken 121 times.
✗ Branch 3 → 14 not taken.
|
121 | auto it = data->data.find(key); |
| 297 |
2/2✓ Branch 7 → 8 taken 48 times.
✓ Branch 7 → 9 taken 73 times.
|
121 | 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 | 34 | bool erase(const std::string& key) { | |
| 312 |
1/2✓ Branch 3 → 4 taken 34 times.
✗ Branch 3 → 18 not taken.
|
34 | auto it = data->data.find(key); |
| 313 |
2/2✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 15 taken 32 times.
|
34 | if (it != data->data.end()) { |
| 314 |
2/4✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 18 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 2 times.
|
2 | if (detach()) |
| 315 | ✗ | it = data->data.find(key); | |
| 316 |
1/2✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 18 not taken.
|
2 | data->data.erase(it); |
| 317 | 2 | return true; | |
| 318 | } | ||
| 319 | 32 | return false; | |
| 320 | } | ||
| 321 | |||
| 322 | 81 | void insert(const std::string& key, VSArrayBase* val) { | |
| 323 |
1/2✓ Branch 2 → 3 taken 81 times.
✗ Branch 2 → 23 not taken.
|
81 | detach(); |
| 324 |
1/2✓ Branch 4 → 5 taken 81 times.
✗ Branch 4 → 23 not taken.
|
81 | auto it = data->data.find(key); |
| 325 |
2/2✓ Branch 8 → 9 taken 15 times.
✓ Branch 8 → 14 taken 66 times.
|
81 | if (it != data->data.end()) { |
| 326 | 15 | it->second = val; | |
| 327 | } | ||
| 328 | else { | ||
| 329 |
2/4✓ Branch 15 → 16 taken 66 times.
✗ Branch 15 → 22 not taken.
✓ Branch 16 → 17 taken 66 times.
✗ Branch 16 → 20 not taken.
|
66 | data->data.insert(std::make_pair(key, val)); |
| 330 | } | ||
| 331 | 81 | } | |
| 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 | 52 | size_t size() const { | |
| 343 | 52 | return data->data.size(); | |
| 344 | } | ||
| 345 | |||
| 346 | 12 | void clear() { | |
| 347 |
2/2✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 7 taken 10 times.
|
12 | if (data->unique()) |
| 348 | 2 | data->clear(); | |
| 349 | else | ||
| 350 |
2/4✓ Branch 7 → 8 taken 10 times.
✗ Branch 7 → 16 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 10 times.
|
10 | data = new VSMapStorage(); |
| 351 | 12 | } | |
| 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 | 42 | bool hasError() const { | |
| 370 | 42 | 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 |