From 8605f2ec320528420362089e723cd3b56f15cc8d Mon Sep 17 00:00:00 2001 From: tanchenxi Date: Fri, 28 Nov 2025 14:22:39 +0800 Subject: [PATCH 1/2] =?UTF-8?q?1.=20=E6=B7=BB=E5=8A=A0linux=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0=E6=94=AF=E6=8C=81=202.=20=E6=B7=BB=E5=8A=A0cmake?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 26 ++ example_user.c | 200 +++++++--- libscl/.gitignore | 27 ++ libscl/CMakeLists.txt | 31 ++ libscl/include/libscl/SCL.h | 310 +++++++++++++++ libscl/include/libscl/SCL_map.h | 133 +++++++ libscl/src/map.c | 675 ++++++++++++++++++++++++++++++++ main.c | 27 +- 8 files changed, 1353 insertions(+), 76 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 libscl/.gitignore create mode 100644 libscl/CMakeLists.txt create mode 100644 libscl/include/libscl/SCL.h create mode 100644 libscl/include/libscl/SCL_map.h create mode 100644 libscl/src/map.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c6a153c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.5) + +project(EzBtn LANGUAGES C) +add_subdirectory(libscl) +add_executable(EzBtn main.c + ebtn/bit_array.h + ebtn/ebtn.c + ebtn/ebtn.h + example_user.c +) + +include_directories(EzBtn PUBLIC + ebtn +) + +target_link_libraries(EzBtn LINK_PRIVATE scl pthread) + +target_include_directories(EzBtn PRIVATE + $ +) + +include(GNUInstallDirs) +install(TARGETS EzBtn + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) diff --git a/example_user.c b/example_user.c index ab0dd11..566920c 100644 --- a/example_user.c +++ b/example_user.c @@ -1,12 +1,21 @@ -#include "windows.h" #include #include - +#include +#include +#include #include "ebtn.h" - -static LARGE_INTEGER freq, sys_start_time; +#include +#include +#include +#include +#include +#include // 新增:用于错误处理 +#include // 新增:用于字符串操作 +#include // 新增:系统类型定义 +#include "libscl/SCL_map.h" +SCL_map_t btn_info_map; +#define KEY_DEVICE "/dev/input/event1" // 按键设备节点 static uint32_t get_tick(void); - typedef enum { USER_BUTTON_0 = 0, @@ -28,6 +37,103 @@ typedef enum USER_BUTTON_COMBO_3, USER_BUTTON_COMBO_MAX, } user_button_t; +static struct termios old_termios; +typedef struct key_btn_info_t +{ + int key_value; + char key_status; +}key_btn_info_t; +user_button_t get_key_input(void) { + static int fd = -1; + struct input_event ev; + ssize_t n; + + // 首次调用时打开设备 + if (fd < 0) { + printf("Trying to open input device %s\n", KEY_DEVICE); + fd = open(KEY_DEVICE, O_RDONLY); + if (fd < 0) { + perror("Failed to open input device"); + return USER_BUTTON_INVALID; + } + printf("Successfully opened input device %s\n", KEY_DEVICE); + } + + // 读取输入事件 + n = read(fd, &ev, sizeof(ev)); + if (n == -1) { + if (errno != EAGAIN) { + perror("Error reading input device"); + close(fd); + fd = -1; + } + return USER_BUTTON_INVALID; + } + else if (n != sizeof(ev)) { + fprintf(stderr, "Read incomplete input event (%zd bytes)\n", n); + return USER_BUTTON_INVALID; + } + + // printf("Input event: type=%d code=%d value=%d\n", ev.type, ev.code, ev.value); + int key_value = USER_BUTTON_INVALID; + int key_status = 0; + if (ev.type == EV_KEY) { + key_status = ev.value; + switch (ev.code) { + case KEY_0: + key_value = USER_BUTTON_0; + break; + case KEY_1: + key_value = USER_BUTTON_1; + break; + case KEY_2: + key_value = USER_BUTTON_2; + break; + case KEY_3: + key_value = USER_BUTTON_3; + break; + case KEY_4: + key_value = USER_BUTTON_4; + break; + case KEY_5: + key_value = USER_BUTTON_5; + break; + case KEY_6: + key_value = USER_BUTTON_6; + break; + case KEY_7: + key_value = USER_BUTTON_7; + break; + case KEY_8: + key_value = USER_BUTTON_8; + break; + case KEY_9: + key_value = USER_BUTTON_9; + break; + default: + printf("Unmapped key code: %d\n", ev.code); + break; + } + if (key_value != USER_BUTTON_INVALID){ + key_btn_info_t *key_btn_info = NULL; + key_btn_info = scl_map_access(btn_info_map, key_value); + if (key_btn_info == NULL){ + key_btn_info = malloc(sizeof(key_btn_info_t)); + memset(key_btn_info, 0, sizeof(key_btn_info_t)); + key_btn_info->key_value = key_value; + key_btn_info->key_status = key_status; + scl_map_insert(btn_info_map, key_value, key_btn_info); + } + key_btn_info->key_value = key_value; + key_btn_info->key_status = key_status; + return key_value; + } + } + return USER_BUTTON_INVALID; +} + + + /* User defined settings */ static const ebtn_btn_param_t defaul_ebtn_param = EBTN_PARAMS_INIT(20, 0, 20, 300, 200, 500, 10); @@ -109,45 +215,7 @@ static ebtn_btn_combo_dyn_t btns_combo_dyn[] = { uint32_t last_time_keys_combo[USER_BUTTON_COMBO_MAX - USER_BUTTON_COMBO_0] = {0}; -static int windows_get_match_key(uint16_t key_id) -{ - int key = 0; - switch (key_id) - { - case USER_BUTTON_0: - key = '0'; - break; - case USER_BUTTON_1: - key = '1'; - break; - case USER_BUTTON_2: - key = '2'; - break; - case USER_BUTTON_3: - key = '3'; - break; - case USER_BUTTON_4: - key = '4'; - break; - case USER_BUTTON_5: - key = '5'; - break; - case USER_BUTTON_6: - key = '6'; - break; - case USER_BUTTON_7: - key = '7'; - break; - case USER_BUTTON_8: - key = '8'; - break; - case USER_BUTTON_9: - key = '9'; - break; - } - return key; -} /** * \brief Get input state callback @@ -160,7 +228,11 @@ uint8_t prv_btn_get_state(struct ebtn_btn *btn) * Function will return negative number if button is pressed, * or zero if button is releases */ - return GetAsyncKeyState(windows_get_match_key(btn->key_id)) < 0; + key_btn_info_t *key_btn_info = scl_map_access(btn_info_map, btn->key_id); + if (key_btn_info){ + return key_btn_info->key_status; + } + return 0; } /** @@ -173,7 +245,6 @@ void prv_btn_event(struct ebtn_btn *btn, ebtn_evt_t evt) { const char *s; uint32_t color, keepalive_cnt = 0; - HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); uint32_t diff_time = 0; uint32_t *diff_time_ptr = NULL; if (btn->key_id < USER_BUTTON_MAX) @@ -198,35 +269,43 @@ void prv_btn_event(struct ebtn_btn *btn, ebtn_evt_t evt) if (evt == EBTN_EVT_KEEPALIVE) { s = "KEEPALIVE"; - color = FOREGROUND_RED | FOREGROUND_BLUE; } else if (evt == EBTN_EVT_ONPRESS) { s = "ONPRESS"; - color = FOREGROUND_GREEN; } else if (evt == EBTN_EVT_ONRELEASE) { s = "ONRELEASE"; - color = FOREGROUND_BLUE; } else if (evt == EBTN_EVT_ONCLICK) { s = "ONCLICK"; - color = FOREGROUND_RED | FOREGROUND_GREEN; } else { s = "UNKNOWN"; - color = FOREGROUND_RED; } - SetConsoleTextAttribute(hConsole, color); printf("[%7u][%6u] ID(hex):%4x, evt: %10s, keep-alive cnt: %3u, click cnt: %3u\r\n", (unsigned)get_tick(), (unsigned)diff_time, btn->key_id, s, (unsigned)ebtn_keepalive_get_count(btn), (unsigned)ebtn_click_get_count(btn)); - SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); } +void* key_listener_thread(void* arg) { + (void)arg; + + while (1) { + int key = get_key_input(); // 使用上述任一方法 + if (key != USER_BUTTON_INVALID) { + // atomic_store(&key_pressed, key); + } + usleep(10000); // 10ms间隔 + } + + return NULL; +} +static pthread_t key_thread; + /** * \brief Example function */ @@ -234,8 +313,9 @@ int example_user(void) { uint32_t time_last; printf("Application running\r\n"); - QueryPerformanceFrequency(&freq); - QueryPerformanceCounter(&sys_start_time); + btn_info_map = scl_map_new(); + pthread_create(&key_thread, NULL, key_listener_thread, NULL); + pthread_detach(key_thread); /* Define buttons */ ebtn_init(btns, EBTN_ARRAY_SIZE(btns), btns_combo, EBTN_ARRAY_SIZE(btns_combo), prv_btn_get_state, prv_btn_event); @@ -269,7 +349,7 @@ int example_user(void) ebtn_process(get_tick()); /* Artificial sleep to offload win process */ - Sleep(5); + usleep(5000); } return 0; } @@ -280,11 +360,7 @@ int example_user(void) */ static uint32_t get_tick(void) { - LONGLONG ret; - LARGE_INTEGER now; - - QueryPerformanceFrequency(&freq); - QueryPerformanceCounter(&now); - ret = now.QuadPart - sys_start_time.QuadPart; - return (uint32_t)((ret * 1000) / freq.QuadPart); + struct timespec ts; + clock_gettime (CLOCK_MONOTONIC_RAW, &ts); + return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; } diff --git a/libscl/.gitignore b/libscl/.gitignore new file mode 100644 index 0000000..862805a --- /dev/null +++ b/libscl/.gitignore @@ -0,0 +1,27 @@ +#ignore .metadata +.metadata +#ignore obj and lib file +*.[oa] + +#ignore temp files +*.swp +*.temp +*.tmp + +#python +*.pyc + + +#ignore android project files +*.properties +build.xml +proguard-project.txt + +#ignore android building directory +/obj/ +/gen/ +/bin/ +/build*/ +*/build/ +/install/ + diff --git a/libscl/CMakeLists.txt b/libscl/CMakeLists.txt new file mode 100644 index 0000000..7efc215 --- /dev/null +++ b/libscl/CMakeLists.txt @@ -0,0 +1,31 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) + +project(libscl C) + +#include(CMakeCStdOpt) + +set(HEADERS + include/libscl/SCL.h + include/libscl/SCL_map.h + ) + +set(SOURCES + src/map.c + ) + +add_library(scl ${SOURCES} ${HEADERS}) + +if (NOT WINDOWS) +target_compile_definitions(scl PUBLIC C99 _unix) +target_compile_options(scl PRIVATE -Wl,-no-undefined) +else() +target_compile_definitions(scl PUBLIC C99) +endif() + +target_include_directories(scl + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include/libscl + ) + +install(TARGETS scl DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) +install(DIRECTORY include/libscl DESTINATION ${CMAKE_INSTALL_PREFIX}/include) diff --git a/libscl/include/libscl/SCL.h b/libscl/include/libscl/SCL.h new file mode 100644 index 0000000..6341687 --- /dev/null +++ b/libscl/include/libscl/SCL.h @@ -0,0 +1,310 @@ +/* + * This file is part of the SCL software. + * The license which this software falls under is as follows: + * + * Copyright (C) 2004-2010 Douglas Jerome + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* ***************************************************************************** + +FILE NAME + + $RCSfile: SCL.h,v $ + $Revision: 1.13 $ + $Date: 2010/04/05 02:28:33 $ + +PROGRAM INFORMATION + + Developed by: SCL project + Developer: Douglas Jerome, drj, + +FILE DESCRIPTION + + Small Container Library: Common Constants, Data Types, etc. + + This file is intended to be an internal SCL header file included by + other SCL header files. There may be not much use for SCL client code + to directly include this file. + +CHANGE LOG + + 04apr10 drj Added context pointer to SCL_cbfn_t. + + 31mar10 drj Changed the silly check for NULL being zero to not + make a warning on 64-bit systems. + + 11jun06 drj Fixed the definition of NULL. + + 07jun06 drj Fixed "ASSERT" to be "SCL_ASSERT". + + 06jun06 drj Fixed my name. Added some #undef before #define. Made + better MSVC and GCC variations of SCL_CHECK_UINT32_1, + SCL_CHECK_UINT32_2. Added DEBUG support. + + 25sep05 drj Added _POSIX_C_SOURCE for "". + + 11jul05 drj Mindless rename of inclusion-control macro. + + 02dec04 drj Conditionally define uint32_t only on not Solaris. + + 02dec04 drj Conditionally define uint32_t only on Linux. + + 16nov04 drj File generation. + +***************************************************************************** */ + + +#ifndef SCL_H +#define SCL_H 1 + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ************************************************************************* */ +/* */ +/* I n c l u d e d F i l e s */ +/* */ +/* ************************************************************************* */ + +#ifdef C99 +# include +#endif +#ifdef _unix +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L /* posix.1 and posix.4 and MORE */ +# include +#endif + + +/* ************************************************************************* */ +/* */ +/* M a n i f e s t C o n s t a n t s */ +/* */ +/* ************************************************************************* */ + +#ifdef _WIN32 +# undef WIN32 +# define WIN32 +#endif + +/* + * Setup proper export, import keyword(s) for some compiler environments. + * This fun stuff is nicked from SDL (www.libsdl.org). + */ +#undef DECLS +#ifdef WIN32 +# ifdef SCL_EXPORTS +# define DECLS __declspec(dllexport) +# else +# define DECLS __declspec(dllimport) +# endif +#else +# define DECLS +#endif + +/* + * Setup proper C calling convention keyword(s) for some compiler environments. + * This fun stuff is nicked from SDL (www.libsdl.org). + */ +#undef DECLC +#ifdef WIN32 +# define DECLC _cdecl +#else +# define DECLC +#endif + +#undef DECLS +#define DECLS +#undef DECLC +#define DECLC +/* + * Set up a proper compiler-specific inline directive. This fun stuff is + * nicked from SDL (www.libsdl.org). + */ +#undef SCL_INLINE_OKAY +#ifdef __GNUC__ +# define SCL_INLINE_OKAY +#else +# if defined(_MSC_VER) || defined(__BORLANDC__) || \ + defined(__DMC__) || defined(__SC__) || \ + defined(__WATCOMC__) || defined(__LCC__) || defined(__ARMCC_VERSION) +# define SCL_INLINE_OKAY +# define __inline__ __inline +# else +# if !defined(__MRC__) && !defined(_SGI_SOURCE) +# define SCL_INLINE_OKAY +# define __inline__ inline +# endif +# endif +#endif +#ifndef SCL_INLINE_OKAY +# define __inline__ +#endif + +/* + * Set up a proper compiler-specific "unused" tag, for tagging unused variables + * and function arguments. + */ +#if defined( __GNUC__ ) && !defined( __cplusplus ) && !defined(IOS) +# define __unused__ __attribute__ ((unused)) +#else +# define __unused__ +#endif + +/* + * Once, I didn't have a NULL. It is a sad thing to not have a NULL. + */ +#ifndef NULL +# ifndef __cplusplus +# define NULL ((void*)0) +# else +# define NULL (0) +# endif +#endif + +/* + * This is a compile-time check for NULL being equal to 0. If NULL is non-zero + * then this next line should create a compile error. + */ +//typedef int SCL_CHECK_NULL[1-(((long long)NULL)*2)]; + + +/* ************************************************************************* */ +/* */ +/* D a t a T y p e s a n d S t r u c t u r e s */ +/* */ +/* ************************************************************************* */ + +//extern void*calloc(size_t,size_t); +//extern void free(void*); +#include + +#define SCL_ALLOCATOR(s) (calloc(1,s)) +#define SCL_DEALLOCATOR(x) (free(x)) + +/* + * This enumeration is the collection of return values that can be returned by + * various SCL functions. + */ +enum + { + SCL_OK = 0, /* all ok */ + SCL_ERROR = -1, /* general error */ + SCL_BADARG = -2, /* bad argument */ + SCL_CORRUPT = -3, /* internal corruption */ + SCL_NOMEM = -4, /* can't allocate memory */ + SCL_NOTFOUND = -5, /* can't find item */ + SCL_NOSVC = -6, /* service not available */ + SCL_DUPKEY = -7 /* duplicate key */ + }; + +/* + * + */ +//#ifndef SOLARIS +//#ifndef __uint32_t_defined +//typedef unsigned int uint32_t; +//#define __uint32_t_defined +//#endif +//#endif +/* + * This is a compile-time check for uint32_t being four bytes in size. If + * uint32_t is not four bytes in size, then these next lines should create a + * compile error. + */ + +#if defined(ADS) || defined(_MSC_VER) +typedef int SCL_CHECK_UINT32_1[4-sizeof(uint32_t)+1]; +typedef int SCL_CHECK_UINT32_2[sizeof(uint32_t)-4+1]; +#else +typedef int SCL_CHECK_UINT32_1[4-sizeof(uint32_t)]; +typedef int SCL_CHECK_UINT32_2[sizeof(uint32_t)-4]; +#endif + +/* + * Some SCL subsystems make use of client-provided callback functions. Client + * code provides function pointers (callbacks) and some SCL subsystems will + * invoke the client functions via these function callback pointers. These are + * the callback function pointer types: + */ +typedef int (*SCL_cbfn_t)(const char*,long,void*,void*); +typedef uint32_t (*SCL_mdfn_t)(const char*,size_t); +typedef void* (*SCL_getfn_t)(size_t); +typedef int (*SCL_putfn_t)(void*,size_t); + +/* + * Usefull commentary goes here. + */ +typedef void* SCL_iterator_t; + + +/* ************************************************************************* */ +/* */ +/* P u b l i c G l o b a l V a r i a b l e s */ +/* */ +/* ************************************************************************* */ + +/* (none) */ + + +/* ************************************************************************* */ +/* */ +/* F u n c t i o n P r o t o t y p e s */ +/* */ +/* ************************************************************************* */ + +/* (none) */ + + +/* ************************************************************************* */ +/* */ +/* D e b u g S u p p o r t */ +/* */ +/* ************************************************************************* */ + +#ifdef _DEBUG +# undef DEBUG +# define DEBUG +#endif + +#undef SCL_ASSERT +#define SCL_ASSERT(exp) ((void)0) +#ifdef DEBUG +# include +# undef SCL_ASSERT +# define SCL_ASSERT(exp) \ + {if (!(exp)) { \ + (void)fflush (stdout); \ + (void)fflush (stderr); \ + (void)fprintf(stderr, \ + "Assertion failed: FILE %s, LINE %u, EXPRESSION \"%s\".\n", \ + __FILE__,__LINE__,#exp); \ + (void)fflush (stderr); }} +#endif + + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/libscl/include/libscl/SCL_map.h b/libscl/include/libscl/SCL_map.h new file mode 100644 index 0000000..7cddbbd --- /dev/null +++ b/libscl/include/libscl/SCL_map.h @@ -0,0 +1,133 @@ +/* + * This file is part of the SCL software. + * The license which this software falls under is as follows: + * + * Copyright (C) 2004-2010 Douglas Jerome + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* ***************************************************************************** + +FILE NAME + + $RCSfile: SCL_map.h,v $ + $Revision: 1.6 $ + $Date: 2010/04/14 03:10:29 $ + +PROGRAM INFORMATION + + Developed by: SCL project + Developer: Douglas Jerome, drj, + +FILE DESCRIPTION + + Small Container Library: Map Container Implementation + +CHANGE LOG + + 04apr10 drj Added callback context pointer to scl_map_foreach(). + + 06jun06 drj Miscellaneous format finessing. + + 11jul05 drj Mindless rename of inclusion-control macro. + + 26nov04 drj Changed scl_map_update() to scl_map_replace(). + + 16nov04 drj File generation. + +***************************************************************************** */ + + +#ifndef SCL_MAP_H +#define SCL_MAP_H 1 + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ************************************************************************* */ +/* */ +/* I n c l u d e d F i l e s */ +/* */ +/* ************************************************************************* */ + +#ifdef _unix +# include +#endif +#include "SCL.h" + + +/* ************************************************************************* */ +/* */ +/* M a n i f e s t C o n s t a n t s */ +/* */ +/* ************************************************************************* */ + +/* (none) */ + + +/* ************************************************************************* */ +/* */ +/* D a t a T y p e s a n d S t r u c t u r e s */ +/* */ +/* ************************************************************************* */ + +typedef struct S_SCL_map_t* SCL_map_t; + + +/* ************************************************************************* */ +/* */ +/* P u b l i c G l o b a l V a r i a b l e s */ +/* */ +/* ************************************************************************* */ + +/* (none) */ + + +/* ************************************************************************* */ +/* */ +/* F u n c t i o n P r o t o t y p e s */ +/* */ +/* ************************************************************************* */ + +extern DECLS SCL_map_t DECLC scl_map_new (void); +extern DECLS void DECLC scl_map_del (SCL_map_t m); +extern DECLS void DECLC scl_map_erase (SCL_map_t m); +extern DECLS size_t DECLC scl_map_size (SCL_map_t m); +extern DECLS size_t DECLC scl_map_count (SCL_map_t m); +extern DECLS int DECLC scl_map_insert (SCL_map_t m, long k, const void* d); +extern DECLS int DECLC scl_map_replace (SCL_map_t m, long k, const void* d); +extern DECLS void* DECLC scl_map_remove (SCL_map_t m, long k); +extern DECLS void* DECLC scl_map_access (SCL_map_t m, long k); +extern DECLS SCL_iterator_t DECLC scl_map_at (SCL_map_t m, long k); +extern DECLS SCL_iterator_t DECLC scl_map_begin (SCL_map_t m); +extern DECLS SCL_iterator_t DECLC scl_map_end (SCL_map_t m); +extern DECLS SCL_iterator_t DECLC scl_map_next (SCL_iterator_t i); +extern DECLS SCL_iterator_t DECLC scl_map_prev (SCL_iterator_t i); +extern DECLS void DECLC scl_map_data_set (SCL_iterator_t i, const void* d); +extern DECLS void* DECLC scl_map_data_get (SCL_iterator_t i); +extern DECLS void DECLC scl_map_foreach (SCL_map_t m, SCL_cbfn_t f, void* c); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/libscl/src/map.c b/libscl/src/map.c new file mode 100644 index 0000000..ad9fb37 --- /dev/null +++ b/libscl/src/map.c @@ -0,0 +1,675 @@ +/* + * This file is part of the SCL software. + * The license which this software falls under is as follows: + * + * Copyright (C) 2004-2010 Douglas Jerome + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + * + * This library 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 Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* ***************************************************************************** + +FILE NAME + + $RCSfile: map.c,v $ + $Revision: 1.6 $ + $Date: 2010/04/14 03:08:14 $ + +PROGRAM INFORMATION + + Developed by: SCL project + Developer: Douglas Jerome, drj, + +FILE DESCRIPTION + + Small Container Library: Map Container Implementation + + Many of the map functions depends upon: + 1. SCL_ALLOCATOR() setting allocated memory to binary 0, + 2. SCL_ALLOCATOR() returning NULL if memory allocation fails and + 3. NULL being equal to binary 0. + +CHANGE LOG + + 04apr10 drj Added callback context pointer to scl_map_foreach(). + + 06jun06 drj Miscellaenous format finessing. + + 16dec04 drj scl_map_insert() returns SCL_DUPKEY for duplicate keys. + + 26nov04 drj Changed scl_map_update() to scl_map_replace(). + + 30oct04 drj File generation. + +***************************************************************************** */ + + +/* ************************************************************************* */ +/* */ +/* F e a t u r e S w i t c h e s */ +/* */ +/* ************************************************************************* */ + +/* + * Select these feature by moving them from the `if UNDEF' into the `else' + * section. + */ +#ifdef UNDEF +# define _BSD_SOURCE 1 /* 4.3+bsd subsystems */ +# define _POSIX_SOURCE 1 /* posix.1 */ +# define _POSIX_C_SOURCE 199309L /* posix.1 and posix.4 */ +# define _POSIX_C_SOURCE 199506L /* posix.1 and posix.4 and MORE */ +#else +# define _POSIX_C_SOURCE 200112L /* posix.1 and posix.4 and MORE */ +# undef _REENTRANT +# define _REENTRANT /* thread-safe for glibc */ +#endif + + +/* ************************************************************************* */ +/* */ +/* I n c l u d e d F i l e s */ +/* */ +/* ************************************************************************* */ + +/* + * OS Specific Header Files + */ +// #ifdef WIN32 +// # include "stdafx.h" +// #endif + +/* + * Standard C (ANSI) Header Files + */ +/* (none) */ + +/* + * Posix Header Files + */ +#ifdef _unix +# include /* always first amongst POSIX header files */ +#endif + +/* + * Project Specific Header Files + */ +#include "libscl/SCL_map.h" + + +/* ************************************************************************* */ +/* */ +/* C o n s t a n t s */ +/* */ +/* ************************************************************************* */ + +#define PRED(x) ((x)->pred) +#define SUCC(x) ((x)->succ) + +#define COSMOLOGICAL_CONSTANT (7) + + +/* ************************************************************************* */ +/* */ +/* E x t e r n a l R e f e r e n c e s */ +/* */ +/* ************************************************************************* */ + +/* (none) */ + + +/* ************************************************************************* */ +/* */ +/* D a t a T y p e s a n d S t r u c t u r e s */ +/* */ +/* ************************************************************************* */ + +typedef struct S_node_t S_node_t; +typedef struct S_SCL_map_t S_SCL_map_t; + +struct S_node_t + { + S_node_t* pred; + S_node_t* succ; + SCL_map_t map; + long index; + long key; + const void* data; + }; + +struct S_SCL_map_t + { + S_node_t** table; + size_t count; + size_t size; + size_t bmod; + }; + + +/* ************************************************************************* */ +/* */ +/* P u b l i c G l o b a l V a r i a b l e s */ +/* */ +/* ************************************************************************* */ + +/* (none) */ + + +/* ************************************************************************* */ +/* */ +/* P r i v a t e G l o b a l V a r i a b l e s */ +/* */ +/* ************************************************************************* */ + +/* (none) */ + + +/* ************************************************************************* */ +/* */ +/* E x e c u t a b l e C o d e (Locally Used Functions) */ +/* */ +/* ************************************************************************* */ + + +/***************************************************************************** + * Private Function Prototypes + *****************************************************************************/ + +static __inline__ long hashfn (size_t a_downshift, long a_key); +static __inline__ void insert (S_node_t** const a_list, S_node_t* const a_node); +static __inline__ S_node_t* find (S_node_t** const a_list, long a_key); +static __inline__ int rebuild (S_SCL_map_t* a_map); + + +/***************************************************************************** + * Private Function hashfn + *****************************************************************************/ + +static __inline__ long hashfn (size_t a_downshift, long a_key) + { + register uint32_t v; + + v = (uint32_t)a_key * (uint32_t)1103515245L; + v = v >> a_downshift; + + return (long)v; + } + + +/***************************************************************************** + * Private Function insert + *****************************************************************************/ + +static __inline__ void insert (S_node_t** const a_list, S_node_t* const a_node) + { + register S_node_t* const node = a_node; + register S_node_t* const head = *a_list; + + if (head != NULL) + { + PRED(head) = node; + SUCC(node) = head; + } + else + { + SUCC(node) = NULL; + } + PRED(node) = NULL; + *a_list = node; + + return; + } + + +/***************************************************************************** + * Private Function find + *****************************************************************************/ + +static __inline__ S_node_t* find (S_node_t** const a_list, long a_key) + { + register S_node_t* node = *a_list; + + while (node != NULL) + { + if (node->key == a_key) break; + node = SUCC(node); + } + + return node; + } + + +/***************************************************************************** + * Private Function rebuild + *****************************************************************************/ + +static __inline__ int rebuild (S_SCL_map_t* a_map) + { + register S_SCL_map_t* const map = a_map; + + register size_t size = map->size << 2; + register size_t bmod = map->bmod -= 2; + + register S_node_t* node; + register S_node_t* next; + register long index; + + register int i; + + S_node_t** nodes = (S_node_t**)SCL_ALLOCATOR (size * sizeof(S_node_t*)); + if (nodes == NULL) return SCL_NOMEM; + + for (i=map->size-1 ; i>=0 ; i--) + { + node = map->table[i]; + while (node != NULL) + { + next = SUCC(node); + index = hashfn (bmod, node->key); + node->index = index; + (void)insert (&nodes[index], node); + node = next; + } + } + + SCL_DEALLOCATOR ((void*)map->table); + + map->table = nodes; + map->size = size; + map->bmod = bmod; + + return SCL_OK; + } + + +/* ************************************************************************* */ +/* */ +/* E x e c u t a b l e C o d e (External Interface Functions) */ +/* */ +/* ************************************************************************* */ + + +/***************************************************************************** + * Public Function scl_map_new + *****************************************************************************/ + +#define BITS_IN_LONG (sizeof(long)*8) +#define BITS_IN_SIZE (2) + +SCL_map_t (scl_map_new) (void) + { + S_SCL_map_t* const map = (S_SCL_map_t* const)SCL_ALLOCATOR (sizeof(S_SCL_map_t)); + S_node_t** const nodes = (S_node_t** const)SCL_ALLOCATOR ((1<table = nodes; + map->size = 1 << BITS_IN_SIZE; + map->bmod = BITS_IN_LONG - BITS_IN_SIZE; + + return map; + } + +#undef BITS_IN_LONG +#undef BITS_IN_SIZE + + +/***************************************************************************** + * Public Function scl_map_del + *****************************************************************************/ + +void (scl_map_del) (SCL_map_t a_map) + { + S_SCL_map_t* const map = a_map; + + size_t size = map->size; + S_node_t** table = map->table; + + S_node_t* node1; + S_node_t* node2; + + while (size-- > 0) + { + node1 = *table++; + while (node1 != NULL) + { + node2 = SUCC(node1); + SCL_DEALLOCATOR ((void*)node1); + node1 = node2; + } + } + + SCL_DEALLOCATOR (map->table); + SCL_DEALLOCATOR (map); + + return; + } + + +/***************************************************************************** + * Public Function scl_map_erase + *****************************************************************************/ + +void (scl_map_erase) (SCL_map_t a_map) + { + S_SCL_map_t* const map = a_map; + + size_t size = map->size; + S_node_t** table = map->table; + + const S_node_t* node1; + const S_node_t* node2; + + while (size-- > 0) + { + node1 = *table; + while (node1 != NULL) + { + node2 = SUCC(node1); + SCL_DEALLOCATOR ((void*)node1); + node1 = node2; + } + *table++ = NULL; + } + + map->count = 0; + + return; + } + + +/***************************************************************************** + * Public Function scl_map_size + *****************************************************************************/ + +size_t (scl_map_size) (SCL_map_t a_map) + { + return a_map->size; + } + + +/***************************************************************************** + * Public Function scl_map_count + *****************************************************************************/ + +size_t (scl_map_count) (SCL_map_t a_map) + { + return a_map->count; + } + + +/***************************************************************************** + * Public Function scl_map_insert + *****************************************************************************/ + +int (scl_map_insert) (SCL_map_t a_map, long a_key, const void* a_data) + { + S_SCL_map_t* const map = a_map; + const long index = hashfn (map->bmod, a_key); + S_node_t* node; + + node = find (&a_map->table[index], a_key); + if (node != NULL) return SCL_DUPKEY; + + node = (S_node_t*)SCL_ALLOCATOR (sizeof(S_node_t)); + if (node == NULL) return SCL_NOMEM; + + node->map = map; + node->index = index; + node->key = a_key; + node->data = a_data; + + (void)insert (&map->table[index], node); + + map->count += 1; + + if (map->count > COSMOLOGICAL_CONSTANT * map->size) + { + (void)rebuild (map); + } + + return SCL_OK; + } + + +/***************************************************************************** + * Public Function scl_map_replace + *****************************************************************************/ + +int (scl_map_replace) (SCL_map_t a_map, long a_key, const void* a_data) + { + S_SCL_map_t* const map = a_map; + const long index = hashfn (map->bmod, a_key); + S_node_t* node = find (&map->table[index], a_key); + + if (node != NULL) + { + node->data = a_data; + return SCL_OK; + } + + node = (S_node_t*)SCL_ALLOCATOR (sizeof(S_node_t)); + if (node == NULL) return SCL_NOMEM; + + node->map = map; + node->index = index; + node->key = a_key; + node->data = a_data; + + (void)insert (&map->table[index], node); + + map->count += 1; + + if (map->count > COSMOLOGICAL_CONSTANT * map->size) + { + (void)rebuild (map); + } + + return SCL_OK; + } + + +/***************************************************************************** + * Public Function scl_map_remove + *****************************************************************************/ + +void* (scl_map_remove) (SCL_map_t a_map, long a_key) + { + S_SCL_map_t* const map = a_map; + const long index = hashfn (map->bmod, a_key); + S_node_t* const node = find (&map->table[index], a_key); + + const void* data; + + if (node == NULL) return NULL; + + if (SUCC(node) != NULL) PRED(SUCC(node)) = PRED(node); + if (PRED(node) != NULL) SUCC(PRED(node)) = SUCC(node); + else map->table[index] = SUCC(node); + + data = node->data; + + SCL_DEALLOCATOR ((void*)node); + map->count -= 1; + + return (void*)data; + } + + +/***************************************************************************** + * Public Function scl_map_access + *****************************************************************************/ + +void* (scl_map_access) (SCL_map_t a_map, long a_key) + { + const long index = hashfn (a_map->bmod, a_key); + const S_node_t* const node = find (&a_map->table[index], a_key); + return node != NULL ? (void*)node->data : NULL; + } + + +/***************************************************************************** + * Public Function scl_map_at + *****************************************************************************/ + +SCL_iterator_t (scl_map_at) (SCL_map_t a_map, long a_key) + { + const long index = hashfn (a_map->bmod, a_key); + return (SCL_iterator_t) find (&a_map->table[index], a_key); + } + + +/***************************************************************************** + * Public Function scl_map_begin + *****************************************************************************/ + +SCL_iterator_t (scl_map_begin) (SCL_map_t a_map) + { + const S_node_t* node = NULL; + + size_t index = a_map->size; + const S_node_t** table = (const S_node_t**)a_map->table; + + while ((node == NULL) && (index-- > 0)) + { + node = *table++; + } + + return (SCL_iterator_t)node; + } + + +/***************************************************************************** + * Public Function scl_map_end + *****************************************************************************/ + +SCL_iterator_t (scl_map_end) (SCL_map_t a_map) + { + const S_node_t* node = NULL; + + size_t index = a_map->size; + const S_node_t** table = (const S_node_t**)&a_map->table[index]; + + while ((node == NULL) && (index-- > 0)) + { + node = *--table; + } + if (node != NULL) while (SUCC(node) != NULL) node = SUCC(node); + + return (SCL_iterator_t)node; + } + + +/***************************************************************************** + * Public Function scl_map_next + *****************************************************************************/ + +SCL_iterator_t (scl_map_next) (SCL_iterator_t a_iterator) + { + const S_node_t* node = a_iterator; + + size_t index = node->index; + const size_t size = node->map->size; + const S_node_t** table = (const S_node_t**)&node->map->table[index]; + + node = SUCC(node); + while ((node == NULL) && (++index < size)) + { + node = *++table; + } + + return (SCL_iterator_t)node; + } + + +/***************************************************************************** + * Public Function scl_map_prev + *****************************************************************************/ + +SCL_iterator_t (scl_map_prev) (SCL_iterator_t a_iterator) + { + const S_node_t* node = a_iterator; + + size_t index = node->index; + const S_node_t** table = (const S_node_t**)&node->map->table[index]; + + node = PRED(node); + if (node != NULL) return (SCL_iterator_t)node; + while ((node == NULL) && (index-- > 0)) + { + node = *--table; + } + if (node != NULL) while (SUCC(node) != NULL) node = SUCC(node); + + return (SCL_iterator_t)node; + } + + +/***************************************************************************** + * Public Function scl_map_data_set + *****************************************************************************/ + +void (scl_map_data_set) (SCL_iterator_t a_iterator, const void* a_data) + { + ((S_node_t*)a_iterator)->data = a_data; + } + + +/***************************************************************************** + * Public Function scl_map_data_get + *****************************************************************************/ + +void* (scl_map_data_get) (SCL_iterator_t a_iterator) + { + return (void*)((S_node_t*)a_iterator)->data; + } + + +/***************************************************************************** + * Public Function scl_map_foreach + *****************************************************************************/ + +void (scl_map_foreach) (SCL_map_t a_map, SCL_cbfn_t a_func, void* a_context) + { + const S_node_t* node; + + const size_t size = a_map->size; + const S_node_t** table = (const S_node_t**)a_map->table; + + size_t i; + int stat; + + for (i=0 ; ikey, (void*)node->data, a_context); + if (stat != SCL_NOTFOUND) return; + node = SUCC(node); + } + } + + return; + } + + +/* end of file */ diff --git a/main.c b/main.c index 66f8156..7f1fa44 100644 --- a/main.c +++ b/main.c @@ -1,14 +1,13 @@ -#include -#include -#include "ebtn.h" -#include "windows.h" - -extern int example_test(void); -extern int example_user(void); - -int main(void) -{ - // example_test(); - example_user(); - return 0; -} +#include +#include +#include "ebtn.h" + +extern int example_test(void); +extern int example_user(void); + +int main(void) +{ + // example_test(); + example_user(); + return 0; +} From 3ebbe836e5b8d6d8fe00ebb7c39d4a68cae4f283 Mon Sep 17 00:00:00 2001 From: tanchenxi Date: Tue, 20 Jan 2026 09:53:08 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E6=94=B9example=5Fuser.c=20?= =?UTF-8?q?=E5=90=8D=E4=B8=BAexample=5Fuser=5Flinux.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example_user.c => example_user_linux.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename example_user.c => example_user_linux.c (100%) diff --git a/example_user.c b/example_user_linux.c similarity index 100% rename from example_user.c rename to example_user_linux.c