This file is indexed.

/usr/include/qt5qevercloud/Optional.h is in qt5qevercloud-dev 3.0.3+ds-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
/**
 * Original work: Copyright (c) 2014 Sergey Skoblikov
 * Modified work: Copyright (c) 2015-2016 Dmitry Ivanov
 *
 * This file is a part of QEverCloud project and is distributed under the terms of MIT license:
 * https://opensource.org/licenses/MIT
 */

#ifndef QEVERCLOUD_OPTIONAL_H
#define QEVERCLOUD_OPTIONAL_H

#include "EverCloudException.h"
#include <algorithm>

namespace qevercloud {

/**
 * Supports optional values.
 *
 * Most of the fields in the Evernote API structs are optional. But C++ does not support this notion directly.
 *
 * To implement the concept of optional values conventional Thrift C++ wrapper uses a special field of a struct type
 * where each field is of type bool with the same name as a field in the struct. This bool flag indicated was
 * the field with the same name in the outer struct assigned or not.
 *
 * While this method have its advantages (obviousness and simplicity) I found it very inconvenient to work with.
 * You have to check by hand that both values (value itself and its __isset flag) are in sync.
 * There is no checks whatsoever against an error and such an error is too easy to make.
 *
 * So for my library I created a special class that supports the optional value notion explicitly.
 * Basically Optional class just holds a bool value that tracks the fact that a value was assigned. But this tracking
 * is done automatically and attempts to use unissigned values throw exceptions. In this way errors are much harder to
 * make and it's harder for them to slip through testing unnoticed too.
 *
 */
template<typename T>
class Optional
{
public:
    /** Default constructor.
     * Default Optional is not set.
     */
    Optional() :
        m_isSet(false),
        m_value(T())
    {}

    /**
     * Copy constructor.
     */
    Optional(const Optional & o) :
        m_isSet(o.m_isSet),
        m_value(o.m_value)
    {}

    /**
     * Template copy constructor. Allows to be initialized with Optional of any compatible type.
     */
    template<typename X>
    Optional(const Optional<X> & o) :
        m_isSet(o.m_isSet),
        m_value(o.m_value)
    {}

    /**
     * Initialization with a value of the type T. Note: it's implicit.
     */
    Optional(const T & value) :
        m_isSet(true),
        m_value(value)
    {}

    /**
     * Template initialization with a value of any compatible type.
     */
    template<typename X>
    Optional(const X & value) :
        m_isSet(true),
        m_value(value)
    {}

    /**
     * Assignment.
     */
    Optional & operator=(const Optional & o)
    {
        m_value = o.m_value;
        m_isSet = o.m_isSet;
        return *this;
    }

    /**
     * Template assignment with an Optional of any compatible value.
     */
    template<typename X>
    Optional & operator=(const Optional<X> & o)
    {
        m_value = o.m_value;
        m_isSet = o.m_isSet;
        return *this;
    }

    /**
     * Assignment with a value of the type T.
     */
    Optional & operator=(const T & value)
    {
        m_value = value;
        m_isSet = true;
        return *this;
    }

    /**
     * Template assignment with a value of any compatible type.
     */
    template<typename X>
    Optional & operator=(const X & value)
    {
        m_value = value;
        m_isSet = true;
        return *this;
    }

    /**
     * Implicit conversion of Optional<T> to T.
     *
     * const version.
     */
    operator const T&() const
    {
        if (!m_isSet) {
            throw EverCloudException("qevercloud::Optional: nonexistent value access");
        }

        return m_value;
    }

    /**
     * Implicit conversion of Optional<T> to T.
     *
     * Note: a reference is returned, not a copy.
     */
    operator T&()
    {
        if (!m_isSet) {
            throw EverCloudException("qevercloud::Optional: nonexistent value access");
        }

        return m_value;
    }

    /**
     * Returs a reference to the holded value.
     *
     * const version.
     *
     */
    const T & ref() const
    {
        if (!m_isSet) {
            throw EverCloudException("qevercloud::Optional: nonexistent value access");
        }

        return m_value;
    }

    /**
     * Returs reference to the holded value.
     *
     * There are contexts in C++ where impicit type conversions can't help. For example:
     *
     * @code
      Optional<QStringList> l;
      for(auto s : l); // you will hear from your compiler
      @endcode
     *
     * Explicit type conversion can be used...
     *
     * @code
      Optional<QStringList> l;
      for(auto s : static_cast<QStringList&>(l)); // ugh...
      @endcode
     *
     * ... but this is indeed ugly as hell.
     *
     * So I implemented ref() function that returns a reference to the holded value.
     * @code
      Optional<QStringList> l;
      for(auto s : l.ref()); // not ideal but OK
      @endcode
     */
    T & ref()
    {
        if (!m_isSet) {
            throw EverCloudException("qevercloud::Optional: nonexistent value access");
        }

        return m_value;
    }

