1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef COMPONENTS_ZUCCHINI_ENCODED_VIEW_H_
6 #define COMPONENTS_ZUCCHINI_ENCODED_VIEW_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 
11 #include <iterator>
12 #include <vector>
13 
14 #include "components/zucchini/image_index.h"
15 #include "components/zucchini/image_utils.h"
16 
17 namespace zucchini {
18 
19 // Zucchini-gen performs semantics-aware matching:
20 // - Same-typed reference target in "old" and "new" can be associated.
21 //   Associated targets are assigned an identifier called "label" (and for
22 //   unassociated targets, label = 0).
23 // - EncodedView maps each offset in "old" and "new" images to a "projected
24 //   value", which can be:
25 //   - Raw byte value (0-255) for non-references.
26 //   - Reference "projected value" (> 256) that depends on target {type, label}
27 //     at each reference's location (byte 0).
28 //   - Reference padding value (256) at the body of each reference (bytes 1+).
29 // - The projected values for "old" and "new" are used to build the equivalence
30 //   map.
31 
32 constexpr size_t kReferencePaddingProjection = 256;
33 constexpr size_t kBaseReferenceProjection = 257;
34 
35 // A Range (providing begin and end iterators) that adapts ImageIndex to make
36 // image data appear as an Encoded Image, that is encoded data under a higher
37 // level of abstraction than raw bytes. In particular:
38 // - First byte of each reference become a projection of its type and label.
39 // - Subsequent bytes of each reference becomes |kReferencePaddingProjection|.
40 // - Non-reference raw bytes remain as raw bytes.
41 class EncodedView {
42  public:
43   // RandomAccessIterator whose values are the results of Projection().
44   class Iterator {
45    public:
46     using iterator_category = std::random_access_iterator_tag;
47     using value_type = size_t;
48     using difference_type = ptrdiff_t;
49     using reference = size_t;
50     using pointer = size_t*;
51 
Iterator(const EncodedView * encoded_view,difference_type pos)52     Iterator(const EncodedView* encoded_view, difference_type pos)
53         : encoded_view_(encoded_view), pos_(pos) {}
54 
55     Iterator(const Iterator&) = default;
56 
57     Iterator& operator=(const Iterator&) = default;
58 
59     value_type operator*() const {
60       return encoded_view_->Projection(static_cast<offset_t>(pos_));
61     }
62 
63     value_type operator[](difference_type n) const {
64       return encoded_view_->Projection(static_cast<offset_t>(pos_ + n));
65     }
66 
67     Iterator& operator++() {
68       ++pos_;
69       return *this;
70     }
71 
72     Iterator operator++(int) {
73       Iterator tmp = *this;
74       ++pos_;
75       return tmp;
76     }
77 
78     Iterator& operator--() {
79       --pos_;
80       return *this;
81     }
82 
83     Iterator operator--(int) {
84       Iterator tmp = *this;
85       --pos_;
86       return tmp;
87     }
88 
89     Iterator& operator+=(difference_type n) {
90       pos_ += n;
91       return *this;
92     }
93 
94     Iterator& operator-=(difference_type n) {
95       pos_ -= n;
96       return *this;
97     }
98 
99     friend bool operator==(Iterator a, Iterator b) { return a.pos_ == b.pos_; }
100 
101     friend bool operator!=(Iterator a, Iterator b) { return !(a == b); }
102 
103     friend bool operator<(Iterator a, Iterator b) { return a.pos_ < b.pos_; }
104 
105     friend bool operator>(Iterator a, Iterator b) { return b < a; }
106 
107     friend bool operator<=(Iterator a, Iterator b) { return !(b < a); }
108 
109     friend bool operator>=(Iterator a, Iterator b) { return !(a < b); }
110 
111     friend difference_type operator-(Iterator a, Iterator b) {
112       return a.pos_ - b.pos_;
113     }
114 
115     friend Iterator operator+(Iterator it, difference_type n) {
116       it += n;
117       return it;
118     }
119 
120     friend Iterator operator-(Iterator it, difference_type n) {
121       it -= n;
122       return it;
123     }
124 
125    private:
126     const EncodedView* encoded_view_;
127     difference_type pos_;
128   };
129 
130   using value_type = size_t;
131   using size_type = offset_t;
132   using difference_type = ptrdiff_t;
133   using const_iterator = Iterator;
134 
135   // |image_index| is the annotated image being adapted, and is required to
136   // remain valid for the lifetime of the object.
137   explicit EncodedView(const ImageIndex& image_index);
138   EncodedView(const EncodedView&) = delete;
139   const EncodedView& operator=(const EncodedView&) = delete;
140   ~EncodedView();
141 
142   // Projects |location| to a scalar value that describes the content at a
143   // higher level of abstraction.
144   value_type Projection(offset_t location) const;
145 
IsToken(offset_t location)146   bool IsToken(offset_t location) const {
147     return image_index_.IsToken(location);
148   }
149 
150   // Returns the cardinality of the projection, i.e., the upper bound on
151   // values returned by Projection().
152   value_type Cardinality() const;
153 
154   // Associates |labels| to targets for a given |pool|, replacing previous
155   // association. Values in |labels| must be smaller than |bound|.
156   void SetLabels(PoolTag pool, std::vector<uint32_t>&& labels, size_t bound);
image_index()157   const ImageIndex& image_index() const { return image_index_; }
158 
159   // Range functions.
size()160   size_type size() const { return size_type(image_index_.size()); }
begin()161   const_iterator begin() const {
162     return const_iterator{this, difference_type(0)};
163   }
end()164   const_iterator end() const {
165     return const_iterator{this, difference_type(size())};
166   }
167 
168  private:
169   struct PoolInfo {
170     PoolInfo();
171     PoolInfo(PoolInfo&&);
172     ~PoolInfo();
173 
174     // |labels| translates IndirectReference target_key to label.
175     std::vector<uint32_t> labels;
176     size_t bound = 0;
177   };
178 
179   const ImageIndex& image_index_;
180   std::vector<PoolInfo> pool_infos_;
181 };
182 
183 }  // namespace zucchini
184 
185 #endif  // COMPONENTS_ZUCCHINI_ENCODED_VIEW_H_
186