| // 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 "common/compiler-util.h" |
| |
| namespace impala { |
| |
| /// Utility classes for reading and writing to memory. |
| |
| |
| /// Utility class for writing to unaligned memory containing values of type T separated |
| /// by an arbitrary byte stride. |
| template <typename T> |
| struct StrideWriter { |
| // The next element to write to. May not be aligned to the natural alignment of T. |
| T* current; |
| |
| // The stride in bytes between subsequent values. |
| int64_t stride; |
| |
| explicit StrideWriter(T* current, int64_t stride) : current(current), stride(stride) { |
| DCHECK(current != nullptr); |
| } |
| |
| /// Set the next element to 'val' and advance 'current' to the next element. |
| ALWAYS_INLINE void SetNext(T& val) { |
| // memcpy() is necessary because 'current' may not be aligned. |
| memcpy(current, &val, sizeof(T)); |
| SkipNext(1); |
| } |
| |
| /// Return a pointer to the current element and advance 'current' to the next element. |
| ALWAYS_INLINE T* Advance() { |
| T* curr = current; |
| SkipNext(1); |
| return curr; |
| } |
| |
| /// Set the next 'count' elements to 'val', advancing 'current' by 'count' values. |
| void SetNext(T& val, int64_t count) { |
| for (int64_t i = 0; i < count; ++i) SetNext(val); |
| } |
| |
| /// Advance 'current' by 'count' values. |
| ALWAYS_INLINE void SkipNext(int64_t count) { |
| DCHECK_GE(count, 0); |
| current = reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(current) + stride * count); |
| } |
| }; |
| } // namespace impala |