-
Notifications
You must be signed in to change notification settings - Fork 117
Expand file tree
/
Copy pathtruncate_util.h
More file actions
157 lines (140 loc) · 6.52 KB
/
Copy pathtruncate_util.h
File metadata and controls
157 lines (140 loc) · 6.52 KB
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
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include <type_traits>
#include <utility>
#include "iceberg/iceberg_export.h"
#include "iceberg/result.h"
#include "iceberg/type_fwd.h"
#include "iceberg/util/int128.h"
namespace iceberg {
class ICEBERG_EXPORT TruncateUtils {
public:
/// \brief Truncate a UTF-8 string to a specified number of code points.
///
/// \param source The input string to truncate.
/// \param L The maximum number of code points allowed in the output string.
/// \return A valid UTF-8 string truncated to L code points.
/// If the input string is already valid and has fewer than L code points, it is
/// returned unchanged.
static std::string TruncateUTF8(std::string source, size_t L) {
size_t code_point_count = 0;
size_t safe_point = 0;
for (size_t i = 0; i < source.size(); ++i) {
// Start of a new UTF-8 code point
if ((source[i] & 0xC0) != 0x80) {
code_point_count++;
if (code_point_count > static_cast<size_t>(L)) {
safe_point = i;
break;
}
}
}
if (safe_point != 0) {
// Resize the string to the safe point
source.resize(safe_point);
}
return source;
}
/// \brief Truncate a UTF-8 string to a specified number of code points for
/// use as an upper-bound value.
///
/// When truncation is required, the returned value is the smallest UTF-8
/// string greater than the truncated prefix. When no truncation is needed
/// for the given width, the original string may be returned unchanged.
///
/// \param source The input string to truncate.
/// \param L The maximum number of code points allowed in the output string.
/// \return A Result containing the original string (if no truncation is
/// needed), the smallest string greater than the truncated prefix, or nullopt if no
/// safe upper bound can be represented. Invalid UTF-8 is returned as an error.
static Result<std::optional<std::string>> TruncateUTF8Max(const std::string& source,
size_t L);
/// \brief Truncate an integer v, either int32_t or int64_t, to v - (v % W).
///
/// The remainder, v % W, must be positive. For languages where % can produce negative
/// values, the correct truncate function is: v - (((v % W) + W) % W)
template <typename T>
requires std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t>
static inline T TruncateInteger(T v, int32_t W) {
using WideInt = std::conditional_t<std::is_same_v<T, int32_t>, int64_t, int128_t>;
using UnsignedT = std::make_unsigned_t<T>;
const auto value = static_cast<WideInt>(v);
const auto width = static_cast<WideInt>(W);
const auto remainder = ((value % width) + width) % width;
const auto truncated = value - remainder;
// Preserve modulo conversion when the mathematical result is below the signed range.
return static_cast<T>(static_cast<UnsignedT>(truncated));
}
/// \brief Truncate a Decimal to a specified width.
/// \param decimal The input Decimal to truncate.
/// \param width The width to truncate to.
/// \return A Decimal truncated to the specified width.
static Decimal TruncateDecimal(const Decimal& decimal, int32_t width);
/// \brief Truncate a Literal to a specified width.
/// \param literal The input Literal to truncate.
/// \param width The width to truncate to.
/// \return A Result containing the truncated Literal or an error.
/// Supported types are: INT, LONG, DECIMAL, STRING, BINARY.
/// Reference:
/// - [Truncate Transform
/// Details](https://iceberg.apache.org/spec/#truncate-transform-details)
static Result<Literal> TruncateLiteral(const Literal& literal, int32_t width);
/// \brief Truncate a Literal to a specified width for use as an upper-bound value.
///
/// When truncation is required, the returned value is the smallest Literal greater than
/// the truncated prefix. When no truncation is needed for the given width, the original
/// Literal may be returned unchanged.
///
/// \param value The input Literal maximum value to truncate.
/// \param width The width to truncate to.
/// \return A Result containing either the original Literal (if no truncation is
/// needed), the smallest Literal greater than the truncated prefix, or nullopt if no
/// safe upper bound can be represented.
static Result<std::optional<Literal>> TruncateLiteralMax(const Literal& value,
int32_t width);
/// \brief Truncate the lower bound of a string or binary value.
///
/// For string/binary types, truncates to the given length. For other types, returns the
/// value unchanged.
///
/// \param type The Iceberg primitive type.
/// \param value The lower bound literal value.
/// \param width The width to truncate to.
/// \return The truncated lower bound literal.
static Result<Literal> TruncateLowerBound(const PrimitiveType& type,
const Literal& value, int32_t width);
/// \brief Truncate the upper bound of a string or binary value.
///
/// For string/binary types, truncates to the smallest value greater than the truncated
/// prefix. For other types, returns the value unchanged.
///
/// \param type The Iceberg primitive type.
/// \param value The upper bound literal value.
/// \param width The width to truncate to.
/// \return The truncated upper bound literal, or nullopt if no safe upper bound can be
/// represented.
static Result<std::optional<Literal>> TruncateUpperBound(const PrimitiveType& type,
const Literal& value,
int32_t width);
};
} // namespace iceberg