include/avs/alignment.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Avisynth C Interface Version 0.20 | ||
| 2 | // Copyright 2003 Kevin Atkinson | ||
| 3 | |||
| 4 | // This program is free software; you can redistribute it and/or modify | ||
| 5 | // it under the terms of the GNU General Public License as published by | ||
| 6 | // the Free Software Foundation; either version 2 of the License, or | ||
| 7 | // (at your option) any later version. | ||
| 8 | // | ||
| 9 | // This program 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 | ||
| 12 | // GNU General Public License for more details. | ||
| 13 | // | ||
| 14 | // You should have received a copy of the GNU General Public License | ||
| 15 | // along with this program; if not, write to the Free Software | ||
| 16 | // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit | ||
| 17 | // http://www.gnu.org/copyleft/gpl.html . | ||
| 18 | // | ||
| 19 | // As a special exception, I give you permission to link to the | ||
| 20 | // Avisynth C interface with independent modules that communicate with | ||
| 21 | // the Avisynth C interface solely through the interfaces defined in | ||
| 22 | // avisynth_c.h, regardless of the license terms of these independent | ||
| 23 | // modules, and to copy and distribute the resulting combined work | ||
| 24 | // under terms of your choice, provided that every copy of the | ||
| 25 | // combined work is accompanied by a complete copy of the source code | ||
| 26 | // of the Avisynth C interface and Avisynth itself (with the version | ||
| 27 | // used to produce the combined work), being distributed under the | ||
| 28 | // terms of the GNU General Public License plus this exception. An | ||
| 29 | // independent module is a module which is not derived from or based | ||
| 30 | // on Avisynth C Interface, such as 3rd-party filters, import and | ||
| 31 | // export plugins, or graphical user interfaces. | ||
| 32 | |||
| 33 | #ifndef AVS_ALIGNMENT_H | ||
| 34 | #define AVS_ALIGNMENT_H | ||
| 35 | |||
| 36 | // Functions and macros to help work with alignment requirements. | ||
| 37 | |||
| 38 | // Tells if a number is a power of two. | ||
| 39 | #define IS_POWER2(n) ((n) && !((n) & ((n) - 1))) | ||
| 40 | |||
| 41 | // Tells if the pointer "ptr" is aligned to "align" bytes. | ||
| 42 | #define IS_PTR_ALIGNED(ptr, align) (((uintptr_t)ptr & ((uintptr_t)(align-1))) == 0) | ||
| 43 | |||
| 44 | // Rounds up the number "n" to the next greater multiple of "align" | ||
| 45 | #define ALIGN_NUMBER(n, align) (((n) + (align)-1) & (~((align)-1))) | ||
| 46 | |||
| 47 | // Rounds up the pointer address "ptr" to the next greater multiple of "align" | ||
| 48 | #define ALIGN_POINTER(ptr, align) (((uintptr_t)(ptr) + (align)-1) & (~(uintptr_t)((align)-1))) | ||
| 49 | |||
| 50 | #ifdef __cplusplus | ||
| 51 | |||
| 52 | #include <cassert> | ||
| 53 | #include <cstdlib> | ||
| 54 | #include <cstdint> | ||
| 55 | #include "config.h" | ||
| 56 | |||
| 57 | #if defined(MSVC) && _MSC_VER<1400 | ||
| 58 | // needed for VS2013, otherwise C++11 'alignas' works | ||
| 59 | #define avs_alignas(x) __declspec(align(x)) | ||
| 60 | #else | ||
| 61 | // assumes C++11 support | ||
| 62 | #define avs_alignas(x) alignas(x) | ||
| 63 | #endif | ||
| 64 | |||
| 65 | template<typename T> | ||
| 66 | 35 | static bool IsPtrAligned(T* ptr, size_t align) | |
| 67 | { | ||
| 68 |
4/8bool IsPtrAligned<unsigned char const>(unsigned char const*, unsigned long):
✓ Branch 2 → 3 taken 7 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 5 not taken.
bool IsPtrAligned<unsigned char>(unsigned char*, unsigned long):
✓ Branch 2 → 3 taken 28 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 28 times.
✗ Branch 3 → 5 not taken.
|
35 | assert(IS_POWER2(align)); |
| 69 | 35 | return (bool)IS_PTR_ALIGNED(ptr, align); | |
| 70 | } | ||
| 71 | |||
| 72 | template<typename T> | ||
| 73 | 236121 | static T AlignNumber(T n, T align) | |
| 74 | { | ||
| 75 |
4/8int AlignNumber<int>(int, int):
✓ Branch 2 → 3 taken 3241 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 3241 times.
✗ Branch 3 → 5 not taken.
unsigned long AlignNumber<unsigned long>(unsigned long, unsigned long):
✓ Branch 2 → 3 taken 232880 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 232880 times.
✗ Branch 3 → 5 not taken.
|
236121 | assert(IS_POWER2(align)); |
| 76 | 236121 | return ALIGN_NUMBER(n, align); | |
| 77 | } | ||
| 78 | |||
| 79 | template<typename T> | ||
| 80 | 903 | static T* AlignPointer(T* ptr, size_t align) | |
| 81 | { | ||
| 82 |
2/4✓ Branch 2 → 3 taken 903 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 903 times.
✗ Branch 3 → 5 not taken.
|
903 | assert(IS_POWER2(align)); |
| 83 | 903 | return (T*)ALIGN_POINTER(ptr, align); | |
| 84 | } | ||
| 85 | |||
| 86 | extern "C" | ||
| 87 | { | ||
| 88 | #else | ||
| 89 | #include <stdlib.h> | ||
| 90 | #endif // __cplusplus | ||
| 91 | |||
| 92 | // Returns a new buffer that is at least the size "nbytes". | ||
| 93 | // The buffer will be aligned to "align" bytes. | ||
| 94 | // Returns NULL on error. On successful allocation, | ||
| 95 | // the returned buffer must be freed using "avs_free". | ||
| 96 | 3 | inline void* avs_malloc(size_t nbytes, size_t align) | |
| 97 | { | ||
| 98 |
2/4✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 4 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3 times.
|
3 | if (!IS_POWER2(align)) |
| 99 | ✗ | return NULL; | |
| 100 | |||
| 101 | 3 | size_t offset = sizeof(void*) + align - 1; | |
| 102 | |||
| 103 | 3 | void *orig = malloc(nbytes + offset); | |
| 104 |
1/2✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 3 times.
|
3 | if (orig == NULL) |
| 105 | ✗ | return NULL; | |
| 106 | |||
| 107 | 3 | void **aligned = (void**)(((uintptr_t)orig + (uintptr_t)offset) & (~(uintptr_t)(align-1))); | |
| 108 | 3 | aligned[-1] = orig; | |
| 109 | 3 | return aligned; | |
| 110 | } | ||
| 111 | |||
| 112 | // Buffers allocated using "avs_malloc" must be freed | ||
| 113 | // using "avs_free" instead of "free". | ||
| 114 | 3 | inline void avs_free(void *ptr) | |
| 115 | { | ||
| 116 | // Mirroring free()'s semantic requires us to accept NULLs | ||
| 117 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3 times.
|
3 | if (ptr == NULL) |
| 118 | ✗ | return; | |
| 119 | |||
| 120 | 3 | free(((void**)ptr)[-1]); | |
| 121 | } | ||
| 122 | |||
| 123 | #ifdef __cplusplus | ||
| 124 | } // extern "C" | ||
| 125 | |||
| 126 | // The point of these undef's is to force using the template functions | ||
| 127 | // if we are in C++ mode. For C, the user can rely only on the macros. | ||
| 128 | #undef IS_PTR_ALIGNED | ||
| 129 | #undef ALIGN_NUMBER | ||
| 130 | #undef ALIGN_POINTER | ||
| 131 | |||
| 132 | #endif // __cplusplus | ||
| 133 | |||
| 134 | #endif //AVS_ALIGNMENT_H | ||
| 135 |