OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2016 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include <unordered_map> | |
9 | |
10 #include "SkValue.h" | |
11 #include "SkData.h" | |
12 #include "SkRefCnt.h" | |
13 | |
14 class SkValue::Obj : public SkRefCnt { | |
15 public: | |
16 std::unordered_map<SkValue::Key, SkValue> fMap; | |
17 }; | |
18 | |
19 SkValue::SkValue() : fType(SkValue::Null) {} | |
20 | |
21 SkValue::SkValue(const SkValue& o) { | |
22 memcpy(this, &o, sizeof(o)); | |
23 if (SkValue::Bytes == fType) { | |
24 reinterpret_cast<SkData*>(fBytes)->ref(); | |
mtklein
2016/01/15 00:25:22
WTF? If you want to have an SkData* member, just
hal.canary
2016/01/15 13:38:56
I started by trying to implelment this without cha
| |
25 } else if (fType > 0xFF) { | |
26 fObject->ref(); | |
mtklein
2016/01/15 00:25:22
This makes no sense. You can't share anything tha
hal.canary
2016/01/15 13:38:56
If I add a flag that gets set on the first copy th
mtklein
2016/01/15 13:46:56
Yes, but that's an extremely fragile design. If y
| |
27 } | |
28 } | |
29 | |
30 SkValue::SkValue(SkValue&& o) { | |
31 memcpy(this, &o, sizeof(o)); | |
32 new(&o) SkValue(); | |
mtklein
2016/01/15 00:25:22
space after new?
hal.canary
2016/01/15 13:38:56
done
| |
33 } | |
34 | |
35 SkValue& SkValue::operator=(const SkValue& o) { | |
36 if (this != &o) { | |
37 this->~SkValue(); | |
38 new (this) SkValue(o); | |
39 } | |
40 return *this; | |
41 } | |
42 SkValue& SkValue::operator=(SkValue&& o) { | |
43 if (this != &o) { | |
44 this->~SkValue(); | |
45 new (this) SkValue(std::move(o)); | |
46 } | |
47 return *this; | |
48 } | |
49 | |
50 SkValue::~SkValue() { | |
51 if (SkValue::Bytes == fType) { | |
52 reinterpret_cast<SkData*>(fBytes)->unref(); | |
53 } else if (fType > 0xFF) { | |
mtklein
2016/01/15 00:25:22
Let's add
private:
bool isObject() const { f
hal.canary
2016/01/15 13:38:56
done.
| |
54 fObject->unref(); | |
55 } | |
56 } | |
57 | |
58 SkValue SkValue::FromS32(int32_t x) { | |
59 SkValue v; | |
60 v.fType = SkValue::S32; | |
mtklein
2016/01/15 00:25:22
in this scope you can just write S32, etc.
hal.canary
2016/01/15 13:38:56
done.
| |
61 v.fS32 = x; | |
62 return v; | |
63 } | |
64 | |
65 SkValue SkValue::FromU32(uint32_t x) { | |
66 SkValue v; | |
67 v.fType = SkValue::U32; | |
68 v.fU32 = x; | |
69 return v; | |
70 } | |
71 | |
72 SkValue SkValue::FromF32(float x) { | |
73 SkValue v; | |
74 v.fType = SkValue::F32; | |
75 v.fF32 = x; | |
76 return v; | |
77 } | |
78 | |
79 SkValue SkValue::FromBytes(const void* data, size_t length) { | |
80 SkValue v; | |
81 v.fType = SkValue::Bytes; | |
82 reinterpret_cast<SkData*&>(v.fBytes) = SkData::NewWithCopy(data, length); | |
83 return v; | |
84 } | |
85 | |
86 SkValue SkValue::Object(SkValue::Type t) { | |
87 SkASSERT(t > 0xFF); | |
88 SkValue v; | |
89 v.fType = t; | |
90 v.fObject = new SkValue::Obj; | |
91 return v; | |
92 } | |
93 | |
94 SkValue::Type SkValue::type() const { return fType; } | |
95 | |
96 int32_t SkValue::s32() const { return SkValue::S32 == fType ? fS32 : 0; } | |
mtklein
2016/01/15 00:25:22
These should all assert they're the right type.
hal.canary
2016/01/15 13:38:56
done.
| |
97 | |
98 uint32_t SkValue::u32() const { return SkValue::U32 == fType ? fU32 : 0; } | |
99 | |
100 float SkValue::f32() const { return SkValue::F32 == fType ? fF32 : 0; } | |
101 | |
102 const void* SkValue::bytes() const { | |
103 return SkValue::Bytes == fType | |
104 ? reinterpret_cast<SkData*>(fBytes)->data() | |
105 : nullptr; | |
106 } | |
107 | |
108 size_t SkValue::count() const { | |
109 if (SkValue::Bytes == fType) { | |
110 return reinterpret_cast<SkData*>(fBytes)->size(); | |
111 } else if (fType > 0xFF) { | |
112 return fObject->fMap.size(); | |
mtklein
2016/01/15 00:25:22
let's just have count() work for Bytes for now.
hal.canary
2016/01/15 13:38:56
why?
mtklein
2016/01/15 13:46:56
We have foreach().
| |
113 } | |
114 return 0; | |
115 } | |
116 | |
117 void SkValue::set(SkValue::Key k, SkValue v) { | |
118 if (fType <= 0xFF) { | |
119 return; | |
120 } | |
121 fObject->fMap[k] = std::move(v); | |
122 } | |
123 const SkValue* SkValue::get(SkValue::Key k) const { | |
124 if (fType <= 0xFF) { | |
125 return nullptr; | |
126 } | |
127 auto& map = fObject->fMap; | |
128 return map.find(k) != map.end() ? &map[k] : nullptr; | |
mtklein
2016/01/15 00:25:22
This does the hash lookup twice.
const auto& map
hal.canary
2016/01/15 13:38:56
done. reading the specs it looked like the iterat
mtklein
2016/01/15 13:46:56
That map iterator is a little surprising, I admit,
| |
129 } | |
130 void SkValue::foreach( | |
131 std::function<void(SkValue::Key, const SkValue&)> fn) const { | |
132 if (fType <= 0xFF) { | |
133 return; | |
134 } | |
135 for (const auto& pair : fObject->fMap) { | |
136 fn(pair.first, pair.second); | |
137 } | |
138 } | |
OLD | NEW |