1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef LATINIME_INT_ARRAY_VIEW_H
18#define LATINIME_INT_ARRAY_VIEW_H
19
20#include <algorithm>
21#include <array>
22#include <cstdint>
23#include <cstring>
24#include <vector>
25
26#include "defines.h"
27
28namespace latinime {
29
30/**
31 * Helper class used to provide a read-only view of a given range of integer array. This class
32 * does not take ownership of the underlying integer array but is designed to be a lightweight
33 * object that obeys value semantics.
34 *
35 * Example:
36 * <code>
37 * bool constinsX(IntArrayView view) {
38 *     for (size_t i = 0; i < view.size(); ++i) {
39 *         if (view[i] == 'X') {
40 *             return true;
41 *         }
42 *     }
43 *     return false;
44 * }
45 *
46 * const int codePointArray[] = { 'A', 'B', 'X', 'Z' };
47 * auto view = IntArrayView(codePointArray, NELEMS(codePointArray));
48 * const bool hasX = constinsX(view);
49 * </code>
50 */
51class IntArrayView {
52 public:
53    IntArrayView() : mPtr(nullptr), mSize(0) {}
54
55    IntArrayView(const int *const ptr, const size_t size)
56            : mPtr(ptr), mSize(size) {}
57
58    explicit IntArrayView(const std::vector<int> &vector)
59            : mPtr(vector.data()), mSize(vector.size()) {}
60
61    template <size_t N>
62    AK_FORCE_INLINE static IntArrayView fromArray(const std::array<int, N> &array) {
63        return IntArrayView(array.data(), array.size());
64    }
65
66    // Returns a view that points one int object.
67    AK_FORCE_INLINE static IntArrayView singleElementView(const int *const ptr) {
68        return IntArrayView(ptr, 1);
69    }
70
71    AK_FORCE_INLINE int operator[](const size_t index) const {
72        ASSERT(index < mSize);
73        return mPtr[index];
74    }
75
76    AK_FORCE_INLINE bool empty() const {
77        return size() == 0;
78    }
79
80    AK_FORCE_INLINE size_t size() const {
81        return mSize;
82    }
83
84    AK_FORCE_INLINE const int *data() const {
85        return mPtr;
86    }
87
88    AK_FORCE_INLINE const int *begin() const {
89        return mPtr;
90    }
91
92    AK_FORCE_INLINE const int *end() const {
93        return mPtr + mSize;
94    }
95
96    AK_FORCE_INLINE bool contains(const int value) const {
97        return std::find(begin(), end(), value) != end();
98    }
99
100    // Returns the view whose size is smaller than or equal to the given count.
101    AK_FORCE_INLINE const IntArrayView limit(const size_t maxSize) const {
102        return IntArrayView(mPtr, std::min(maxSize, mSize));
103    }
104
105    AK_FORCE_INLINE const IntArrayView skip(const size_t n) const {
106        if (mSize <= n) {
107            return IntArrayView();
108        }
109        return IntArrayView(mPtr + n, mSize - n);
110    }
111
112    template <size_t N>
113    void copyToArray(std::array<int, N> *const buffer, const size_t offset) const {
114        ASSERT(mSize + offset <= N);
115        memmove(buffer->data() + offset, mPtr, sizeof(int) * mSize);
116    }
117
118    AK_FORCE_INLINE int firstOrDefault(const int defaultValue) const {
119        if (empty()) {
120            return defaultValue;
121        }
122        return mPtr[0];
123    }
124
125    AK_FORCE_INLINE int lastOrDefault(const int defaultValue) const {
126        if (empty()) {
127            return defaultValue;
128        }
129        return mPtr[mSize - 1];
130    }
131
132    AK_FORCE_INLINE std::vector<int> toVector() const {
133        return std::vector<int>(begin(), end());
134    }
135
136    std::vector<IntArrayView> split(const int separator, const int limit = S_INT_MAX) const {
137        if (limit <= 0) {
138            return std::vector<IntArrayView>();
139        }
140        std::vector<IntArrayView> result;
141        if (limit == 1) {
142            result.emplace_back(mPtr, mSize);
143            return result;
144        }
145        size_t startIndex = 0;
146        for (size_t i = 0; i < mSize; ++i) {
147            if (mPtr[i] == separator) {
148                result.emplace_back(mPtr + startIndex, i - startIndex);
149                startIndex = i + 1;
150                if (result.size() >= static_cast<size_t>(limit - 1)) {
151                    break;
152                }
153            }
154        }
155        result.emplace_back(mPtr + startIndex, mSize - startIndex);
156        return result;
157    }
158
159 private:
160    DISALLOW_ASSIGNMENT_OPERATOR(IntArrayView);
161
162    const int *const mPtr;
163    const size_t mSize;
164};
165
166using WordIdArrayView = IntArrayView;
167using PtNodePosArrayView = IntArrayView;
168using CodePointArrayView = IntArrayView;
169template <size_t size>
170using WordIdArray = std::array<int, size>;
171
172} // namespace latinime
173#endif // LATINIME_MEMORY_VIEW_H
174