shayla/utils.h -rw-r--r-- 4.7 KiB View raw
                                                                                
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
158
159
/**
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef UTILS_H
# define UTILS_H

# include <fcntl.h>
# include <unistd.h>
# include <stdbool.h>
# include <string.h>
# include <dirent.h>
# include <sys/types.h>
# include <sys/stat.h>
# if defined(__APPLE__) || defined(__FreeBSD__)
#  include <copyfile.h>
# else
#  include <sys/sendfile.h>
# endif

/* Compile-time assertion */
# define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]
# define COUNT_OF(ptr) sizeof(ptr) / sizeof(ptr[0])

# define QUOTE_ME(x) #x
# define STR(x) QUOTE_ME(x)

# define EMPTY_STR() { '\0' }
# define STR_OR_EMPTY(str) (str != NULL ? str : "")
# define STR_NULL_OR_EMPTY(str) (str == NULL || (str != NULL && *str == '\0'))
# define FREE(ptr) free(ptr); ptr = NULL;
# define UNUSED_ARG(arg) (void)arg
# define STRLEN(str) str == NULL ? 0 : strlen(str)

/* Magic things */
# undef offsetof
# ifdef __compiler_offsetof
#  define offsetof(TYPE, MEMBER)        __compiler_offsetof(TYPE, MEMBER)
# else
#  define offsetof(TYPE, MEMBER)        ((size_t)&((TYPE *)0)->MEMBER)
# endif /* __compiler_offsetof */

# define container_of(ptr, type, member) ({\
    const typeof( ((type *)0)->member ) *__mptr = (ptr);\
    (type *)( (char *)__mptr - offsetof(type,member) );})

# define ___UNIQ(name, n) name##n
# define __UNIQ(name, n) ___UNIQ(name, n)
# define _UNIQ(name, n) __UNIQ(name, n)
# define UNIQ(name) _UNIQ(name, __LINE__)

# define __STATIC_ARRAY_FOREACH(index, keep, item, array) \
    for (size_t keep = 1, index = 0; keep && index < COUNT_OF(array); keep = !keep, index++) \
        for (item = &array[index]; keep; keep = !keep)

# define STATIC_ARRAY_FOREACH_I(index, item, array) __STATIC_ARRAY_FOREACH(index, UNIQ(__foreach_keep), item, array)
# define STATIC_ARRAY_FOREACH(item, array) __STATIC_ARRAY_FOREACH(UNIQ(__foreach_index), UNIQ(__foreach_keep), item, array)

# define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
# define MIN(X, Y) ((X) < (Y) ? (X) : (Y))

# define __HOT_FUNCTION         __attribute__((hot))
# define __COLD_FUNCTION        __attribute__((cold))
# ifndef __DEPRECATED
#  define __DEPRECATED          __attribute__((deprecated))
# endif /* __DEPRECATED */
# define __CONST_FUNCTION       __attribute__((const))
# define __NORETURN_FUNCTION    __attribute__((noreturn))
# define __INLINE_FUNCTION      __attribute__((always_inline))
# define __NON_NULL_ARGS(...)   __attribute__((nonnull(__VA_ARGS__)))
# define __NON_NULL_ALL         __attribute__((nonnull))
# define __PURE_FUNCTION        __attribute__((pure))
# define __PRINTF_FUNCTION(...) __attribute__((format (printf, __VA_ARGS__)))
# define likely(x)              __builtin_expect((x), 1)
# define unlikely(x)            __builtin_expect((x), 0)

# define UNREACHABLE_CODE       assert(!"Unreachable code " __FILE__ ": " STR(__FUNCTION__))

/*!
 * \brief Get a filename from a path
 */
static inline char *get_filename(char *path)
{
    size_t      len = strlen(path);

    for (; len > 0 && path[len] != '/'; len--)
        ;

    if (len == 0)
        return path;
    return path + len + 1;
}

/*!
 * \brief Create a directory if non-existent from a path
 */
static inline bool create_dir(const char *path)
{
    DIR *fd = opendir(path);

    if (fd == NULL)
    {
        if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1)
            return false;
    }
    else
        closedir(fd);

    return true;
}

/*!
 * \brief Zero-buffering kernel space copy of a file
 */
static inline bool fast_copy(const char *from, const char *to)
{
    int         in_fd;
    int         out_fd;
    int         result;

    in_fd = open(from, O_RDONLY);
    if (in_fd == -1)
        return false;

    out_fd = creat(to, 0660);
    if (out_fd == -1)
    {
        close(in_fd);
        return false;
    }

#if defined(__APPLE__) || defined(__FreeBSD__)
    result = fcopyfile(in_fd, out_fd, 0, COPYFILE_ALL);
#else
    off_t       bytesCopied = 0;
    struct stat fileinfo = { 0 };

    fstat(in_fd, &fileinfo);
    result = sendfile(out_fd, in_fd, &bytesCopied, fileinfo.st_size);
#endif

    close(in_fd);
    close(out_fd);
    return result != -1;
}

#endif /* UTILS_H */