    /**
     * @brief Checks if value is set.
     * @return true if Optional have been assigned a value and false otherwise.
     *
     * Access to an unassigned ("not set") Optional lead to an exception.
     */
    bool isSet() const
    {
        return m_isSet;
    }

    /**
     * Clears an Optional.
     *
     * @code

      Optional<int> o(1);
      o.clear();
      cout << o; // exception

      @endcode
     */
    void clear()
    {
        m_isSet = false;
        m_value = T();
    }

    /**
     * Fast way to initialize an Optional with a default value.
     *
     * It's very useful for structs.
     *
     * @code

      struct S2 {int f;};
      struct S {int f1; Optional<S2> f2};
      Optional<S> o; // o.isSet() != ture

      // without init() it's cumbersome to access struct fields
      // it's especially true for nested Optionals
      o = S(); // now o is set
      o->f2 = S2(); // and o.f2 is set
      o->f2->f = 1; // so at last it can be used

      // with init() it's simpler
      o.init()->f2.init()->f = 1;

      @endcode
     * @return reference to itself
     */
    Optional & init()
    {
        m_isSet = true;
        m_value = T();
        return *this;
    }

    /**
     * Two syntatic constructs come to mind to use for implementation of access to a struct's/class's field directly from Optional.
     *
     * One is the dereference operator.
     * This is what boost::optional uses. While it's conceptually nice
     * I found it to be not a very convenient way to refer to structs, especially nested ones.
     * So I overloaded the operator-> and use smart pointer semantics.
     *
     * @code
      struct S1 {int f1;};
      struct S2 {Optional<S1> f2;};
      Optional<S2> o;

      *((*o).f2).f1; // boost way, not implemented

      o->f2->f1;     // QEverCloud way

      @endcode
     *
     * I admit, boost::optional is much more elegant overall. It uses pointer semantics quite clearly and
     * in an instantly understandable way. It's universal (* works for any type and not just structs). There is
     * no need for implicit type concersions and so there is no subtleties because of it. And so on.
     *
     * But then referring to struct fields is a chore. And this is the most common use case of Optionals in QEverCloud.
     *
     * So I decided to use non-obvious-on-the-first-sight semantics for my Optional. IMO it's much more convenient when gotten used to.
     *
     */
    T * operator->()
    {
        if (!m_isSet) {
            throw EverCloudException("qevercloud::Optional: nonexistent value access");
        }

        return &m_value;
    }

    /**
     * const version.
     */
    const T * operator->() const
    {
        if (!m_isSet) {
            throw EverCloudException("qevercloud::Optional: nonexistent value access");
        }

        return &m_value;
    }

    /**
     * The function is sometimes useful to simplify checking for the value being set.
     * @param defaultValue
     * The value to return if Optional is not set.
     * @return Optional value if set and defaultValue otherwise.
     */
    T value(T defaultValue = T()) const
    {
        return m_isSet ? m_value : defaultValue;
    }

    /**
     * Two optionals are equal if they are both not set or have
     * equal values.
     *
     * I do not define `operator==` due to not easily resolvable conflicts with `operator T&`.
     *
     * Note that `optional == other_optional` may throw but `optional.isEqual(other_optional)` will not.
     */
    bool isEqual(const Optional<T> & other) const
    {
        if(m_isSet != other.m_isSet) return false;
        return !m_isSet || (m_value == other.m_value);
    }

    template<typename X> friend class Optional;

    friend void swap(Optional & first, Optional & second)
    {
        using std::swap;
        swap(first.m_isSet, second.m_isSet);
        swap(first.m_value, second.m_value);
    }

// Visual C++ does not to generate implicit move constructors so this stuff doesn't work with even recent MSVC compilers
#if defined(Q_COMPILER_RVALUE_REFS) && !defined(_MSC_VER)
    Optional(Optional && other)
    {
        swap(*this, other);
    }

    Optional & operator=(Optional && other)
    {
        swap(*this, other);
        return *this;
    }

    Optional(T && other)
    {
        using std::swap;
        m_isSet = true;
        swap(m_value, other);
    }

    Optional & operator=(T && other)
    {
        using std::swap;
        m_isSet = true;
        swap(m_value, other);
        return *this;
    }
#endif

private:
    bool m_isSet;
    T m_value;
};

} // namespace qevercloud

#endif // QEVERCLOUD_OPTIONAL_H