1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2011-2016 Brazil
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License version 2.1 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#pragma once
20
21#include "string.hpp"
22
23namespace grn {
24namespace dat {
25
26class GRN_DAT_API Key {
27 public:
28 const UInt8 &operator[](UInt32 i) const {
29 GRN_DAT_DEBUG_THROW_IF(i >= length());
30 return buf_[i];
31 }
32
33 bool is_valid() const {
34 return id() != INVALID_KEY_ID;
35 }
36
37 String str() const {
38 return String(ptr(), length());
39 }
40
41 const void *ptr() const {
42 return buf_;
43 }
44 UInt32 length() const {
45 return (length_high_ << 4) | (id_and_length_low_ & 0x0F);
46 }
47 UInt32 id() const {
48 return id_and_length_low_ >> 4;
49 }
50
51 bool equals_to(const void *ptr, UInt32 length, UInt32 offset = 0) const {
52 if (length != this->length()) {
53 return false;
54 }
55 for ( ; offset < length; ++offset) {
56 if ((*this)[offset] != static_cast<const UInt8 *>(ptr)[offset]) {
57 return false;
58 }
59 }
60 return true;
61 }
62
63 // Creates an object of Key from given parameters. Then, the created object
64 // is embedded into a specified buffer.
65 static const Key &create(UInt32 *buf, UInt32 key_id,
66 const void *key_ptr, UInt32 key_length) {
67 GRN_DAT_DEBUG_THROW_IF(buf == NULL);
68 GRN_DAT_DEBUG_THROW_IF(key_id > MAX_KEY_ID);
69 GRN_DAT_DEBUG_THROW_IF((key_ptr == NULL) && (key_length != 0));
70 GRN_DAT_DEBUG_THROW_IF(key_length > MAX_KEY_LENGTH);
71
72 *buf = (key_id << 4) | (key_length & 0x0F);
73 UInt8 *ptr = reinterpret_cast<UInt8 *>(buf + 1);
74 *ptr++ = key_length >> 4;
75 for (UInt32 i = 0; i < key_length; ++i) {
76 ptr[i] = static_cast<const UInt8 *>(key_ptr)[i];
77 }
78 return *reinterpret_cast<const Key *>(buf);
79 }
80
81 // Calculates how many UInt32s are required for a string. It is guaranteed
82 // that the estimated size is not less than the actual size.
83 static UInt32 estimate_size(UInt32 length) {
84 return 2 + (length / sizeof(UInt32));
85 }
86
87 // Returns a reference to an invalid key.
88 static const Key &invalid_key() {
89 static const Key invalid_key;
90 return invalid_key;
91// static const UInt32 invalid_key_buf[2] = { INVALID_KEY_ID << 4, 0 };
92// return *reinterpret_cast<const Key *>(invalid_key_buf);
93 }
94
95 private:
96 UInt32 id_and_length_low_;
97 UInt8 length_high_;
98 UInt8 buf_[3];
99
100 // Disallows instantiation.
101 Key() : id_and_length_low_(INVALID_KEY_ID << 4), length_high_(0) {}
102 ~Key() {}
103
104 // Disallows copy and assignment.
105 Key(const Key &);
106 Key &operator=(const Key &);
107};
108
109} // namespace dat
110} // namespace grn
111