utils 按作用拆成 log/macros/memory 三个模块

This commit is contained in:
2026-03-23 19:05:39 +08:00
parent fa93b3d733
commit 67f0c169f5
15 changed files with 179 additions and 175 deletions

View File

@@ -29,7 +29,7 @@ option(BUILD_TESTING "Build tests" OFF)
add_executable(${APP_NAME} add_executable(${APP_NAME}
${SOURCE_DIR}/wm.c ${SOURCE_DIR}/wm.c
${SOURCE_DIR}/utils.c ${SOURCE_DIR}/base/log.c
${SOURCE_DIR}/buffer.c ${SOURCE_DIR}/buffer.c
${SOURCE_DIR}/backtrace.c ${SOURCE_DIR}/backtrace.c
${SOURCE_DIR}/monitor.c ${SOURCE_DIR}/monitor.c

View File

@@ -3,9 +3,9 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "base/memory.h"
#include "core/backend.h" #include "core/backend.h"
#include "core/types.h" #include "core/types.h"
#include "utils.h"
static inline int32_t right(rect_t a) { return a.x + a.width; } static inline int32_t right(rect_t a) { return a.x + a.width; }
static inline int32_t bottom(rect_t a) { return a.y + a.height; } static inline int32_t bottom(rect_t a) { return a.y + a.height; }

View File

@@ -12,8 +12,9 @@
#include <xcb/xproto.h> #include <xcb/xproto.h>
#include "backend/output_utils.h" #include "backend/output_utils.h"
#include "base/log.h"
#include "base/memory.h"
#include "core/types.h" #include "core/types.h"
#include "utils.h"
struct backend_t { struct backend_t {
xcb_connection_t *conn; xcb_connection_t *conn;

View File

@@ -1,4 +1,4 @@
#include "utils.h" #include "base/log.h"
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
@@ -19,9 +19,6 @@ const char *current_time_str(void) {
return buffer; return buffer;
} }
/**
* Print error and exit with EXIT_FAILURE code.
*/
void _fatal(int line, const char *fct, const char *file, const char *fmt, ...) { void _fatal(int line, const char *fct, const char *file, const char *fmt, ...) {
va_list ap; va_list ap;
@@ -34,9 +31,6 @@ void _fatal(int line, const char *fct, const char *file, const char *fmt, ...) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/**
* Print error message on stderr
*/
void _warn(int line, const char *fct, const char *file, const char *fmt, ...) { void _warn(int line, const char *fct, const char *file, const char *fmt, ...) {
va_list ap; va_list ap;

32
src/base/log.h Normal file
View File

@@ -0,0 +1,32 @@
#pragma once
#include <stdarg.h>
#include <stdio.h>
#define fatal(format, ...) \
_fatal(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
void _fatal(int line, const char *function, const char *file,
const char *format, ...) __attribute__((noreturn))
__attribute__((format(printf, 4, 5)));
#define warn(format, ...) \
_warn(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
void _warn(int line, const char *function, const char *file, const char *format,
...) __attribute__((format(printf, 4, 5)));
const char *current_time_str(void);
#if defined(RELEASE)
#define logger(format, ...)
#elif defined(LOG_FILE)
static inline void logger(const char *format, ...) {
va_list ap;
va_start(ap, format);
FILE *log_file = fopen(LOG_FILE, "a+t");
vfprintf(log_file, format, ap);
va_end(ap);
fclose(log_file);
}
#else
#define logger(format, ...) printf(format, ##__VA_ARGS__)
#endif

29
src/base/macros.h Normal file
View File

@@ -0,0 +1,29 @@
#pragma once
#include <stddef.h>
#include <sys/types.h>
#define ssizeof(foo) (ssize_t)sizeof(foo)
#define countof(foo) (ssizeof(foo) / ssizeof(foo[0]))
#ifdef __GNUC__
#define likely(expr) __builtin_expect(!!(expr), 1)
#define unlikely(expr) __builtin_expect((expr), 0)
#else
#define likely(expr) expr
#define unlikely(expr) expr
#endif
#ifdef MIN
#undef MIN
#endif
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifdef MAX
#undef MAX
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif

73
src/base/memory.h Normal file
View File

@@ -0,0 +1,73 @@
#pragma once
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "base/macros.h"
#define p_alloc_nr(x) (((x) + 16) * 3 / 2)
#define p_new(type, count) ((type *)xmalloc(sizeof(type) * (count)))
#define p_clear(p, count) ((void)memset((p), 0, sizeof(*(p)) * (count)))
#define p_realloc(pp, count) xrealloc((void *)(pp), sizeof(**(pp)) * (count))
#define p_copy(src, count) xmemcopy((src), sizeof(*(src)) * (count))
#define p_delete(mem_p) \
do { \
void **__ptr = (void **)(mem_p); \
free(*__ptr); \
*(void **)__ptr = nullptr; \
} while (0)
static inline char *p_strdup(const char *text) {
char *r = strdup(text);
if (!r) abort();
return r;
}
static inline char *p_strdup_nullable(const char *text) {
if (!text) return nullptr;
return p_strdup(text);
}
static inline void *__attribute__((malloc)) xmalloc(ssize_t size) {
void *ptr;
if (size <= 0) return nullptr;
ptr = calloc(1, size);
if (!ptr) abort();
return ptr;
}
static inline void *xmemcopy(const void *src, size_t n) {
if (!n) return nullptr;
void *mem = xmalloc(n);
void *ret = memcpy(mem, src, n);
if (ret != mem) abort();
return ret;
}
static inline void xrealloc(void **ptr, ssize_t newsize) {
if (newsize <= 0)
p_delete(ptr);
else {
*ptr = realloc(*ptr, newsize);
if (!*ptr) abort();
}
}
/*
* Unlike strlen(), a_strlen() accepts nullptr and returns 0 in that case.
*/
static inline ssize_t a_strlen(const char *s) { return s ? strlen(s) : 0; }
static constexpr size_t INIT_CAPACITY = 4;
static inline size_t next_capacity(size_t capacity) {
if (capacity) return capacity * 2;
return INIT_CAPACITY;
}

View File

@@ -4,7 +4,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include "utils.h" #include "base/log.h"
#include "base/memory.h"
static char *config_loader_join_path(const char *base, const char *suffix) { static char *config_loader_join_path(const char *base, const char *suffix) {
if (!base || !suffix) return nullptr; if (!base || !suffix) return nullptr;

View File

@@ -4,7 +4,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "utils.h" #include "base/memory.h"
void layout_result_init(layout_result_t *result) { void layout_result_init(layout_result_t *result) {
result->item_count = 0; result->item_count = 0;

View File

@@ -2,10 +2,10 @@
#include <stddef.h> #include <stddef.h>
#include "base/memory.h"
#include "core/backend.h" #include "core/backend.h"
#include "core/state.h" #include "core/state.h"
#include "core/wm_desc.h" #include "core/wm_desc.h"
#include "utils.h"
static bool runtime_workspace_desc_has_valid_layouts( static bool runtime_workspace_desc_has_valid_layouts(
const layout_registry_t *layouts, const workspace_desc_t *workspace) { const layout_registry_t *layouts, const workspace_desc_t *workspace) {

View File

@@ -3,9 +3,10 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include "base/log.h"
#include "base/memory.h"
#include "core/types.h" #include "core/types.h"
#include "core/wm_desc.h" #include "core/wm_desc.h"
#include "utils.h"
void state_init(state_t *state, const output_info_t *outputs, void state_init(state_t *state, const output_info_t *outputs,
size_t output_count, const workspace_desc_t *workspaces, size_t output_count, const workspace_desc_t *workspaces,

View File

@@ -85,8 +85,8 @@ typedef struct state_t {
* workspace若某个 output 没有任何归属 workspacestate_init() 会失败。 * workspace若某个 output 没有任何归属 workspacestate_init() 会失败。
*/ */
void state_init(state_t *state, const output_info_t *outputs, void state_init(state_t *state, const output_info_t *outputs,
size_t output_count, const workspace_desc_t *workspaces, size_t output_count, const workspace_desc_t *workspaces,
size_t workspace_count); size_t workspace_count);
void state_cleanup(state_t *state); void state_cleanup(state_t *state);
/* /*
@@ -95,20 +95,18 @@ void state_cleanup(state_t *state);
* 这组接口对外只提供只读访问。 * 这组接口对外只提供只读访问。
* workspace 的运行期可变状态必须通过专门的 state 级更新接口修改。 * workspace 的运行期可变状态必须通过专门的 state 级更新接口修改。
*/ */
const workspace_t *state_workspace_get(const state_t *state, const workspace_t *state_workspace_get(const state_t *state, workspace_id_t id);
workspace_id_t id);
const workspace_t *state_workspace_at(const state_t *state, size_t index); const workspace_t *state_workspace_at(const state_t *state, size_t index);
bool state_workspace_cycle_layout(state_t *state, bool state_workspace_cycle_layout(state_t *state, workspace_id_t workspace_id);
workspace_id_t workspace_id);
bool state_workspace_set_layout_by_index(state_t *state, bool state_workspace_set_layout_by_index(state_t *state,
workspace_id_t workspace_id,
size_t index);
bool state_workspace_set_layout_by_id(state_t *state,
workspace_id_t workspace_id, workspace_id_t workspace_id,
layout_id_t layout_id); size_t index);
bool state_workspace_set_layout_by_id(state_t *state,
workspace_id_t workspace_id,
layout_id_t layout_id);
void state_workspace_set_focused_window(state_t *state, void state_workspace_set_focused_window(state_t *state,
workspace_id_t workspace_id, workspace_id_t workspace_id,
window_id_t window_id); window_id_t window_id);
size_t state_workspace_count(const state_t *state); size_t state_workspace_count(const state_t *state);
bool state_workspace_valid(const state_t *state, workspace_id_t id); bool state_workspace_valid(const state_t *state, workspace_id_t id);
@@ -121,10 +119,9 @@ bool state_workspace_valid(const state_t *state, workspace_id_t id);
const output_t *state_output_get(const state_t *state, output_id_t id); const output_t *state_output_get(const state_t *state, output_id_t id);
const output_t *state_output_at(const state_t *state, size_t index); const output_t *state_output_at(const state_t *state, size_t index);
void state_output_set_workarea(state_t *state, output_id_t output_id, void state_output_set_workarea(state_t *state, output_id_t output_id,
rect_t workarea); rect_t workarea);
void state_output_set_current_workspace(state_t *state, void state_output_set_current_workspace(state_t *state, output_id_t output_id,
output_id_t output_id, workspace_id_t workspace_id);
workspace_id_t workspace_id);
size_t state_output_count(const state_t *state); size_t state_output_count(const state_t *state);
bool state_output_valid(const state_t *state, output_id_t id); bool state_output_valid(const state_t *state, output_id_t id);
@@ -142,8 +139,7 @@ bool state_output_valid(const state_t *state, output_id_t id);
* info 提供 backend 已探测到的窗口基础信息。 * info 提供 backend 已探测到的窗口基础信息。
* workspace 归属与其他策略相关字段由后续 state_window_* 接口设置。 * workspace 归属与其他策略相关字段由后续 state_window_* 接口设置。
*/ */
const window_t *state_window_add(state_t *state, const window_t *state_window_add(state_t *state, const window_info_t *info);
const window_info_t *info);
const window_t *state_window_get(const state_t *state, window_id_t id); const window_t *state_window_get(const state_t *state, window_id_t id);
const window_t *state_window_at(const state_t *state, size_t index); const window_t *state_window_at(const state_t *state, size_t index);
/* 删除窗口,并同步从 stack_order[] 中移除。 */ /* 删除窗口,并同步从 stack_order[] 中移除。 */
@@ -152,31 +148,31 @@ size_t state_window_count(const state_t *state);
/* state 持有的单个 window 状态更新接口 */ /* state 持有的单个 window 状态更新接口 */
void state_window_set_workspace(state_t *state, window_id_t window_id, void state_window_set_workspace(state_t *state, window_id_t window_id,
workspace_id_t workspace_id); workspace_id_t workspace_id);
void state_window_set_geometry_mode(state_t *state, window_id_t window_id, void state_window_set_geometry_mode(state_t *state, window_id_t window_id,
window_geometry_mode_t geometry_mode); window_geometry_mode_t geometry_mode);
void state_window_set_floating(state_t *state, window_id_t window_id, void state_window_set_floating(state_t *state, window_id_t window_id,
bool floating); bool floating);
void state_window_set_sticky(state_t *state, window_id_t window_id, void state_window_set_sticky(state_t *state, window_id_t window_id,
bool sticky); bool sticky);
void state_window_set_urgent(state_t *state, window_id_t window_id, void state_window_set_urgent(state_t *state, window_id_t window_id,
bool urgent); bool urgent);
void state_window_set_fixed_size(state_t *state, window_id_t window_id, void state_window_set_fixed_size(state_t *state, window_id_t window_id,
bool fixed_size); bool fixed_size);
void state_window_set_skip_taskbar(state_t *state, window_id_t window_id, void state_window_set_skip_taskbar(state_t *state, window_id_t window_id,
bool skip_taskbar); bool skip_taskbar);
void state_window_set_float_rect(state_t *state, window_id_t window_id, void state_window_set_float_rect(state_t *state, window_id_t window_id,
rect_t float_rect); rect_t float_rect);
void state_window_set_frame_rect(state_t *state, window_id_t window_id, void state_window_set_frame_rect(state_t *state, window_id_t window_id,
rect_t frame_rect); rect_t frame_rect);
bool state_window_set_title(state_t *state, window_id_t window_id, bool state_window_set_title(state_t *state, window_id_t window_id,
const char *title); const char *title);
bool state_window_set_app_id(state_t *state, window_id_t window_id, bool state_window_set_app_id(state_t *state, window_id_t window_id,
const char *app_id); const char *app_id);
bool state_window_set_class(state_t *state, window_id_t window_id, bool state_window_set_class(state_t *state, window_id_t window_id,
const char *class_name); const char *class_name);
bool state_window_set_instance(state_t *state, window_id_t window_id, bool state_window_set_instance(state_t *state, window_id_t window_id,
const char *instance_name); const char *instance_name);
/* /*
* state 持有的堆叠顺序接口 * state 持有的堆叠顺序接口

View File

@@ -51,7 +51,7 @@ static inline bool workspace_desc_layouts_valid(
} }
static inline bool workspace_desc_valid(const workspace_desc_t *workspace, static inline bool workspace_desc_valid(const workspace_desc_t *workspace,
size_t output_count) { size_t output_count) {
if (!workspace || !workspace->name) return false; if (!workspace || !workspace->name) return false;
if (workspace->output_index >= output_count) return false; if (workspace->output_index >= output_count) return false;

View File

@@ -1,131 +1,8 @@
#pragma once #pragma once
#include <stdarg.h> /* Compatibility umbrella header. Prefer including headers from src/base in new
#include <stddef.h> * code. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ssizeof(foo) (ssize_t)sizeof(foo) #include "base/log.h"
#define countof(foo) (ssizeof(foo) / ssizeof(foo[0])) #include "base/macros.h"
#include "base/memory.h"
#define p_alloc_nr(x) (((x) + 16) * 3 / 2)
#define p_new(type, count) ((type *)xmalloc(sizeof(type) * (count)))
#define p_clear(p, count) ((void)memset((p), 0, sizeof(*(p)) * (count)))
#define p_realloc(pp, count) xrealloc((void *)(pp), sizeof(**(pp)) * (count))
#define p_copy(src, count) xmemcopy((src), sizeof(*(src)) * (count))
#define p_delete(mem_p) \
do { \
void **__ptr = (void **)(mem_p); \
free(*__ptr); \
*(void **)__ptr = nullptr; \
} while (0)
#ifdef __GNUC__
#define likely(expr) __builtin_expect(!!(expr), 1)
#define unlikely(expr) __builtin_expect((expr), 0)
#else
#define likely(expr) expr
#define unlikely(expr) expr
#endif
static inline char *p_strdup(const char *text) {
char *r = strdup(text);
if (!r) abort();
return r;
}
static inline char *p_strdup_nullable(const char *text) {
if (!text) return nullptr;
return p_strdup(text);
}
static inline void *__attribute__((malloc)) xmalloc(ssize_t size) {
void *ptr;
if (size <= 0) return nullptr;
ptr = calloc(1, size);
if (!ptr) abort();
return ptr;
}
static inline void *xmemcopy(const void *src, size_t n) {
if (!n) return nullptr;
void *mem = xmalloc(n);
void *ret = memcpy(mem, src, n);
if (ret != mem) abort();
return ret;
}
static inline void xrealloc(void **ptr, ssize_t newsize) {
if (newsize <= 0)
p_delete(ptr);
else {
*ptr = realloc(*ptr, newsize);
if (!*ptr) abort();
}
}
/**
* @brief nullptr resistant strlen.
*
* Unlike it's libc sibling, a_strlen returns a ssize_t, and supports its
* argument being nullptr.
*
* @param s the string.
* @return the string length (or 0 if s is nullptr).
*/
static inline ssize_t a_strlen(const char *s) { return s ? strlen(s) : 0; }
#define fatal(format, ...) \
_fatal(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
void _fatal(int line, const char *function, const char *file,
const char *format, ...) __attribute__((noreturn))
__attribute__((format(printf, 4, 5)));
#define warn(format, ...) \
_warn(__LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
void _warn(int line, const char *function, const char *file, const char *format,
...) __attribute__((format(printf, 4, 5)));
const char *current_time_str(void);
#if defined(RELEASE)
#define logger(format, ...)
#elif defined(LOG_FILE)
static inline void logger(const char *format, ...) {
va_list ap;
va_start(ap, format);
FILE *log_file = fopen(LOG_FILE, "a+t");
vfprintf(log_file, format, ap);
va_end(ap);
fclose(log_file);
}
#else
#define logger(format, ...) printf(format, ##__VA_ARGS__)
#endif
#ifdef MIN
#undef MIN
#endif
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifdef MAX
#undef MAX
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
static constexpr size_t INIT_CAPACITY = 4;
static inline size_t next_capacity(size_t capacity) {
if (capacity) return capacity * 2;
return INIT_CAPACITY;
}

View File

@@ -2,7 +2,7 @@ set(TEST_APP_NAME "zdwm-tests")
add_executable(${TEST_APP_NAME} add_executable(${TEST_APP_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/main.c ${CMAKE_CURRENT_SOURCE_DIR}/main.c
${SOURCE_DIR}/utils.c ${SOURCE_DIR}/base/log.c
${SOURCE_DIR}/backend/output_utils.c ${SOURCE_DIR}/backend/output_utils.c
${SOURCE_DIR}/backend/x11/backend.c ${SOURCE_DIR}/backend/x11/backend.c
${SOURCE_DIR}/core/layout.c ${SOURCE_DIR}/core/layout.c