├── .gitignore ├── AC ├── README.md ├── api │ ├── cli-test.php │ ├── machinePatrol.php │ └── test.php ├── assets │ └── mac.png ├── auto-test.sh ├── make │ └── Makefile ├── run.sh ├── src │ ├── Makefile │ ├── ac_mf.h │ ├── acmf.c │ ├── acsmx.c │ ├── acsmx.h │ ├── control.sh │ ├── entry.c │ ├── gunittest.cc │ ├── util.c │ └── util.h └── test │ ├── gpl.txt │ ├── ir.htm │ └── simple.txt ├── README.md ├── c ├── atoi.c ├── fib.c ├── list.c └── yang-hui.c ├── event ├── block-http-client.c ├── low-level-rot13-sever.c └── note.c ├── golang └── random-pack │ └── main.go ├── other ├── combination.c ├── db_model.c ├── errno-msg.c ├── func_args.c ├── md5.c ├── random_hex.c ├── shift_bit.c ├── strftime.c ├── struct.c └── typedef-enum.c ├── php ├── Flexihash.php ├── inter.php ├── monkey.php ├── qsort.php └── send-red-pack.php └── tree ├── Makefile ├── binary-tree.c ├── bitree.c ├── bitree.h ├── common.h └── search-tree.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | 9 | # Compiled Static libraries 10 | *.lai 11 | *.la 12 | *.a 13 | 14 | # vi 15 | *~ 16 | *.swp 17 | *.swo 18 | *.dSYM 19 | a.out 20 | tags 21 | data 22 | doc 23 | acsmx 24 | acmf 25 | test 26 | nohup.out 27 | gunittest 28 | .DS_Store 29 | -------------------------------------------------------------------------------- /AC/README.md: -------------------------------------------------------------------------------- 1 | # 使用说明 2 | 3 | ## author: [yuchao86@gmail.com] 4 | 5 | ## 编译及使用方法 6 | 7 | ``` 8 | 1. 编译之前请先确认安装好 libevent 9 | 10 | 2. 进入src目录直接 make; 11 | cc -c -o entry.o entry.c 12 | cc -c -o acsmx.o acsmx.c 13 | gcc -g -o acsmx entry.o acsmx.o -levent 14 | cc -c -o acmf.o acmf.c 15 | cc -c -o util.o util.c 16 | gcc -g -o acmf acmf.o acsmx.o util.o -levent 17 | rm -f *.o 18 | 19 | 3. make 完成之后生成可执行文件 acmf 20 | acmf -h 帮助信息如下: 21 | ac-mf 0.0.1 22 | Build-date Jun 26 2014 16:15:18 23 | -p set ABS path(prefix), Necessarily 24 | -f filter keywords file name 25 | -v show version and help 26 | -h show this help and exit 27 | -H hostname(default: 0.0.0.0) 28 | -P listen port(default: 8668) 29 | -t set HTTP timeout(default: 1) 30 | -c [0|1] case switch(default: 1) 31 | 32 | 4. 启动服务使用如下命令: 33 | ./acmf -p /root/portal/src -P 8080 34 | 35 | 注: -p 必须使用绝对路径,需要过滤的关键词表在 data 目录里面的 mf.keyword.txt 里面 36 | 需要过滤什么,自己添加,注意不要有空行。 37 | ``` 38 | 39 | ## 使用实例: 40 | 41 | 接口地址:`http://yourhosts:8080` 42 | 43 | 请求方式:GET或者POST 44 | 45 | ``` 46 | 参数:format=json 47 | word=需要检测的中文英文字符串。 48 | 返回值:error 是否等于0 等于0则成功,其他值失败。 49 | 然后再判断数组stat是否为空, 50 | 如果为空,则说明评论文本可以发布。 51 | 否则不能发布。 52 | ``` 53 | 54 | ### 实例1 55 | 56 | `http://yourhosts:8080/?format=json&word=%E5%85%B1%E4%BA%A7%E5%85%9A%E5%A4%A7%E5%A3%B0%E9%81%93%E6%98%AF%E4%BB%A3%E7%90%86%E5%95%86%E7%9A%84%E7%9F%AD%E5%8F%91%E7%9A%84%E5%A4%9A%E5%B0%91Fuck%E5%85%B1%E4%BA%A7%E5%85%9Afuck%E8%A5%BF%E8%97%8F` 57 | 58 | ### 返回值 59 | 60 | ```json 61 | { 62 | "error": 0, 63 | "stat": [ 64 | { 65 | "keyword": "西藏", 66 | "hit_count": 1 67 | }, 68 | { 69 | "keyword": "FUCK", 70 | "hit_count": 2 71 | }, 72 | { 73 | "keyword": "共产党", 74 | "hit_count": 2 75 | } 76 | ] 77 | } 78 | ``` 79 | 80 | ### 实例2 81 | 82 | `http://yourhosts:8080/?format=json&word=%E8%AF%9A%E6%8B%9B%E6%9A%91%E5%81%87%E5%85%BC%E8%81%8C%E5%B0%8F%E6%97%B6%E5%B7%A5%EF%BC%8C%E6%AF%8F%E5%A4%A9%E5%9C%A8%E7%BA%BF2.3%E5%B0%8F%E6%97%B6%EF%BC%8C%E6%97%B6%E9%97%B4%E5%9C%B0%E7%82%B9%E6%B2%A1%E9%99%90%E5%88%B6%EF%BC%8C%E6%97%A5%E8%B5%9A80-150%E5%9B%AD%EF%BC%8C%E6%9C%89%E5%85%B4%E8%B6%A3%E8%81%94%E7%B3%BBQQ%E3%80%903609027004%E3%80%91%EF%BC%8C%E6%AD%A4%E5%A4%84%E4%B8%8D%E5%9B%9E%E5%A4%8D` 83 | 84 | ### 返回值 85 | 86 | ```json 87 | { 88 | "error": 0, 89 | "stat": [ 90 | { 91 | "keyword": "联系", 92 | "hit_count": 1 93 | }, 94 | { 95 | "keyword": "QQ", 96 | "hit_count": 2 97 | }, 98 | { 99 | "keyword": "QQ", 100 | "hit_count": 2 101 | }, 102 | { 103 | "keyword": "兼职", 104 | "hit_count": 1 105 | } 106 | ] 107 | } 108 | ``` 109 | 110 | ## 测试报告 111 | ### 机器配置 112 | 113 | ![mac](assets/mac.png) 114 | 115 | ### 测试结果 116 | 117 | ``` 118 | $ webbench -c 500 -t 5 'http://127.0.0.1:8668/?format=json&word=sb' 119 | Webbench - Simple Web Benchmark 1.5 120 | Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software. 121 | 122 | Benchmarking: GET http://127.0.0.1:8668/?format=json&word=sb 123 | 500 clients, running 5 sec. 124 | 125 | Speed=198456 pages/min, 717637 bytes/sec. 126 | Requests: 16163 susceed, 375 failed. 127 | ``` 128 | 129 | ``` 130 | $ ab -c 100 -n 10000 'http://127.0.0.1:8668/?format=json&word=sb' 131 | This is ApacheBench, Version 2.3 <$Revision: 1663405 $> 132 | Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 133 | Licensed to The Apache Software Foundation, http://www.apache.org/ 134 | 135 | Benchmarking 127.0.0.1 (be patient) 136 | Completed 1000 requests 137 | Completed 2000 requests 138 | Completed 3000 requests 139 | Completed 4000 requests 140 | Completed 5000 requests 141 | Completed 6000 requests 142 | Completed 7000 requests 143 | Completed 8000 requests 144 | Completed 9000 requests 145 | Completed 10000 requests 146 | Finished 10000 requests 147 | 148 | 149 | Server Software: eac 150 | Server Hostname: 127.0.0.1 151 | Server Port: 8668 152 | 153 | Document Path: /?format=json&word=sb 154 | Document Length: 57 bytes 155 | 156 | Concurrency Level: 100 157 | Time taken for tests: 1.633 seconds 158 | Complete requests: 10000 159 | Failed requests: 0 160 | Total transferred: 2220000 bytes 161 | HTML transferred: 570000 bytes 162 | Requests per second: 6123.55 [#/sec] (mean) 163 | Time per request: 16.330 [ms] (mean) 164 | Time per request: 0.163 [ms] (mean, across all concurrent requests) 165 | Transfer rate: 1327.57 [Kbytes/sec] received 166 | 167 | Connection Times (ms) 168 | min mean[+/-sd] median max 169 | Connect: 0 8 38.0 5 549 170 | Processing: 2 8 38.7 5 549 171 | Waiting: 1 8 38.7 5 549 172 | Total: 5 16 54.1 10 554 173 | 174 | Percentage of the requests served within a certain time (ms) 175 | 50% 10 176 | 66% 11 177 | 75% 12 178 | 80% 13 179 | 90% 15 180 | 95% 17 181 | 98% 19 182 | 99% 553 183 | 100% 554 (longest request) 184 | ``` 185 | -------------------------------------------------------------------------------- /AC/api/cli-test.php: -------------------------------------------------------------------------------- 1 | $line, 21 | ); 22 | 23 | $response = machinePatrol::getPatrol($post); 24 | $log = sprintf('%s %s%s', date('Y-m-d-H:m:s'), json_encode($response), "\n"); 25 | echo $log; 26 | } 27 | 28 | fclose($fp); 29 | -------------------------------------------------------------------------------- /AC/api/machinePatrol.php: -------------------------------------------------------------------------------- 1 | 1, 11 | ); 12 | 13 | if (isset($para['word']) && strlen($para['word'])) 14 | { 15 | $json = machinePatrol::_getJson(machinePatrol::$api, $para); 16 | if (strlen($json)) 17 | { 18 | $res = json_decode($json, true); 19 | } 20 | } 21 | 22 | return $res; 23 | } 24 | 25 | static protected function _getJson($api, $post = array()) 26 | { 27 | $json = ''; 28 | 29 | if (!(is_array($post) && count($post) && isset($post['word']) && strlen($post['word']))) 30 | { 31 | return $json; 32 | } 33 | 34 | $post_data = ''; 35 | foreach ($post as $k => $v) 36 | { 37 | $post_data .= "{$k}={$v}&"; 38 | } 39 | 40 | $ch = curl_init(); 41 | curl_setopt($ch, CURLOPT_URL, $api); 42 | /** 43 | * Note: Passing an array to CURLOPT_POSTFIELDS will encode 44 | * the data as multipart/form-data, while passing a 45 | * URL-encoded string will encode the data as application/x-www-form-urlencoded. 46 | **/ 47 | curl_setopt($ch, CURLOPT_POST, 1); 48 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); 49 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 50 | //curl_setopt($ch, CURLOPT_HEADER, 0); 51 | curl_setopt($ch, CURLOPT_TIMEOUT, machinePatrol::$time_out); 52 | $json = curl_exec($ch); 53 | //echo $json . "\n"; 54 | if (curl_errno($ch)) 55 | { 56 | $json = ''; 57 | } 58 | curl_close($ch); 59 | 60 | return $json; 61 | } 62 | } 63 | 64 | /** 65 | // just test 66 | $para = array( 67 | 'word' => 'test for 这是有一些敏感词,比如: 西单. 行房, sb', 68 | //'word' => '这行没有敏感词', 69 | ); 70 | //machinePatrol::$time_out = 1; 71 | print_r(machinePatrol::getPatrol($para)); 72 | */ 73 | -------------------------------------------------------------------------------- /AC/api/test.php: -------------------------------------------------------------------------------- 1 | '', 7 | ); 8 | if (isset($_POST) && count($_POST) && isset($_POST['word'])) 9 | { 10 | $post_data = $_POST; 11 | } 12 | ?> 13 | 14 |
15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 | 23 |
24 | '; 29 | print_r($response['stat']); 30 | echo ''; 31 | } 32 | ?> 33 |
34 | -------------------------------------------------------------------------------- /AC/assets/mac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hy0kl/algorithm/2079d44fcb328d3e3ccecf9a61e1094ac1fe4379/AC/assets/mac.png -------------------------------------------------------------------------------- /AC/auto-test.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | 3 | work_path=$(pwd) 4 | i=0 5 | # 并发测试 6 | # 使用了 libevent 的 ev_buf 后 7 | # 并发能力有很大的提升 8 | # 也从侧面验证内存管理方式为内存池 9 | while ((i < 10)) 10 | do 11 | #echo $i 12 | nohup php api/cli-test.php & 13 | i=$((i + 1)) 14 | done 15 | -------------------------------------------------------------------------------- /AC/make/Makefile: -------------------------------------------------------------------------------- 1 | # SYNOPSIS: 2 | # 3 | # make [all] - makes everything. 4 | # make TARGET - makes the given target. 5 | # make clean - removes all files generated by make. 6 | 7 | # Please tweak the following variable definitions as needed by your 8 | # project, except GTEST_HEADERS, which you can use in your own targets 9 | # but shouldn't modify. 10 | 11 | # Points to the root of Google Test, relative to where this file is. 12 | # Remember to tweak this if you move this file. 13 | GCC = gcc 14 | GCCFLAGS = -g -finline-functions -Wall -Winline -pipe 15 | 16 | HOME = /Users/yongjieyang 17 | GTEST_DIR = $(HOME)/study/gtest 18 | 19 | # Where to find user code. 20 | USER_DIR = ../src 21 | 22 | # Flags passed to the preprocessor. 23 | CPPFLAGS += -I$(GTEST_DIR)/include \ 24 | -I$(HOME)/local/include 25 | LIBDIR = \ 26 | -levent 27 | 28 | # Flags passed to the C++ compiler. 29 | CXXFLAGS += -g -Wall -Wextra 30 | 31 | # All tests produced by this Makefile. Remember to add new tests you 32 | # created to the list. 33 | TESTS = gunittest 34 | 35 | # All Google Test headers. Usually you shouldn't change this 36 | # definition. 37 | GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \ 38 | $(GTEST_DIR)/include/gtest/internal/*.h 39 | 40 | # House-keeping build targets. 41 | 42 | all : $(TESTS) 43 | 44 | clean : 45 | rm -f $(TESTS) gtest.a gtest_main.a *.o 46 | 47 | # Builds gtest.a and gtest_main.a. 48 | 49 | # Usually you shouldn't tweak such internal variables, indicated by a 50 | # trailing _. 51 | GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS) 52 | 53 | # For simplicity and to avoid depending on Google Test's 54 | # implementation details, the dependencies specified below are 55 | # conservative and not optimized. This is fine as Google Test 56 | # compiles fast and for ordinary users its source rarely changes. 57 | gtest-all.o : $(GTEST_SRCS_) 58 | $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ 59 | $(GTEST_DIR)/src/gtest-all.cc 60 | 61 | gtest_main.o : $(GTEST_SRCS_) 62 | $(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c \ 63 | $(GTEST_DIR)/src/gtest_main.cc 64 | 65 | gtest.a : gtest-all.o 66 | $(AR) $(ARFLAGS) $@ $^ 67 | 68 | gtest_main.a : gtest-all.o gtest_main.o 69 | $(AR) $(ARFLAGS) $@ $^ 70 | 71 | # Builds a sample test. A test should link with either gtest.a or 72 | # gtest_main.a, depending on whether it defines its own main() 73 | # function. 74 | 75 | acsmx.o : $(USER_DIR)/acsmx.c $(USER_DIR)/acsmx.h $(GTEST_HEADERS) 76 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/acsmx.c 77 | 78 | util.o : $(USER_DIR)/util.c $(USER_DIR)/util.h $(USER_DIR)/ac_mf.h $(GTEST_HEADERS) 79 | #$(GCC) -g -o $@ $^ $(LIBDIR) $(CPPFLAGS) 80 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/util.c $(LIBDIR) 81 | 82 | gunittest.o : $(USER_DIR)/gunittest.cc \ 83 | $(USER_DIR)/util.h $(GTEST_HEADERS) 84 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/gunittest.cc 85 | 86 | gunittest : acsmx.o util.o gunittest.o gtest_main.a 87 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $(LIBDIR) $^ -o $@ 88 | 89 | -------------------------------------------------------------------------------- /AC/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | program="./src/acsmx" 4 | data_path="./test" 5 | 6 | $program $data_path/simple.txt abc test 7 | $program $data_path/gpl.txt copy software free gpl -nocase 8 | $program $data_path/ir.htm 论文 课题 领域 学术 9 | 10 | $program $data_path/filter.txt sb "free Tibet" "free Tibet" 西藏 胡 -nocase 11 | 12 | #$program $data_path/Bible.txt grievous continually ungirded 13 | -------------------------------------------------------------------------------- /AC/src/Makefile: -------------------------------------------------------------------------------- 1 | GCC = gcc 2 | GCCFLAGS = -g -finline-functions -Wall -Winline -pipe 3 | 4 | LIBDIR = \ 5 | -levent 6 | 7 | TARGET = acsmx 8 | SERVER = acmf 9 | 10 | OBJS1 = entry.o acsmx.o 11 | OBJS2 = acmf.o acsmx.o util.o 12 | 13 | all: $(TARGET) $(SERVER) 14 | rm -f *.o 15 | 16 | $(TARGET): $(OBJS1) 17 | $(GCC) -g -o $@ $^ $(LIBDIR) 18 | 19 | $(SERVER): $(OBJS2) 20 | $(GCC) -g -o $@ $^ $(LIBDIR) 21 | 22 | $.o: %c 23 | $(GCC) $(GCCFLAGS) -c $< -o $@ 24 | 25 | .PHONY: clean 26 | clean : 27 | rm -rf $(TARGET) $(SERVER) $(OBJS1) $(OBJS2) 28 | 29 | .PHONY: cleanobj 30 | cleanobj: 31 | rm -rf $(OBJS1) $(OBJS2) 32 | -------------------------------------------------------------------------------- /AC/src/ac_mf.h: -------------------------------------------------------------------------------- 1 | #ifndef _AC_MF_H 2 | #define _AC_MF_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | /** 36 | #include 37 | #include 38 | #include 39 | */ 40 | #include "acsmx.h" 41 | 42 | #define _DEBUG 0 43 | 44 | #define PACKAGE "ac-mf" 45 | #define VERSION "0.0.1" 46 | 47 | #define SERVER_TAG "eac v 0.0.1" 48 | #define POST_DATA_BUF_LEN 1024 * 20 49 | #define FILE_PATH_LEN 256 50 | #define READ_LINE_BUF_LEN 1024 51 | #define HOST_NAME_LEN 32 52 | 53 | #define ACTION_FILTER 1 54 | #define ACTION_LIST 2 55 | #define ACTION_MEMORY 3 56 | 57 | /** output format */ 58 | #define OUTPUT_AS_HTML 0 59 | #define OUTPUT_AS_JSON 1 60 | 61 | #define CRLF "
" 62 | #define FORMAT_HTML "html" 63 | #define FORMAT_JSON "json" 64 | 65 | #define DEFAULT_LOG_LEVEL 4 /** unused */ 66 | #define DEFAULT_TIMEOUT 1 67 | #define DEFAULT_HOSTNAME "0.0.0.0" 68 | #define DEFAULT_PORT 8668 69 | #define DEFINE_KEYWORD_FILE "mf.keyword.txt" 70 | #define DEFAULT_PREFIX "." 71 | #define DEFAULT_CASE_SWITCH 1 72 | 73 | #if defined(__DATE__) && defined(__TIME__) 74 | static const char build_date[] = __DATE__ " " __TIME__; 75 | #else 76 | static const char build_date[] = "unknown"; 77 | #endif 78 | 79 | #define SIGNO_END 111 80 | 81 | #define logprintf(format, arg...) fprintf(stderr, "[NOTICE]%s:%d:%s "format"\n", __FILE__, __LINE__, __func__, ##arg) 82 | 83 | typedef struct _global_variable_t 84 | { 85 | ACSM_STRUCT *acsm; 86 | char post_data[POST_DATA_BUF_LEN]; 87 | } global_variable_t; 88 | 89 | typedef struct _config_t 90 | { 91 | int log_level; 92 | int no_case; 93 | int port; 94 | int timeout; 95 | char prefix[FILE_PATH_LEN]; 96 | char hostname[HOST_NAME_LEN]; 97 | char keyword_file[FILE_PATH_LEN]; 98 | } config_t; 99 | 100 | extern global_variable_t g_vars; 101 | extern config_t gconfig; 102 | 103 | #endif 104 | 105 | -------------------------------------------------------------------------------- /AC/src/acmf.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: hy0kle@gmail.com 3 | * NOTE: p += snprintf(p, buf_len - (p - buf), ""); 4 | * 这种写法简单易读,但需要一个隐式的条件,那就是缓冲区足够大, 5 | * 能容纳下全部内容,否则可能出 core. 6 | */ 7 | #include "ac_mf.h" 8 | #include "util.h" 9 | 10 | int main (int argc, char **argv) 11 | { 12 | struct evhttp *httpd = NULL; 13 | ACSM_STRUCT *acsm = NULL; 14 | 15 | init_config(); 16 | if (0 != parse_args(argc, argv)) 17 | { 18 | fprintf(stderr, "parse args error.\n"); 19 | goto FINISH; 20 | } 21 | #if (_DEBUG) 22 | print_config(); 23 | #endif 24 | 25 | /** 信息屏蔽 */ 26 | signal_setup(); 27 | 28 | init_acsm(&acsm); 29 | /* Generate GtoTo Table and Fail Table */ 30 | acsmCompile(acsm); 31 | g_vars.acsm = acsm; 32 | 33 | /** 初始化事件 */ 34 | event_init(); 35 | /** 初始化监听ip和端口 */ 36 | // httpd = evhttp_start(proxy_listen, proxy_port); 37 | httpd = evhttp_start(gconfig.hostname, gconfig.port); 38 | if (NULL == httpd) 39 | { 40 | fprintf(stderr, "[Error]: Unable to listen on %s:%d\n", 41 | gconfig.hostname, gconfig.port); 42 | exit(1); 43 | } 44 | 45 | // 设置http连接超时时间 46 | evhttp_set_timeout(httpd, gconfig.timeout); 47 | // 设置请求到达后的回调函数 48 | evhttp_set_gencb(httpd, api_proxy_handler, NULL); 49 | // libevent 循环处理事件 50 | event_dispatch(); 51 | 52 | // 释放资源 53 | evhttp_free(httpd); 54 | acsmFree(acsm); 55 | 56 | FINISH: 57 | return (0); 58 | } 59 | 60 | -------------------------------------------------------------------------------- /AC/src/acsmx.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** 3 | ** Multi-Pattern Search Engine 4 | ** 5 | ** Aho-Corasick State Machine - uses a Deterministic Finite Automata - DFA 6 | ** 7 | ** Copyright (C) 2002 Sourcefire,Inc. 8 | ** Marc Norton 9 | ** 10 | ** 11 | ** This program is free software; you can redistribute it and/or modify 12 | ** it under the terms of the GNU General Public License as published by 13 | ** the Free Software Foundation; either version 2 of the License, or 14 | ** (at your option) any later version. 15 | ** 16 | ** This program is distributed in the hope that it will be useful, 17 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | ** GNU General Public License for more details. 20 | ** 21 | ** You should have received a copy of the GNU General Public License 22 | ** along with this program; if not, write to the Free Software 23 | ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 24 | ** 25 | ** 26 | ** Reference - Efficient String matching: An Aid to Bibliographic Search 27 | ** Alfred V Aho and Margaret J Corasick 28 | ** Bell Labratories 29 | ** Copyright(C) 1975 Association for Computing Machinery,Inc 30 | ** 31 | ** Implemented from the 4 algorithms in the paper by Aho & Corasick 32 | ** and some implementation ideas from 'Practical Algorithms in C' 33 | ** 34 | ** Notes: 35 | ** 1) This version uses about 1024 bytes per pattern character - heavy on the memory. 36 | ** 2) This algorithm finds all occurrences of all patterns within a 37 | ** body of text. 38 | ** 3) Support is included to handle upper and lower case matching. 39 | ** 4) Some comopilers optimize the search routine well, others don't, this makes all the difference. 40 | ** 5) Aho inspects all bytes of the search text, but only once so it's very efficient, 41 | ** if the patterns are all large than the Modified Wu-Manbar method is often faster. 42 | ** 6) I don't subscribe to any one method is best for all searching needs, 43 | ** the data decides which method is best, 44 | ** and we don't know until after the search method has been tested on the specific data sets. 45 | ** 46 | ** 47 | ** May 2002 : Marc Norton 1st Version 48 | ** June 2002 : Modified interface for SNORT, added case support 49 | ** Aug 2002 : Cleaned up comments, and removed dead code. 50 | ** Nov 2,2002: Fixed queue_init() , added count=0 51 | ** 52 | ** Wangyao : wangyao@cs.hit.edu.cn 53 | ** 54 | ** Apr 24,2007: WangYao Combined Build_NFA() and Convert_NFA_To_DFA() into Build_DFA(); 55 | ** And Delete Some redundancy Code 56 | ** 57 | */ 58 | 59 | #include 60 | #include 61 | #include 62 | #include 63 | #include "acsmx.h" 64 | 65 | #define MEMASSERT(p,s) if(!p){fprintf(stderr,"ACSM-No Memory: %s!\n",s);exit(0);} 66 | 67 | /*Define the number of the line,when match a keyword*/ 68 | //extern int nline = 1; 69 | int nline = 1; 70 | 71 | /* 72 | * Malloc the AC Memory 73 | */ 74 | static void *AC_MALLOC (int n) 75 | { 76 | void *p; 77 | p = malloc (n); 78 | 79 | return p; 80 | } 81 | 82 | /* 83 | *Free the AC Memory 84 | */ 85 | static void AC_FREE (void *p) 86 | { 87 | if (p) 88 | free (p); 89 | } 90 | 91 | 92 | /* 93 | * Simple QUEUE NODE 94 | */ 95 | typedef struct _qnode 96 | { 97 | int state; 98 | struct _qnode *next; 99 | }QNODE; 100 | 101 | /* 102 | * Simple QUEUE Structure 103 | */ 104 | typedef struct _queue 105 | { 106 | QNODE * head, *tail; 107 | int count; 108 | }QUEUE; 109 | 110 | /* 111 | *Init the Queue 112 | */ 113 | static void queue_init(QUEUE * s) 114 | { 115 | s->head = s->tail = 0; 116 | s->count = 0; 117 | } 118 | 119 | 120 | /* 121 | * Add Tail Item to queue 122 | */ 123 | static void queue_add(QUEUE *s, int state) 124 | { 125 | QNODE *q = NULL; 126 | /*Queue is empty*/ 127 | if (!s->head) 128 | { 129 | q = s->tail = s->head = (QNODE *)AC_MALLOC(sizeof(QNODE)); 130 | /*if malloc failed,exit the problom*/ 131 | MEMASSERT(q, "queue_add"); 132 | q->state = state; 133 | q->next = 0; /*Set the New Node's Next Null*/ 134 | } 135 | else 136 | { 137 | q = (QNODE *) AC_MALLOC (sizeof (QNODE)); 138 | MEMASSERT (q, "queue_add"); 139 | q->state = state; 140 | q->next = 0; 141 | /*Add the new Node into the queue*/ 142 | s->tail->next = q; 143 | /*set the new node is the Queue's Tail*/ 144 | s->tail = q; 145 | } 146 | s->count++; 147 | } 148 | 149 | 150 | /* 151 | * Remove Head Item from queue 152 | */ 153 | static int queue_remove (QUEUE * s) 154 | { 155 | int state = 0; 156 | QNODE * q; 157 | /*Remove A QueueNode From the head of the Queue*/ 158 | if (s->head) 159 | { 160 | q = s->head; 161 | state = q->state; 162 | s->head = s->head->next; 163 | s->count--; 164 | 165 | /*If Queue is Empty,After Remove A QueueNode*/ 166 | if (!s->head) 167 | { 168 | s->tail = 0; 169 | s->count = 0; 170 | } 171 | /*Free the QueNode Memory*/ 172 | AC_FREE (q); 173 | } 174 | return state; 175 | } 176 | 177 | 178 | /* 179 | *Return The count of the Node in the Queue 180 | */ 181 | static int queue_count (QUEUE * s) 182 | { 183 | return s->count; 184 | } 185 | 186 | 187 | /* 188 | *Free the Queue Memory 189 | */ 190 | static void queue_free (QUEUE * s) 191 | { 192 | while (queue_count (s)) 193 | { 194 | queue_remove (s); 195 | } 196 | } 197 | 198 | 199 | /* 200 | ** Case Translation Table 201 | */ 202 | static unsigned char xlatcase[256]; 203 | /* 204 | * Init the xlatcase Table,Trans alpha to UpperMode 205 | * Just for the NoCase State 206 | */ 207 | static void init_xlatcase(void) 208 | { 209 | int i = 0; 210 | for (i = 0; i < 256; i++) 211 | { 212 | xlatcase[i] = toupper(i); 213 | } 214 | 215 | return; 216 | } 217 | 218 | /* 219 | *Convert the pattern string into upper 220 | */ 221 | static void ConvertCaseEx (unsigned char *d, unsigned char *s, int m) 222 | { 223 | int i; 224 | for (i = 0; i < m; i++) 225 | { 226 | d[i] = xlatcase[s[i]]; 227 | } 228 | } 229 | 230 | /* 231 | * Add a pattern to the list of patterns terminated at this state. 232 | * Insert at front of list. 233 | */ 234 | static void AddMatchListEntry(ACSM_STRUCT *acsm, int state, ACSM_PATTERN * px) 235 | { 236 | ACSM_PATTERN *p = NULL; 237 | 238 | p = (ACSM_PATTERN *)AC_MALLOC(sizeof(ACSM_PATTERN)); 239 | MEMASSERT(p, "AddMatchListEntry"); 240 | memcpy(p, px, sizeof(ACSM_PATTERN)); 241 | 242 | /*Add the new pattern to the pattern list*/ 243 | p->next = acsm->acsmStateTable[state].MatchList; 244 | acsm->acsmStateTable[state].MatchList = p; 245 | } 246 | 247 | /* 248 | * Add Pattern States 249 | */ 250 | static void AddPatternStates(ACSM_STRUCT *acsm, ACSM_PATTERN *p) 251 | { 252 | unsigned char *pattern = NULL; 253 | int state = 0, next = 0, n = 0; 254 | 255 | n = p->n; /*The number of alpha in the pattern string*/ 256 | pattern = p->patrn; 257 | 258 | /* 259 | * Match up pattern with existing states 260 | */ 261 | for (; n > 0; pattern++, n--) 262 | { 263 | next = acsm->acsmStateTable[state].NextState[*pattern]; 264 | if (next == ACSM_FAIL_STATE) 265 | break; 266 | 267 | state = next; 268 | } 269 | 270 | /* 271 | * Add new states for the rest of the pattern bytes, 1 state per byte 272 | */ 273 | for (; n > 0; pattern++, n--) 274 | { 275 | acsm->acsmNumStates++; 276 | acsm->acsmStateTable[state].NextState[*pattern] = acsm->acsmNumStates; 277 | state = acsm->acsmNumStates; 278 | } 279 | /*Here,An accept state,just add into the MatchListof the state*/ 280 | AddMatchListEntry(acsm, state, p); 281 | } 282 | 283 | 284 | /* 285 | * Build Non-Deterministic Finite Automata 286 | */ 287 | static void Build_DFA (ACSM_STRUCT * acsm) 288 | { 289 | int r = 0, stat = 0; 290 | int i = 0; 291 | QUEUE q, *queue = &q; 292 | ACSM_PATTERN *mlist = NULL; 293 | ACSM_PATTERN *px = NULL; 294 | 295 | /* Init a Queue */ 296 | queue_init(queue); 297 | 298 | /* Add the state 0 transitions 1st */ 299 | /*1st depth Node's FailState is 0, fail(x) = 0 */ 300 | for (i = 0; i < ALPHABET_SIZE; i++) 301 | { 302 | stat = acsm->acsmStateTable[0].NextState[i]; 303 | if (stat) 304 | { 305 | queue_add(queue, stat); 306 | acsm->acsmStateTable[stat].FailState = 0; 307 | } 308 | } 309 | 310 | /* Build the fail state transitions for each valid state */ 311 | while (queue_count(queue) > 0) 312 | { 313 | r = queue_remove(queue); 314 | 315 | /* Find Final States for any Failure */ 316 | for (i = 0; i < ALPHABET_SIZE; i++) 317 | { 318 | int fs, next; 319 | /*** Note NextState[i] is a const variable in this block ***/ 320 | if ((stat = acsm->acsmStateTable[r].NextState[i]) != ACSM_FAIL_STATE) 321 | { 322 | queue_add(queue, stat); 323 | fs = acsm->acsmStateTable[r].FailState; 324 | 325 | /* 326 | * Locate the next valid state for 'i' starting at s 327 | */ 328 | /**** Note the variable "next" ****/ 329 | /*** Note "NextState[i]" is a const variable in this block ***/ 330 | while ((next = acsm->acsmStateTable[fs].NextState[i]) == 331 | ACSM_FAIL_STATE) 332 | { 333 | fs = acsm->acsmStateTable[fs].FailState; 334 | } 335 | 336 | /* 337 | * Update 's' state failure state to point to the next valid state 338 | */ 339 | acsm->acsmStateTable[stat].FailState = next; 340 | } 341 | else 342 | { 343 | acsm->acsmStateTable[r].NextState[i] = 344 | acsm->acsmStateTable[acsm->acsmStateTable[r].FailState].NextState[i]; 345 | } 346 | } 347 | } 348 | 349 | /* Clean up the queue */ 350 | queue_free(queue); 351 | } 352 | 353 | 354 | /* 355 | * Init the acsm DataStruct 356 | */ 357 | ACSM_STRUCT *acsmNew(void) 358 | { 359 | ACSM_STRUCT *p = NULL; 360 | 361 | init_xlatcase(); 362 | p = (ACSM_STRUCT *)AC_MALLOC(sizeof(ACSM_STRUCT)); 363 | MEMASSERT (p, "acsmNew"); 364 | if (p) 365 | memset(p, 0, sizeof(ACSM_STRUCT)); 366 | 367 | return p; 368 | } 369 | 370 | 371 | /* 372 | * Add a pattern to the list of patterns for this state machine 373 | */ 374 | int acsmAddPattern(ACSM_STRUCT *p, unsigned char *pat, int n, int nocase) 375 | { 376 | ACSM_PATTERN *plist = NULL; 377 | //fprintf(stderr, "pattern: [%s]\n", pat); 378 | 379 | plist = (ACSM_PATTERN *)AC_MALLOC(sizeof(ACSM_PATTERN)); 380 | MEMASSERT(plist, "acsmAddPattern"); 381 | 382 | plist->patrn = (unsigned char *)AC_MALLOC(n + 1); 383 | plist->patrn[n] = '\0'; 384 | ConvertCaseEx(plist->patrn, pat, n); 385 | 386 | plist->casepatrn = (unsigned char *)AC_MALLOC(n + 1); 387 | plist->casepatrn[n] = '\0'; 388 | memcpy(plist->casepatrn, pat, n); 389 | 390 | plist->n = n; /** 单个模式串的长度 */ 391 | plist->nocase = nocase; 392 | plist->nmatch = 0; 393 | 394 | /*Add the pattern into the pattern list*/ 395 | /** 在头部链新节点:2012.10.15 */ 396 | plist->next = p->acsmPatterns; 397 | p->acsmPatterns = plist; 398 | 399 | return 0; 400 | } 401 | 402 | /* 403 | * Compile State Machine 404 | */ 405 | int acsmCompile(ACSM_STRUCT * acsm) 406 | { 407 | int i = 0; 408 | int k = 0; 409 | size_t size = 0; 410 | ACSM_PATTERN *plist = NULL; 411 | 412 | /* Count number of states */ 413 | /** 模式串的长度和 */ 414 | acsm->acsmMaxStates = 1; /*State 0*/ 415 | for (plist = acsm->acsmPatterns; plist != NULL; plist = plist->next) 416 | { 417 | acsm->acsmMaxStates += plist->n; 418 | } 419 | 420 | size = sizeof(ACSM_STATETABLE) * acsm->acsmMaxStates; 421 | acsm->acsmStateTable = (ACSM_STATETABLE *)AC_MALLOC(size); 422 | MEMASSERT (acsm->acsmStateTable, "acsmCompile"); 423 | memset(acsm->acsmStateTable, 0, size); 424 | 425 | /* Initialize state zero as a branch */ 426 | acsm->acsmNumStates = 0; 427 | 428 | /* Initialize all States NextStates to FAILED */ 429 | for (k = 0; k < acsm->acsmMaxStates; k++) 430 | { 431 | for (i = 0; i < ALPHABET_SIZE; i++) 432 | { 433 | acsm->acsmStateTable[k].NextState[i] = ACSM_FAIL_STATE; 434 | } 435 | } 436 | 437 | /* This is very import */ 438 | /* Add each Pattern to the State Table */ 439 | for (plist = acsm->acsmPatterns; plist != NULL; plist = plist->next) 440 | { 441 | AddPatternStates(acsm, plist); 442 | } 443 | 444 | /* Set all failed state transitions which from state 0 to return to the 0'th state */ 445 | for (i = 0; i < ALPHABET_SIZE; i++) 446 | { 447 | if (acsm->acsmStateTable[0].NextState[i] == ACSM_FAIL_STATE) 448 | { 449 | acsm->acsmStateTable[0].NextState[i] = 0; 450 | } 451 | } 452 | 453 | /* Build the NFA */ 454 | Build_DFA(acsm); 455 | 456 | return 0; 457 | } 458 | 459 | 460 | /*64KB Memory*/ 461 | static unsigned char Tc[64*1024]; 462 | 463 | /* 464 | * Search Text or Binary Data for Pattern matches 465 | */ 466 | int acsmSearch (ACSM_STRUCT * acsm, unsigned char *Tx, int n, 467 | void (*PrintMatch)(ACSM_PATTERN * pattern, ACSM_PATTERN * mlist, int nline, int index)) 468 | { 469 | int state; 470 | ACSM_PATTERN * mlist = NULL; 471 | unsigned char *Tend = NULL; 472 | ACSM_STATETABLE * StateTable = acsm->acsmStateTable; 473 | int nfound = 0; /*Number of the found(matched) patten string*/ 474 | unsigned char *T = NULL; 475 | int index; 476 | 477 | //fprintf(stderr, "******search keyword str: [%s]\n", Tx); 478 | 479 | /* Case conversion */ 480 | ConvertCaseEx(Tc, Tx, n); 481 | T = Tc; 482 | Tend = T + n; 483 | 484 | for (state = 0; T < Tend; T++) 485 | { 486 | state = StateTable[state].NextState[*T]; 487 | 488 | /* State is a accept state? */ 489 | if( StateTable[state].MatchList != NULL ) 490 | { 491 | for (mlist = StateTable[state].MatchList; 492 | mlist != NULL; 493 | mlist = mlist->next) 494 | { 495 | /*Get the index of the Match Pattern String in the Text*/ 496 | index = T - mlist->n + 1 - Tc; 497 | 498 | nfound++; 499 | if (PrintMatch) 500 | { 501 | PrintMatch(acsm->acsmPatterns, mlist, nline, index); 502 | } 503 | } 504 | } 505 | } 506 | 507 | return nfound; 508 | } 509 | 510 | 511 | /* 512 | * Free all memory 513 | */ 514 | void acsmFree (ACSM_STRUCT * acsm) 515 | { 516 | int i; 517 | ACSM_PATTERN * mlist, *ilist; 518 | for (i = 0; i < acsm->acsmMaxStates; i++) 519 | 520 | { 521 | if (acsm->acsmStateTable[i].MatchList != NULL) 522 | 523 | { 524 | mlist = acsm->acsmStateTable[i].MatchList; 525 | while (mlist) 526 | { 527 | ilist = mlist; 528 | mlist = mlist->next; 529 | AC_FREE (ilist); 530 | } 531 | } 532 | } 533 | AC_FREE (acsm->acsmStateTable); 534 | } 535 | 536 | /* 537 | * Print A Match String's Information 538 | */ 539 | void PrintMatch (ACSM_PATTERN * pattern,ACSM_PATTERN * mlist, int nline,int index) 540 | { 541 | /* Count the Each Match Pattern */ 542 | ACSM_PATTERN *temp = pattern; 543 | for (; temp != NULL; temp=temp->next) 544 | { 545 | if (!strcmp((const char *)temp->patrn, (const char *)mlist->patrn)) //strcmp succeed return 0,So here use "!" operation 546 | { 547 | temp->nmatch++; 548 | } 549 | 550 | } 551 | 552 | /** 553 | if(mlist->nocase) 554 | fprintf (stdout, "Match KeyWord %s at %d line %d char\n", mlist->patrn, nline, index); 555 | else 556 | fprintf (stdout, "Match KeyWord %s at %d line %d char\n", mlist->casepatrn, nline, index); 557 | */ 558 | } 559 | 560 | /* 561 | * Print Summary Information of the AC Match 562 | */ 563 | void PrintSummary(ACSM_PATTERN *pattern) 564 | { 565 | ACSM_PATTERN *mlist = pattern; 566 | printf("\n### Summary ###\n"); 567 | for (; mlist != NULL; mlist = mlist->next) 568 | { 569 | if (mlist->nocase) 570 | printf("%12s : %5d\n", mlist->patrn,mlist->nmatch); 571 | else 572 | printf("%12s : %5d\n", mlist->casepatrn,mlist->nmatch); 573 | } 574 | } 575 | -------------------------------------------------------------------------------- /AC/src/acsmx.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (C) 2002 Martin Roesch 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 | */ 18 | 19 | 20 | /* 21 | ** ACSMX.H 22 | ** 23 | ** 24 | */ 25 | #ifndef _ACSMX_H 26 | #define _ACSMX_H 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | /* 33 | * Prototypes 34 | */ 35 | #define ALPHABET_SIZE 256 36 | #define MAXLEN 256 37 | 38 | #define ACSM_FAIL_STATE -1 39 | 40 | typedef struct _acsm_pattern { 41 | 42 | struct _acsm_pattern *next; 43 | unsigned char *patrn; 44 | unsigned char *casepatrn; 45 | int n; 46 | int nocase; 47 | void * id; 48 | int nmatch; 49 | 50 | } ACSM_PATTERN; 51 | 52 | 53 | typedef struct { 54 | 55 | /* Next state - based on input character */ 56 | int NextState[ ALPHABET_SIZE ]; 57 | 58 | /* Failure state - used while building NFA & DFA */ 59 | int FailState; 60 | 61 | /* List of patterns that end here, if any */ 62 | ACSM_PATTERN *MatchList; 63 | 64 | }ACSM_STATETABLE; 65 | 66 | 67 | /* 68 | * State machine Struct 69 | */ 70 | typedef struct { 71 | 72 | int acsmMaxStates; 73 | int acsmNumStates; 74 | 75 | ACSM_PATTERN * acsmPatterns; 76 | ACSM_STATETABLE * acsmStateTable; 77 | 78 | }ACSM_STRUCT; 79 | 80 | 81 | /* 82 | * Prototypes 83 | */ 84 | ACSM_STRUCT * acsmNew (); 85 | int acsmAddPattern( ACSM_STRUCT * p, unsigned char *pat, int n, int nocase); 86 | int acsmCompile ( ACSM_STRUCT * acsm ); 87 | //int acsmSearch ( ACSM_STRUCT * acsm,unsigned char * T, int n, int (*Match) (ACSM_PATTERN * pattern,ACSM_PATTERN * mlist, int nline,int index)); 88 | int acsmSearch (ACSM_STRUCT * acsm, unsigned char *Tx, int n,void (*PrintMatch) (ACSM_PATTERN * pattern,ACSM_PATTERN * mlist, int nline,int index)); 89 | void acsmFree ( ACSM_STRUCT * acsm ); 90 | void PrintMatch (ACSM_PATTERN * pattern,ACSM_PATTERN * mlist, int nline,int index) ; 91 | void PrintSummary (ACSM_PATTERN * pattern) ; 92 | 93 | extern int nline; 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /AC/src/control.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set -x 3 | abs_path=$(pwd) 4 | 5 | # global vars 6 | #start_time=$(date +"%Y-%m-%d:%H:%M:%S") 7 | time_str=$(date +"%Y-%m-%d") 8 | env_dir="data lua conf log" 9 | pro_name="acmf" 10 | 11 | Usage="$0 " 12 | if [ $# -lt 1 ]; 13 | then 14 | echo "$Usage" 15 | exit 1 16 | fi 17 | runtype=$1 18 | 19 | if [ "$runtype" != "start" ] && [ "$runtype" != "stop" ] 20 | then 21 | echo "$Usage" 22 | exit 1 23 | fi 24 | 25 | # check evn dir 26 | for dir in $env_dir 27 | do 28 | if [ -d $dir ] 29 | then 30 | echo "'$dir' diretory is exists." 31 | # delete old file for space, befor 90 days. 32 | find "$dir" -type f -mtime +90 -exec rm {} \; 33 | else 34 | echo "'$dir' is NOT exists, create it ..." 35 | mkdir -p $dir 36 | fi 37 | done 38 | 39 | # global functions { 40 | work_pids="" 41 | function get_work_pids() 42 | { 43 | work_pids=$(ps aux | grep $pro_name | grep -v grep | awk '{print $2}' | xargs) 44 | } 45 | 46 | 47 | # delete old file for space, befor 30 days. 48 | #find "$work_path/data/" -type f -mtime +30 -exec rm {} \; 49 | 50 | # stop process 51 | if [ "stop" == "$runtype" ]; then 52 | echo "Stop process, please wait a moment. :)" 53 | 54 | get_work_pids 55 | kill_pids=$work_pids 56 | 57 | #no process need to quit 58 | if [ "$kill_pids" == "" ]; then 59 | echo "No process need to quit..." 60 | exit 0 61 | fi 62 | 63 | kill -s SIGKILL $kill_pids 64 | echo "kill SIGKILL: $kill_pids" 65 | 66 | exit 0 67 | fi 68 | 69 | # start 70 | if [ "start" == "$runtype" ]; then 71 | get_work_pids 72 | if [ "$work_pids" == "" ]; then 73 | echo "It is no process working, so let it start to work." 74 | else 75 | echo "It has process working now, please stop it before start it." 76 | exit -1 77 | fi 78 | 79 | nohup $abs_path/$pro_name -p "$abs_path" & 80 | 81 | exit 0; 82 | fi 83 | 84 | -------------------------------------------------------------------------------- /AC/src/entry.c: -------------------------------------------------------------------------------- 1 | /* 2 | Author: wangyao 3 | Email: wangyao@cs.hit.edu.cn 4 | */ 5 | #include "acsmx.h" 6 | 7 | /* 8 | * Text Data Buffer 9 | */ 10 | unsigned char text[MAXLEN]; 11 | int nline; 12 | 13 | int main (int argc, char **argv) 14 | { 15 | int i, nocase = 0; 16 | FILE *fd; 17 | char filename[256]; 18 | ACSM_STRUCT *acsm = NULL; 19 | 20 | if (argc < 3) 21 | { 22 | fprintf(stderr, "Usage: acsmx filename pattern1 pattern2 ... -nocase\n"); 23 | exit (0); 24 | } 25 | 26 | acsm = acsmNew(); 27 | 28 | strncpy(filename, argv[1], sizeof(filename)); 29 | fd = fopen(filename, "r"); 30 | if (fd == NULL) 31 | { 32 | fprintf(stderr, "Open file [%s] error! \n", filename); 33 | exit(1); 34 | } 35 | 36 | for (i = 1; i < argc; i++) 37 | { 38 | if (strcmp(argv[i], "-nocase") == 0) 39 | { 40 | nocase = 1; 41 | } 42 | } 43 | 44 | for (i = 2; i < argc; i++) 45 | { 46 | if (argv[i][0] == '-') 47 | { 48 | continue; 49 | } 50 | 51 | acsmAddPattern(acsm, (unsigned char *)argv[i], strlen(argv[i]), nocase); 52 | } 53 | 54 | /* Generate GtoTo Table and Fail Table */ 55 | acsmCompile(acsm); 56 | 57 | /*Search Pattern*/ 58 | while (! feof(fd) && fgets((char *)text, MAXLEN, fd)) 59 | { 60 | acsmSearch(acsm, (unsigned char *)text, strlen((const char *)text), PrintMatch); 61 | nline++; 62 | } 63 | 64 | PrintSummary(acsm->acsmPatterns); 65 | 66 | acsmFree(acsm); 67 | 68 | printf("\n### AC Match Finished ###\n"); 69 | // system("pause"); 70 | 71 | return (0); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /AC/src/gunittest.cc: -------------------------------------------------------------------------------- 1 | // Don't forget gtest.h, which declares the testing framework. 2 | 3 | #include 4 | #include "util.h" 5 | #include "gtest/gtest.h" 6 | 7 | TEST(daemonize, setDaemon) 8 | { 9 | EXPECT_EQ(0, daemonize(1, 1)); 10 | } 11 | 12 | TEST(parse_args, parseArgs) 13 | { 14 | int argc = 1; 15 | char *argv[] = {"./test"}; 16 | EXPECT_EQ(0, parse_args(argc, argv)); 17 | } 18 | 19 | TEST(work, workProcess) 20 | { 21 | ACSM_STRUCT *acsm = NULL; 22 | 23 | int argc = 3; 24 | char *argv[] = { 25 | "./test", 26 | "-p", 27 | "../src" 28 | }; 29 | 30 | init_config(); 31 | signal_setup(); 32 | 33 | EXPECT_EQ(0, parse_args(argc, argv)); 34 | EXPECT_EQ(0, init_acsm(&acsm)); 35 | EXPECT_EQ(0, acsmCompile(acsm)); 36 | printf("init PASS\n"); 37 | 38 | struct evbuffer *buf; 39 | buf = evbuffer_new(); 40 | g_vars.acsm = acsm; 41 | 42 | EXPECT_EQ(0, list_memory_pattern(buf)); 43 | EXPECT_EQ(0, list_keyword(buf)); 44 | printf("list function PASS\n"); 45 | 46 | char word[1024] = "fuck"; 47 | EXPECT_EQ(0, filter_process(word, 1, buf)); 48 | snprintf(word, sizeof(word), "sb"); 49 | EXPECT_EQ(0, filter_process(word, 1, buf)); 50 | printf("filter process PASS\n"); 51 | 52 | evbuffer_free(buf); 53 | } 54 | -------------------------------------------------------------------------------- /AC/src/util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | config_t gconfig; 4 | global_variable_t g_vars; 5 | 6 | void usage(void) 7 | { 8 | printf(PACKAGE " " VERSION "\n"); 9 | printf("Build-date %s\n", build_date); 10 | printf("-p set ABS path(prefix), Necessarily\n" 11 | "-f filter keywords file name\n" 12 | "-v show version and help\n" 13 | "-h show this help and exit\n"); 14 | printf("-H hostname(default: %s)\n", DEFAULT_HOSTNAME); 15 | printf("-P listen port(default: %d)\n", DEFAULT_PORT); 16 | printf("-t set HTTP timeout(default: %d)\n", DEFAULT_TIMEOUT); 17 | printf("-c [0|1] case switch(default: %d)\n", DEFAULT_CASE_SWITCH); 18 | 19 | return; 20 | } 21 | 22 | int parse_args(int argc, char *argv[]) 23 | { 24 | int c = 0; 25 | int ret = 0; 26 | int t_opt; 27 | size_t str_len = 0; 28 | char tmp_str[FILE_PATH_LEN] = {0}; 29 | 30 | #if (_DEBUG) 31 | logprintf("grgc = %d", argc); 32 | #endif 33 | 34 | while (-1 != (c = getopt(argc, argv, 35 | "p:" /* ABS path for work(prefix) */ 36 | "f:" /* filter keywords file name*/ 37 | "H:" /* hostname */ 38 | "P:" /* listen port */ 39 | "t:" /* set HTTP timeout */ 40 | "c:" /* case switch */ 41 | "v" /* show version */ 42 | "h" /* show usage */ 43 | ))) 44 | { 45 | switch (c) 46 | { 47 | case 'p': 48 | str_len = strlen(optarg); 49 | if (str_len) 50 | { 51 | snprintf(gconfig.prefix, FILE_PATH_LEN, "%s", optarg); 52 | } 53 | else 54 | { 55 | usage(); 56 | ret = -1; 57 | goto FINISH; 58 | } 59 | break; 60 | 61 | case 'f': 62 | str_len = strlen(optarg); 63 | if (str_len) 64 | { 65 | snprintf(tmp_str, sizeof(tmp_str), "%s", optarg); 66 | } 67 | else 68 | { 69 | usage(); 70 | ret = -1; 71 | goto FINISH; 72 | } 73 | break; 74 | 75 | case 'H': 76 | str_len = strlen(optarg); 77 | if (str_len) 78 | { 79 | snprintf(gconfig.hostname, HOST_NAME_LEN, "%s", optarg); 80 | } 81 | else 82 | { 83 | usage(); 84 | ret = -1; 85 | goto FINISH; 86 | } 87 | break; 88 | 89 | case 'P': 90 | t_opt = atoi(optarg); 91 | if (t_opt > 0) 92 | { 93 | gconfig.port = t_opt; 94 | } 95 | break; 96 | 97 | case 't': 98 | t_opt = atoi(optarg); 99 | if (t_opt > 0 && t_opt <= 60 ) 100 | { 101 | gconfig.timeout = t_opt; 102 | } 103 | break; 104 | 105 | case 'c': 106 | t_opt = atoi(optarg); 107 | gconfig.no_case = t_opt; 108 | break; 109 | 110 | case 'v': 111 | case 'h': 112 | usage(); 113 | exit(EXIT_SUCCESS); 114 | } 115 | } 116 | 117 | snprintf(gconfig.keyword_file, sizeof(gconfig.keyword_file), 118 | "%s/data/%s", gconfig.prefix, tmp_str[0] ? tmp_str : DEFINE_KEYWORD_FILE); 119 | 120 | FINISH: 121 | return ret; 122 | } 123 | 124 | void print_config(void) 125 | { 126 | printf("---gconfig---\n"); 127 | printf("prefix: %s\n", gconfig.prefix); 128 | printf("keyword_file: %s\n", gconfig.keyword_file); 129 | printf("hostname: %s\n", gconfig.hostname); 130 | printf("port: %d\n", gconfig.port); 131 | printf("timeout: %d\n", gconfig.timeout); 132 | printf("no_case: %d\n", gconfig.no_case); 133 | printf("---end print gconfig---\n"); 134 | 135 | return; 136 | } 137 | 138 | int daemonize(int nochdir, int noclose) 139 | { 140 | int fd; 141 | 142 | switch (fork()) 143 | { 144 | case -1: 145 | return (-1); 146 | 147 | case 0: 148 | break; 149 | 150 | default: 151 | _exit(EXIT_SUCCESS); 152 | } 153 | 154 | if (setsid() == -1) 155 | return (-1); 156 | 157 | if (nochdir == 0) 158 | { 159 | if(chdir("/") != 0) 160 | { 161 | perror("chdir"); 162 | return (-1); 163 | } 164 | } 165 | 166 | if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) 167 | { 168 | if (dup2(fd, STDIN_FILENO) < 0) 169 | { 170 | perror("dup2 stdin"); 171 | return (-1); 172 | } 173 | if (dup2(fd, STDOUT_FILENO) < 0) 174 | { 175 | perror("dup2 stdout"); 176 | return (-1); 177 | } 178 | if (dup2(fd, STDERR_FILENO) < 0) 179 | { 180 | perror("dup2 stderr"); 181 | return (-1); 182 | } 183 | 184 | if (fd > STDERR_FILENO) 185 | { 186 | if (close(fd) < 0) 187 | { 188 | perror("close"); 189 | return (-1); 190 | } 191 | } 192 | } 193 | 194 | return(0); 195 | } 196 | 197 | void handler(int signo) 198 | { 199 | fprintf(stderr, "Get one signal: %d. man sigaction.\n", signo); 200 | return; 201 | } 202 | 203 | void signal_setup(void) 204 | { 205 | static int signo[] = { 206 | SIGHUP, 207 | SIGINT, /* ctrl + c */ 208 | SIGCHLD, /* 僵死进程或线程的信号 */ 209 | SIGPIPE, 210 | SIGALRM, 211 | SIGUSR1, 212 | SIGUSR2, 213 | SIGTERM, 214 | //SIGCLD, 215 | 216 | #ifdef SIGTSTP 217 | /* background tty read */ 218 | SIGTSTP, 219 | #endif 220 | #ifdef SIGTTIN 221 | /* background tty read */ 222 | SIGTTIN, 223 | #endif 224 | #ifdef SIGTTOU 225 | SIGTTOU, 226 | #endif 227 | SIGNO_END 228 | }; 229 | 230 | int i = 0; 231 | struct sigaction sa; 232 | //sa.sa_handler = SIG_IGN; //设定接受到指定信号后的动作为忽略 233 | sa.sa_handler = handler; 234 | sa.sa_flags = SA_SIGINFO; 235 | 236 | if (-1 == sigemptyset(&sa.sa_mask)) //初始化信号集为空 237 | { 238 | fprintf(stderr, "failed to init sa_mask.\n"); 239 | exit(EXIT_FAILURE); 240 | } 241 | 242 | for (i = 0; SIGNO_END != signo[i]; i++) 243 | { 244 | //屏蔽信号 245 | if (-1 == sigaction(signo[i], &sa, NULL)) 246 | { 247 | fprintf(stderr, "failed to ignore: %d\n", signo[i]); 248 | exit(EXIT_FAILURE); 249 | } 250 | } 251 | 252 | return (void)0; 253 | } 254 | 255 | void init_config(void) 256 | { 257 | 258 | gconfig.log_level = DEFAULT_LOG_LEVEL; 259 | gconfig.no_case = DEFAULT_CASE_SWITCH; 260 | gconfig.port = DEFAULT_PORT; 261 | gconfig.timeout = DEFAULT_TIMEOUT; 262 | 263 | snprintf(gconfig.prefix, sizeof(gconfig.prefix), "%s", DEFAULT_PREFIX); 264 | snprintf(gconfig.hostname, HOST_NAME_LEN, "%s", DEFAULT_HOSTNAME); 265 | snprintf(gconfig.keyword_file, FILE_PATH_LEN, "%s/data/%s", 266 | gconfig.prefix, DEFINE_KEYWORD_FILE); 267 | 268 | return; 269 | } 270 | 271 | int init_acsm(ACSM_STRUCT **acsm) 272 | { 273 | int ret = 0; 274 | 275 | FILE *fp = NULL; 276 | char line[READ_LINE_BUF_LEN] = {0}; 277 | char *p = NULL; 278 | 279 | *acsm = acsmNew(); 280 | fp = fopen(gconfig.keyword_file, "r"); 281 | if (fp == NULL) 282 | { 283 | fprintf(stderr,"Open file error: %s\n", gconfig.keyword_file); 284 | exit(1); 285 | } 286 | 287 | while (! feof(fp)) 288 | { 289 | if (NULL == fgets(line, READ_LINE_BUF_LEN - 1, fp)) 290 | { 291 | continue; 292 | } 293 | 294 | line[READ_LINE_BUF_LEN - 1] = '\0'; 295 | if (NULL != (p = strstr(line, "\n"))) 296 | { 297 | *p = '\0'; 298 | } 299 | 300 | #if (_DEBUG) 301 | logprintf("line: [%s]", line); 302 | #endif 303 | acsmAddPattern(*acsm, (unsigned char *)line, strlen(line), gconfig.no_case); 304 | } 305 | 306 | return ret; 307 | } 308 | 309 | void clear_match_count(void) 310 | { 311 | ACSM_PATTERN *mlist = NULL; 312 | 313 | mlist = g_vars.acsm->acsmPatterns; 314 | for (; NULL != mlist; mlist = mlist->next) 315 | { 316 | mlist->nmatch = 0; 317 | } 318 | 319 | return; 320 | } 321 | 322 | int filter_process(const char *data, int output_format, struct evbuffer *ev_buf) 323 | { 324 | assert(NULL != ev_buf); 325 | 326 | int ret = 0; 327 | int hit = 0; 328 | ACSM_PATTERN * mlist = NULL; 329 | 330 | if (data) 331 | { 332 | //clear_match_count(); 333 | hit = acsmSearch(g_vars.acsm, (unsigned char *)data, strlen(data), PrintMatch); 334 | //logprintf("acsmSearch() = %d", ret); 335 | mlist = g_vars.acsm->acsmPatterns; 336 | 337 | switch (output_format) 338 | { 339 | case OUTPUT_AS_JSON: /** json */ 340 | { 341 | evbuffer_add_printf(ev_buf, "{\"error\": 0, \"stat\": ["); 342 | 343 | int flag = 0; 344 | for (; NULL != mlist; mlist = mlist->next) 345 | { 346 | if (! mlist->nmatch) 347 | { 348 | continue; 349 | } 350 | 351 | evbuffer_add_printf(ev_buf, "%s{\"keyword\": \"%s\", \"hit_count\": %d}", 352 | flag ? ", " : "", 353 | mlist->nocase ? mlist->patrn : mlist->casepatrn, mlist->nmatch); 354 | 355 | flag = 1; 356 | mlist->nmatch = 0; 357 | } 358 | 359 | evbuffer_add_printf(ev_buf, "]}"); 360 | break; 361 | } 362 | 363 | case OUTPUT_AS_HTML: /** html */ 364 | default: 365 | { 366 | evbuffer_add_printf(ev_buf, "ac server demo\ 367 | \ 368 |
word: %s
\ 369 |
***filter result***
\ 370 |
", 371 | data ? data : "No input."); 372 | for (; NULL != mlist; mlist = mlist->next) 373 | { 374 | if (! mlist->nmatch) 375 | { 376 | continue; 377 | } 378 | 379 | evbuffer_add_printf(ev_buf, "
filter-key: %s, hit count: %d
", 380 | mlist->nocase ? mlist->patrn : mlist->casepatrn, mlist->nmatch); 381 | 382 | mlist->nmatch = 0; 383 | } 384 | evbuffer_add_printf(ev_buf, "
"); 385 | break; 386 | } 387 | } 388 | } 389 | 390 | return ret; 391 | } 392 | 393 | int list_keyword(struct evbuffer *ev_buf) 394 | { 395 | assert(NULL != ev_buf); 396 | 397 | int ret = 0; 398 | int fd = 0; 399 | struct stat stat_buf; 400 | size_t size = 0; 401 | char read_buf[1024 * 10] = {0}; 402 | ssize_t r_size = 0; 403 | 404 | fd = open(gconfig.keyword_file, O_RDONLY); 405 | if (-1 == fd || 0 == fd) 406 | { 407 | evbuffer_add_printf(ev_buf, "Can NOT open('%s')\n", gconfig.keyword_file); 408 | ret = -1; 409 | goto FINISH; 410 | } 411 | 412 | if (0 != fstat(fd, &stat_buf)) 413 | { 414 | evbuffer_add_printf(ev_buf, "Can get fstat()\n"); 415 | ret = -1; 416 | goto STAT_ERR; 417 | } 418 | 419 | evbuffer_add_printf(ev_buf, "
");
420 |     // stat_buf.st_size;
421 |     size = 0;
422 |     while (size <= stat_buf.st_size)
423 |     {
424 |         lseek(fd, size, SEEK_SET);
425 |         r_size = read(fd, read_buf, sizeof(read_buf) - 1);
426 |         if (-1 == r_size)
427 |         {
428 |             break;
429 |         }
430 |         read_buf[r_size] = '\0';
431 | #if (_DEBUG)
432 |         logprintf("read: [%s]", read_buf);
433 | #endif
434 |         evbuffer_add_printf(ev_buf, "%s", read_buf);
435 | 
436 |         size += r_size;
437 |         if (0 == r_size)
438 |         {
439 |             break;
440 |         }
441 |     }
442 |     evbuffer_add_printf(ev_buf, "
"); 443 | 444 | STAT_ERR: 445 | close(fd); 446 | 447 | FINISH: 448 | return ret; 449 | } 450 | 451 | int list_memory_pattern(struct evbuffer *ev_buf) 452 | { 453 | assert(NULL != ev_buf); 454 | 455 | int ret = 0; 456 | ACSM_PATTERN *mlist = NULL; 457 | 458 | evbuffer_add_printf(ev_buf, "
\n"
459 |             "---dump memory pattern---\n");
460 |     mlist = g_vars.acsm->acsmPatterns;
461 |     for (; NULL != mlist; mlist = mlist->next)
462 |     {
463 |         mlist->nmatch = 0;
464 |         evbuffer_add_printf(ev_buf, "%s\n", mlist->patrn);
465 |     }
466 |     evbuffer_add_printf(ev_buf, "
"); 467 | 468 | return ret; 469 | } 470 | 471 | void api_proxy_handler(struct evhttp_request *req, void *arg) 472 | { 473 | // 初始化返回客户端的数据缓存 474 | struct evbuffer *buf; 475 | buf = evbuffer_new(); 476 | 477 | /* 分析URL参数 */ 478 | char *decode_uri = strdup((char*) evhttp_request_uri(req)); 479 | struct evkeyvalq http_query; 480 | evhttp_parse_query(decode_uri, &http_query); 481 | 482 | int output_format = 0; 483 | int do_action = ACTION_FILTER; 484 | char post_buf[POST_DATA_BUF_LEN] = {0}; 485 | char *p = NULL; 486 | char *pt = NULL; 487 | char *find = NULL; 488 | 489 | #if (_DEBUG) 490 | logprintf("uri: %s", decode_uri); 491 | #endif 492 | 493 | /** free memory */ 494 | free(decode_uri); 495 | 496 | #if (_DEBUG) 497 | #ifdef TAILQ_FOREACH 498 | //遍历整个uri的对应关系值 499 | { 500 | logprintf("--- foreach uri ---"); 501 | struct evkeyval *header; 502 | TAILQ_FOREACH(header, &http_query, next) { 503 | logprintf("%s: %s", header->key, header->value); 504 | } 505 | logprintf("--- end uri ---"); 506 | } 507 | //遍历整个请求头. 508 | { 509 | logprintf("---- foreach request header ----"); 510 | struct evkeyvalq *input_headers = evhttp_request_get_input_headers(req); 511 | struct evkeyval *header; 512 | TAILQ_FOREACH(header, input_headers, next) { 513 | logprintf("%s: %s", header->key, header->value); 514 | } 515 | logprintf("---- end request header ----"); 516 | } 517 | #endif 518 | #endif 519 | 520 | /* 接收 GET 解析参数 */ 521 | const char *word = evhttp_find_header(&http_query, "word"); 522 | const char *action = evhttp_find_header(&http_query, "action"); 523 | const char *uri_format = evhttp_find_header(&http_query, "format"); 524 | 525 | if (NULL != action) 526 | { 527 | if (0 == strncmp(action, "list", 4)) 528 | { 529 | do_action = ACTION_LIST; 530 | } 531 | else if (0 == strncmp(action, "memory", 6)) 532 | { 533 | do_action = ACTION_MEMORY; 534 | } 535 | } 536 | 537 | if (uri_format && 0 == strncmp(uri_format, FORMAT_JSON, sizeof(FORMAT_JSON) - 1)) 538 | { 539 | output_format = OUTPUT_AS_JSON; 540 | } 541 | 542 | /** 接受 PSOT 数据 */ 543 | const char *post_data = (char *)EVBUFFER_DATA(req->input_buffer); 544 | if (post_data) 545 | { 546 | snprintf(post_buf, sizeof(post_buf), "%s", post_data); 547 | logprintf("POST: [%s]", post_buf); 548 | find = post_buf; 549 | if (NULL != (find = strstr(post_buf, "word="))) 550 | { 551 | find += 5; 552 | p = find; 553 | 554 | if (NULL != (pt = strchr(p, '&'))) 555 | { 556 | *pt = '\0'; 557 | } 558 | 559 | word = find; 560 | } 561 | } 562 | #if (_DEBUG) 563 | else 564 | { 565 | logprintf("NO POST data."); 566 | } 567 | #endif 568 | 569 | switch (do_action) 570 | { 571 | case ACTION_LIST: 572 | list_keyword(buf); 573 | break; 574 | 575 | case ACTION_MEMORY: 576 | list_memory_pattern(buf); 577 | break; 578 | 579 | case ACTION_FILTER: 580 | default: 581 | // portions handle 582 | filter_process(word, output_format, buf); 583 | break; 584 | } 585 | //处理输出header头 586 | evhttp_add_header(req->output_headers, "Content-Type", output_format ? 587 | "application/json; charset=UTF-8" : 588 | "text/html; charset=UTF-8"); 589 | evhttp_add_header(req->output_headers, "Status", "200 OK"); 590 | evhttp_add_header(req->output_headers, "Connection", "keep-alive"); 591 | evhttp_add_header(req->output_headers, "Cache-Control", "no-cache"); 592 | evhttp_add_header(req->output_headers, "Expires", "-1"); 593 | evhttp_add_header(req->output_headers, "Server", SERVER_TAG); /** libevent http server */ 594 | 595 | //返回code 200 596 | evhttp_send_reply(req, HTTP_OK, "OK", buf); 597 | 598 | //释放内存 599 | evhttp_clear_headers(&http_query); 600 | evbuffer_free(buf); 601 | 602 | return; 603 | } 604 | 605 | -------------------------------------------------------------------------------- /AC/src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_H 2 | #define _UTIL_H 3 | #include "ac_mf.h" 4 | 5 | void usage(void); 6 | 7 | int parse_args(int argc, char *argv[]); 8 | 9 | void print_config(void); 10 | 11 | int daemonize(int nochdir, int noclose); 12 | 13 | void handler(int signo); 14 | 15 | void signal_setup(void); 16 | 17 | void init_config(void); 18 | 19 | int init_acsm(ACSM_STRUCT **acsm); 20 | 21 | void clear_match_count(void); 22 | 23 | int filter_process(const char *data, int output_format, struct evbuffer *ev_buf); 24 | 25 | int list_keyword(struct evbuffer *ev_buf); 26 | 27 | int list_memory_pattern(struct evbuffer *ev_buf); 28 | 29 | void api_proxy_handler(struct evhttp_request *req, void *arg); 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /AC/test/gpl.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /AC/test/ir.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 13 |
7 |
8 | 哈尔滨工业大学信息检索研究室 9 |
10 | 友爱  精诚  乐学  日新 11 |
12 |

14 | 15 | 16 | 137 | 306 | 351 | 352 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 |
26 |
HIT-IRLab

27 |
28 | 31 | 32 | 35 | 36 | 39 | 40 | 43 | 44 | 47 | 48 | 51 | 52 | 55 | 56 | 59 | 60 | 63 | 64 | 67 | 68 | 71 | 72 | 75 | 76 | 79 | 80 | 83 | 84 | 87 |
29 | 首  页 30 |
33 | 成员介绍 34 |
37 | 研 究 组 38 |
41 | 科研项目 42 |
45 | 新  闻 46 |
49 | 下  载 50 |
53 | 发表论文 54 |
57 | 技术推广 58 |
61 | 在线演示 62 |
65 | 相关链接 66 |
69 | 电子邮件 70 |
73 | 论  坛 74 |
77 | 博  客 78 |
81 | Wiki 82 |
85 | English 86 |
88 |
97 |
98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 |
107 |
Log In

108 |
109 |
110 | 111 | 112 | Username
113 |
114 | Password
115 |
116 |
117 | 118 |
119 |
120 |
121 | Forgot Your Password? 122 |
123 |
124 |
133 |
134 | 135 | 136 |
138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 |
147 |
热点

148 | 153 |
162 |
163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 |
172 |
Announcements

173 |
174 | 175 | 176 | 180 | 181 | 184 |
IR迎新春足球赛圆满结束
177 | Posted by: dyzlj1984 on 04/22/2007 09:28 PM 178 | (Read: 46) 179 |
182 | Read More 183 |
185 | 186 | 187 | 191 | 192 | 195 |
IR迎新春篮球赛圆满结束
188 | Posted by: dyzlj1984 on 04/15/2007 04:06 PM 189 | (Read: 111) 190 |
193 | Read More 194 |
196 | 197 | 198 | 202 | 203 | 206 |
哈工大金山联合实验室词霸搜索项目组在京成立
199 | Posted by: dyzlj1984 on 04/13/2007 05:13 PM 200 | (Read: 175) 201 |
204 | Read More 205 |
207 | 208 | 209 | 213 | 214 | 217 |
信息检索实验室在SemEval-2007评测中获得一项第一名
210 | Posted by: dyzlj1984 on 04/12/2007 05:43 PM 211 | (Read: 205) 212 |
215 | Read More 216 |
218 | 219 | 220 | 224 | 225 | 228 |
车万翔发表ACL论文
221 | Posted by: dyzlj1984 on 03/26/2007 03:45 PM 222 | (Read: 468) 223 |
226 | Read More 227 |
229 |
230 |
239 |
240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 |
249 |
信息检索研究室简介

250 |
251 | 252 | 253 | 254 | 255 | 256 | 280 | 281 | 282 |
257 | 258 | 信息检索研究室简介 259 | 260 | 261 |

262 |     哈工大信息检索研究室 (HIT IR-Lab) 成立于 2001 年 3 月1日,隶属于以李生教授为主任的教育部重点实验室。信息检索研究室主任为刘挺教授,研究人员包括张宇副教授、秦兵副教授和车万翔讲师/博士生。
263 |
264 |     目前,哈工大信息检索研究室的研究方向包括文本检索、文本挖掘和语言分析三个方面,研究室以语言分析为基础研究,以信息抽取、文本检索等为应用研究,以人物资讯中心为应用系统平台。研究室已完成和现承担的国家自然科学基金、国家863、国际合作、企业合作等课题二十余项。在这些项目的支持下已打造出“语言技术平台LTP”。
265 |
266 |     研究室坚持理论研究与技术开发互动同步发展的原则,一方面在向技术极限挑战的过程中撰写高质量的论文,一方面将陆续完成的阶段性成果适时地转化为实用技术。文本检索及相关技术在数字图书馆、内容安全、商务智能、语言学习、军事情报、移动计算和电子政务等各个领域均有巨大的应用价值。研究室主要通过与企业合作,采取将技术嵌入企业的产品中的方式,实现研究的价值,回报社会。
267 |
268 |     研究室努力营造浓厚的学术氛围,悉心培养优秀学子。目前实验室有9名博士生,19名硕士生,学生中多人次获美国数学建模竞赛奖、IBM奖学金、计算机世界奖学金、罗克维尔奖学金等。
269 |
270 |     HIT-IRLab是语言语音教育部微软重点实验室、哈工大-IBM联合实验室、哈工大-金山联合实验室中的重要成员,与国内外10余家相关的研究机构和企业保持着密切而友好的合作关系。哈工大信息检索研究室是一个年轻的团队,她渴望向国内和国际的同行们学习,也愿意尽自己的努力在计算机应用领域做出贡献。
271 |
272 |     联系我们:
273 |         电话:+86-451-86413683或86402993
274 |         地址:哈尔滨市南岗区教化街27号6楼
275 |         通信地址:哈尔滨工业大学321信箱
276 |         电子邮件:webmaster [At] ir.hit.edu.cn
277 |

278 | 279 |
283 |
284 | 285 | 286 | 290 | 292 |
287 | Created on 2003-02-04 10:24:27 by install
288 | Updated on 2007-01-20 18:53:36 by tliu 289 |
 Printable Version 291 |
293 |
294 |
303 |
304 | 305 |
307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 |
316 |
Recently Added Documents

317 |
Name: 计算机新进展讲义-中文信息处理纵览-2007
318 | Updated: 03/24/2007 10:41 PM 319 |
320 | Name: 英文文本操作技术
321 | Updated: 01/04/2007 03:21 PM 322 |
323 | Name: ACE06评测介绍
324 | Updated: 06/19/2006 07:08 PM 325 |
326 | Name: (阅读报告)A probability model for retrospective news event detection
327 | Updated: 06/14/2006 10:57 AM 328 |
329 | Name: Paper Summarization Of “Introduction to the Special Issue on Computational Anaphora Resolution”
330 | Updated: 06/13/2006 10:07 PM 331 |
332 | Name: Paper Summarization Of “ANAPHORA RESOLUTION: THE STATE OF ART”
333 | Updated: 06/13/2006 10:04 PM 334 |
335 | Name: Web文本聚类工作
336 | Updated: 06/13/2006 09:59 PM 337 |
338 |
347 |
348 | 349 | 350 |
353 |
354 |
Copyright © Information Retrieval Lab, Harbin Institute of Technology 2001 - 2006
355 | P.O.Box 321, HIT, P.R.China 150001
356 | webmaster at ir dot hit dot edu dot cn 357 |
358 |
359 | 360 | 361 | -------------------------------------------------------------------------------- /AC/test/simple.txt: -------------------------------------------------------------------------------- 1 | hh abcd efgh abc test -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # algorithm 2 | 3 | Algorithm research. 4 | 5 | ## AC 有限状态自动状态机 6 | 7 | 请移步 [AC](https://github.com/hy0kl/algorithm/tree/master/AC) 8 | -------------------------------------------------------------------------------- /c/atoi.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: atoi 函数实现 3 | * @see: http://blog.csdn.net/u014082714/article/details/44775269 4 | * @author: Jerry Yang(hy0kle@gmail.com) 5 | * */ 6 | #include 7 | 8 | /** 来自 linux内核的 atoi 函数实现 */ 9 | static int local_atoi(const char *name) 10 | { 11 | int val = 0; 12 | 13 | for (;; name++) { 14 | switch (*name) { 15 | case '0' ... '9': 16 | val = 10 * val + (*name - '0'); 17 | break; 18 | default: 19 | return val; 20 | } 21 | } 22 | } 23 | 24 | int 25 | isspace(int x) 26 | { 27 | if (x ==' '|| x == '\t' || x == '\n' || x == '\f' || x == '\b' || x == '\r') 28 | return 1; 29 | else 30 | return 0; 31 | } 32 | 33 | int 34 | isdigit(int x) 35 | { 36 | if (x <= '9' && x >= '0') 37 | return 1; 38 | else 39 | return 0; 40 | 41 | } 42 | 43 | int 44 | atoi(const char *nptr) 45 | { 46 | int c; /* current char */ 47 | int total; /* current total */ 48 | int sign; /* if '-', then negative, otherwise positive */ 49 | 50 | /* skip whitespace */ 51 | while (isspace((int)(unsigned char)*nptr)) 52 | ++nptr; 53 | 54 | c = (int)(unsigned char)*nptr++; 55 | sign = c; /* save sign indication */ 56 | if (c == '-' || c == '+') 57 | c = (int)(unsigned char)*nptr++; /* skip sign */ 58 | 59 | total = 0; 60 | 61 | while (isdigit(c)) { 62 | total = 10 * total + (c - '0'); /* accumulate digit */ 63 | c = (int)(unsigned char)*nptr++; /* get next char */ 64 | } 65 | 66 | if (sign == '-') 67 | return -total; 68 | else 69 | return total; /* return result, negated if necessary */ 70 | } 71 | 72 | int main(int argc, char *argv[]) 73 | { 74 | char *num = "1024"; 75 | char *s_num = "-1024"; 76 | printf("local_atoi(\"%s\") = %d\n", num, local_atoi(num)); 77 | printf("atoi(\"%s\") = %d\n", s_num, atoi(s_num)); 78 | 79 | return 0; 80 | } 81 | 82 | /* vim:set ft=c ts=4 sw=4 et fdm=marker: */ 83 | 84 | -------------------------------------------------------------------------------- /c/fib.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 斐波那契数列 3 | * @see: https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97 4 | * @author: Jerry Yang(hy0kle@gmail.com) 5 | * 数学上: 6 | * F(0) = 0 7 | * F(1) = 1 8 | * F(n) = F(n -1) + F(n - 2) 9 | * 10 | * # 常见的包装题: 11 | * 已知 12 | * 1. n 个台阶 13 | * 2. 一次只走一个或两个台阶 14 | * 求 共有多种走法 15 | * 误区: 很容易产生排列组合的错觉 16 | * 解法: 从1个台阶到5个台阶,写出所有的可能的走法 17 | * f(1) = [(1)], 1 18 | * f(2) = [(1, 1), (2)], 2 19 | * f(3) = [(1, 1, 1), (1, 2), (2, 1)], 3 20 | * f(4) = [(1, 1, 1, 1), (1, 1, 2), (1, 2, 1), (2, 1, 1), (2, 2)] 5 21 | * f(5) = [(1, 1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 2, 1), (1, 2, 1, 1), (2, 1, 1, 1), (1, 2, 2), (2, 1, 2), (2, 2, 1)] 8 22 | * 数学归纳法发现,其本质是个变种版的斐波那契数列 23 | * */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | /** 递归的解法 */ 30 | int 31 | fib_recur(int n) 32 | { 33 | assert(n >= 0); 34 | 35 | if (n <= 2) { 36 | return n; 37 | } 38 | 39 | return fib_recur(n - 1) + fib_recur(n - 2); 40 | } 41 | 42 | /** 迭代解法 */ 43 | int 44 | fib(int n) 45 | { 46 | assert(n >= 0); 47 | 48 | if (n <= 2) { 49 | return n; 50 | } 51 | 52 | int fib_f = 1; 53 | int fib_s = 2; 54 | 55 | for (int i = 3; i <= n; i++) { 56 | int fib_t = fib_f + fib_s; 57 | fib_f = fib_s; 58 | fib_s = fib_t; 59 | } 60 | 61 | return fib_s; 62 | } 63 | 64 | int main(int argc, char *argv[]) 65 | { 66 | int n = 6; 67 | 68 | if (argc > 1) { 69 | int input = atoi(argv[1]); 70 | if (input > 0) { 71 | n = input; 72 | } 73 | } 74 | 75 | printf("Fibonacci-recursion(%d) = %d\n", n, fib_recur(n)); 76 | printf("Fibonacci-iter(%d) = %d\n", n, fib(n)); 77 | 78 | return 0; 79 | } 80 | 81 | /* vim:set ft=c ts=4 sw=4 et fdm=marker: */ 82 | 83 | -------------------------------------------------------------------------------- /c/list.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 链表 3 | * @author: Jerry Yang(hy0kle@gmail.com) 4 | * */ 5 | #include 6 | #include 7 | 8 | #define EXIT_WITH_MALLOC 11 9 | 10 | /** 单链表 */ 11 | typedef struct list_node_s list_node_t; 12 | 13 | struct list_node_s { 14 | //void *data; 15 | int number; 16 | list_node_t *next; 17 | }; 18 | 19 | typedef struct { 20 | list_node_t *head; 21 | list_node_t *tail; 22 | size_t elts; /** 当前元素的个数 */ 23 | } list_t; 24 | 25 | list_t * 26 | list_create() 27 | { 28 | list_t *l = malloc(sizeof(list_t)); 29 | if (NULL == l) { 30 | printf("Can create list, need size: %lu\n", sizeof(list_t)); 31 | exit(EXIT_WITH_MALLOC); 32 | } 33 | 34 | l->head = NULL; 35 | l->tail = NULL; 36 | l->elts = 0; 37 | 38 | return l; 39 | } 40 | 41 | void * 42 | list_push(list_t *l, int number) 43 | { 44 | list_node_t *node = malloc(sizeof(list_node_t)); 45 | if (NULL == node) { 46 | printf("Can malloc for node, need size: %lu\n", sizeof(list_node_t)); 47 | exit(EXIT_WITH_MALLOC); 48 | } 49 | 50 | node->number = number; 51 | node->next = NULL; 52 | l->elts++; 53 | 54 | /** 从表头插入 */ 55 | if (NULL == l->tail) { 56 | l->head = node; 57 | l->tail = node; 58 | } else { 59 | node->next = l->head; 60 | l->head = node; 61 | } 62 | 63 | return node; 64 | } 65 | 66 | list_t * 67 | list_revert(list_t *l) 68 | { 69 | if (NULL == l->head || NULL == l->head->next) { 70 | return l; 71 | } 72 | 73 | list_node_t *prev = l->head; 74 | list_node_t *curt = l->head->next; 75 | list_node_t *next = NULL; 76 | 77 | while (curt != NULL) { 78 | next = curt->next; 79 | curt->next = prev; 80 | prev = curt; 81 | curt = next; 82 | } 83 | 84 | l->head->next = NULL; 85 | l->tail = l->head; /** 头尾互换 */ 86 | l->head = prev; 87 | 88 | return l; 89 | } 90 | 91 | void 92 | print_list(list_t *l) 93 | { 94 | list_node_t *node = l->head; 95 | while (node != NULL) { 96 | printf("list.node->number = %d\n", node->number); 97 | node = node->next; 98 | } 99 | } 100 | 101 | int main(int argc, char *argv[]) 102 | { 103 | list_t *l = list_create(); 104 | 105 | list_push(l, 110); 106 | list_push(l, 128); 107 | list_push(l, 1024); 108 | 109 | print_list(l); 110 | printf("list size: %lu\n", l->elts); 111 | 112 | printf("revert list >>>\n"); 113 | list_revert(l); 114 | print_list(l); 115 | 116 | return 0; 117 | } 118 | 119 | /* vim:set ft=c ts=4 sw=4 et fdm=marker: */ 120 | 121 | -------------------------------------------------------------------------------- /c/yang-hui.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 杨辉三角 3 | * @see: http://www.cnblogs.com/clover-toeic/p/3766001.html 4 | * @author: Jerry Yang(hy0kle@gmail.com) 5 | * */ 6 | #include 7 | #include 8 | 9 | #define MAX_ROW 10 10 | 11 | /** 通过组合公式推导 */ 12 | void 13 | BinomialYangHui(void) 14 | { 15 | int dwRow = 0, dwCol = 0, dwTriVal; 16 | 17 | for (dwRow = 0; dwRow < MAX_ROW; dwRow++) { 18 | // 首列直接输出1,否则由二项式系数递推公式求出杨辉值 19 | dwTriVal = 1; 20 | for (dwCol = 0; dwCol <= dwRow; dwCol++) { 21 | printf("%5d", dwTriVal); 22 | dwTriVal = dwTriVal * (dwRow - dwCol) / (dwCol + 1); 23 | } 24 | printf("\n"); 25 | } 26 | } 27 | 28 | int main(int argc, char *argv[]) 29 | { 30 | BinomialYangHui(); 31 | 32 | return 0; 33 | } 34 | 35 | /* vim:set ft=c ts=4 sw=4 et fdm=marker: */ 36 | 37 | -------------------------------------------------------------------------------- /event/block-http-client.c: -------------------------------------------------------------------------------- 1 | /* For sockaddr_in */ 2 | #include 3 | /* For socket functions */ 4 | #include 5 | /* For gethostbyname */ 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char **argv) 13 | { 14 | const char query[] = 15 | "GET / HTTP/1.0\r\n" 16 | "Host: www.google.com\r\n" 17 | "\r\n"; 18 | const char hostname[] = "www.google.com"; 19 | struct sockaddr_in sin; 20 | struct hostent *h; 21 | const char *cp; 22 | int fd; 23 | ssize_t n_written, remaining; 24 | char buf[1024]; 25 | 26 | /* Look up the IP address for the hostname. Watch out; this isn't 27 | threadsafe on most platforms. */ 28 | h = gethostbyname(hostname); 29 | if (!h) { 30 | fprintf(stderr, "Couldn't lookup %s: %s", hostname, hstrerror(h_errno)); 31 | return 1; 32 | } 33 | if (h->h_addrtype != AF_INET) { 34 | fprintf(stderr, "No ipv6 support, sorry."); 35 | return 1; 36 | } 37 | 38 | /* Allocate a new socket */ 39 | fd = socket(AF_INET, SOCK_STREAM, 0); 40 | if (fd < 0) { 41 | perror("socket"); 42 | return 1; 43 | } 44 | 45 | /* Connect to the remote host. */ 46 | sin.sin_family = AF_INET; 47 | sin.sin_port = htons(80); 48 | sin.sin_addr = *(struct in_addr*)h->h_addr; 49 | if (connect(fd, (struct sockaddr*) &sin, sizeof(sin))) { 50 | perror("connect"); 51 | close(fd); 52 | return 1; 53 | } 54 | 55 | /* Write the query. */ 56 | /* XXX Can send succeed partially? */ 57 | cp = query; 58 | remaining = strlen(query); 59 | while (remaining) { 60 | n_written = send(fd, cp, remaining, 0); 61 | if (n_written <= 0) { 62 | perror("send"); 63 | return 1; 64 | } 65 | remaining -= n_written; 66 | cp += n_written; 67 | } 68 | 69 | /* Get an answer back. */ 70 | while (1) { 71 | ssize_t result = recv(fd, buf, sizeof(buf), 0); 72 | if (result == 0) { 73 | break; 74 | } else if (result < 0) { 75 | perror("recv"); 76 | close(fd); 77 | return 1; 78 | } 79 | 80 | fwrite(buf, 1, result, stdout); 81 | } 82 | 83 | close(fd); 84 | return 0; 85 | } 86 | 87 | -------------------------------------------------------------------------------- /event/low-level-rot13-sever.c: -------------------------------------------------------------------------------- 1 | /* For sockaddr_in */ 2 | #include 3 | /* For socket functions */ 4 | #include 5 | /* For fcntl */ 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define MAX_LINE 16384 18 | 19 | /** 20 | * gcc low-level-rot13-sever.c -levent 21 | * */ 22 | 23 | void do_read(evutil_socket_t fd, short events, void *arg); 24 | void do_write(evutil_socket_t fd, short events, void *arg); 25 | 26 | char 27 | rot13_char(char c) 28 | { 29 | /* We don't want to use isalpha here; setting the locale would change 30 | * which characters are considered alphabetical. */ 31 | if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M')) 32 | return c + 13; 33 | else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z')) 34 | return c - 13; 35 | else 36 | return c; 37 | } 38 | 39 | struct fd_state { 40 | char buffer[MAX_LINE]; 41 | size_t buffer_used; 42 | 43 | size_t n_written; 44 | size_t write_upto; 45 | 46 | struct event *read_event; 47 | struct event *write_event; 48 | }; 49 | 50 | struct fd_state * 51 | alloc_fd_state(struct event_base *base, evutil_socket_t fd) 52 | { 53 | struct fd_state *state = malloc(sizeof(struct fd_state)); 54 | if (!state) 55 | return NULL; 56 | state->read_event = event_new(base, fd, EV_READ|EV_PERSIST, do_read, state); 57 | if (!state->read_event) { 58 | free(state); 59 | return NULL; 60 | } 61 | state->write_event = 62 | event_new(base, fd, EV_WRITE|EV_PERSIST, do_write, state); 63 | 64 | if (!state->write_event) { 65 | event_free(state->read_event); 66 | free(state); 67 | return NULL; 68 | } 69 | 70 | state->buffer_used = state->n_written = state->write_upto = 0; 71 | 72 | assert(state->write_event); 73 | return state; 74 | } 75 | 76 | void 77 | free_fd_state(struct fd_state *state) 78 | { 79 | event_free(state->read_event); 80 | event_free(state->write_event); 81 | free(state); 82 | } 83 | 84 | void 85 | do_read(evutil_socket_t fd, short events, void *arg) 86 | { 87 | struct fd_state *state = arg; 88 | char buf[1024]; 89 | int i; 90 | ssize_t result; 91 | while (1) { 92 | assert(state->write_event); 93 | result = recv(fd, buf, sizeof(buf), 0); 94 | if (result <= 0) 95 | break; 96 | 97 | for (i=0; i < result; ++i) { 98 | if (state->buffer_used < sizeof(state->buffer)) 99 | state->buffer[state->buffer_used++] = rot13_char(buf[i]); 100 | if (buf[i] == '\n') { 101 | assert(state->write_event); 102 | event_add(state->write_event, NULL); 103 | state->write_upto = state->buffer_used; 104 | } 105 | } 106 | } 107 | 108 | if (result == 0) { 109 | free_fd_state(state); 110 | } else if (result < 0) { 111 | if (errno == EAGAIN) // XXXX use evutil macro 112 | return; 113 | perror("recv"); 114 | free_fd_state(state); 115 | } 116 | } 117 | 118 | void 119 | do_write(evutil_socket_t fd, short events, void *arg) 120 | { 121 | struct fd_state *state = arg; 122 | 123 | while (state->n_written < state->write_upto) { 124 | ssize_t result = send(fd, state->buffer + state->n_written, 125 | state->write_upto - state->n_written, 0); 126 | if (result < 0) { 127 | if (errno == EAGAIN) // XXX use evutil macro 128 | return; 129 | free_fd_state(state); 130 | return; 131 | } 132 | assert(result != 0); 133 | 134 | state->n_written += result; 135 | } 136 | 137 | if (state->n_written == state->buffer_used) 138 | state->n_written = state->write_upto = state->buffer_used = 1; 139 | 140 | event_del(state->write_event); 141 | } 142 | 143 | void 144 | do_accept(evutil_socket_t listener, short event, void *arg) 145 | { 146 | struct event_base *base = arg; 147 | struct sockaddr_storage ss; 148 | socklen_t slen = sizeof(ss); 149 | int fd = accept(listener, (struct sockaddr*)&ss, &slen); 150 | if (fd < 0) { // XXXX eagain?? 151 | perror("accept"); 152 | } else if (fd > FD_SETSIZE) { 153 | close(fd); // XXX replace all closes with EVUTIL_CLOSESOCKET */ 154 | } else { 155 | struct fd_state *state; 156 | evutil_make_socket_nonblocking(fd); 157 | state = alloc_fd_state(base, fd); 158 | assert(state); /*XXX err*/ 159 | assert(state->write_event); 160 | event_add(state->read_event, NULL); 161 | } 162 | } 163 | 164 | void 165 | run(void) 166 | { 167 | evutil_socket_t listener; 168 | struct sockaddr_in sin; 169 | struct event_base *base; 170 | struct event *listener_event; 171 | 172 | base = event_base_new(); 173 | if (!base) 174 | return; /*XXXerr*/ 175 | 176 | sin.sin_family = AF_INET; 177 | sin.sin_addr.s_addr = 0; 178 | sin.sin_port = htons(8686); 179 | 180 | listener = socket(AF_INET, SOCK_STREAM, 0); 181 | evutil_make_socket_nonblocking(listener); 182 | 183 | #ifndef WIN32 184 | { 185 | int one = 1; 186 | setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); 187 | } 188 | #endif 189 | 190 | if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) < 0) { 191 | perror("bind"); 192 | return; 193 | } 194 | 195 | if (listen(listener, 16)<0) { 196 | perror("listen"); 197 | return; 198 | } 199 | 200 | listener_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base); 201 | /*XXX check it */ 202 | event_add(listener_event, NULL); 203 | 204 | event_base_dispatch(base); 205 | } 206 | 207 | int 208 | main(int c, char **v) 209 | { 210 | setvbuf(stdout, NULL, _IONBF, 0); 211 | 212 | run(); 213 | return 0; 214 | } 215 | -------------------------------------------------------------------------------- /event/note.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | socket(int domain, int type, int protocol); 5 | 6 | int 7 | bind(int socket, const struct sockaddr *address, socklen_t address_len); 8 | 9 | int 10 | listen(int socket, int backlog); 11 | 12 | int 13 | accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len); 14 | 15 | ssize_t 16 | recv(int socket, void *buffer, size_t length, int flags); 17 | 18 | ssize_t 19 | recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, 20 | socklen_t *restrict address_len); 21 | 22 | ssize_t 23 | recvmsg(int socket, struct msghdr *message, int flags); 24 | 25 | ssize_t 26 | send(int socket, const void *buffer, size_t length, int flags); 27 | 28 | ssize_t 29 | sendmsg(int socket, const struct msghdr *message, int flags); 30 | 31 | ssize_t 32 | sendto(int socket, const void *buffer, size_t length, int flags, const struct sockaddr *dest_addr, 33 | socklen_t dest_len); 34 | 35 | /***/ 36 | #include 37 | 38 | void 39 | FD_CLR(fd, fd_set *fdset); 40 | 41 | void 42 | FD_COPY(fd_set *fdset_orig, fd_set *fdset_copy); 43 | 44 | int 45 | FD_ISSET(fd, fd_set *fdset); 46 | 47 | void 48 | FD_SET(fd, fd_set *fdset); 49 | 50 | void 51 | FD_ZERO(fd_set *fdset); 52 | 53 | int 54 | select(int nfds, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict errorfds, 55 | struct timeval *restrict timeout); 56 | 57 | /***/ 58 | #include 59 | 60 | int 61 | fcntl(int fildes, int cmd, ...); 62 | 63 | /***/ 64 | #include 65 | 66 | uint32_t 67 | htonl(uint32_t hostlong); 68 | 69 | uint16_t 70 | htons(uint16_t hostshort); 71 | 72 | uint32_t 73 | ntohl(uint32_t netlong); 74 | 75 | uint16_t 76 | ntohs(uint16_t netshort); 77 | 78 | /***/ 79 | #include 80 | 81 | void 82 | setbuf(FILE *restrict stream, char *restrict buf); 83 | 84 | void 85 | setbuffer(FILE *stream, char *buf, int size); 86 | 87 | int 88 | setlinebuf(FILE *stream); 89 | 90 | int 91 | setvbuf(FILE *restrict stream, char *restrict buf, int type, size_t size); 92 | -------------------------------------------------------------------------------- /golang/random-pack/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "time" 7 | ) 8 | 9 | // 生成一个区间范围的随机数,左闭右开 10 | func generateRandom(min, max int) int { 11 | if min >= max { 12 | return max 13 | } 14 | 15 | rand.Seed(time.Now().UnixNano()) 16 | randNum := rand.Intn(max - min) 17 | randNum += min 18 | 19 | return randNum 20 | } 21 | 22 | func redPack(amount int, number int) (list []int) { 23 | for i := number; i > 0; i-- { 24 | money := generateRandom(1, amount-i) 25 | list = append(list, money) 26 | amount = amount - money 27 | } 28 | 29 | // 剩余的钱随机分给一个人 30 | if amount > 0 { 31 | list[generateRandom(0, number)] += amount 32 | } 33 | 34 | return 35 | } 36 | 37 | func main() { 38 | list := redPack(100, 10) 39 | fmt.Printf("list: %#v\n", list) 40 | 41 | sum := 0 42 | for _, money := range list { 43 | sum += money 44 | } 45 | fmt.Printf("sum: %d\n", sum) 46 | } 47 | -------------------------------------------------------------------------------- /other/combination.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: Jerry Yang(hy0kle@gmail.com) 4 | * @see: http://blog.csdn.net/w57w57w57/article/details/6657547 5 | * */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | typedef unsigned long long int u_long_int; 33 | 34 | u_long_int BIG1 = 1ULL; 35 | 36 | /** 37 | * 给定一个正整数N,求最小的、比N大的正整数M,使得M与N的二进制表示中有相同数目的1。 38 | * 39 | */ 40 | 41 | /** 42 | * 计算给定的整型数的二进制表示中 1 的个数 43 | * 具体算法 44 | * 应用 n &= (n - 1) 能将 n 的二进制表示中的最右边的 1 翻转为 0 45 | * 只需要不停地执行 n &= (n - 1), 直到 n 变成 0 为止 46 | * 那么翻转的次数就是原来的 n 的二进制表示中 1 的个数. 47 | * */ 48 | int count1_bits(unsigned int n) 49 | { 50 | int count = 0; 51 | 52 | while (n) 53 | { 54 | count++; 55 | n &= (n - 1); 56 | } 57 | 58 | return count; 59 | } 60 | 61 | /** 62 | * 高效算法 63 | * */ 64 | u_long_int next_n(u_long_int N) 65 | { 66 | u_long_int x = N & (-N); 67 | //printf("[%s] x = %llu\n", __func__, x); 68 | u_long_int t = N + x; 69 | //printf("[%s] t = %llu\n", __func__, t); 70 | u_long_int ans = t | ((N ^ t) / x) >> 2; 71 | //printf("[%s] ans = %llu\n", __func__, ans); 72 | 73 | return ans; 74 | } 75 | 76 | /** 77 | * 利用位操作求组合 78 | * 组合就是从N各对象中选取m个对象,问有多少种选法,并且要求输出每次的选法。 79 | * */ 80 | // 定义包含4个元素的集合 81 | char set[] ={'a','b','c','d','e','f','g','h','i', 'j', 'k'}; 82 | char *mset[] ={ 83 | "01", "02", "03", "04", "05", 84 | "06", "07", "08", "09", "10", 85 | "11", "12", "13", "14", "15", 86 | "16", "17", "18", "19", "20", 87 | "21", "22", "23", "24", "25", 88 | "26", "27", "28", "29", "30", 89 | "31", "32", "33" 90 | }; 91 | 92 | size_t mset_size = sizeof(mset) / sizeof(*mset); 93 | 94 | //根据C的二进制表示输出一个组合 95 | void print(char* set, int C) 96 | { 97 | int i = 0; 98 | int k; 99 | while ((k = 1 << i) <= C) 100 | { 101 | //循环测试每个bit是否为1 102 | if ((C & k) != 0) 103 | { 104 | printf("%c", set[i]); 105 | } 106 | 107 | i++; 108 | } 109 | } 110 | 111 | void mprint(char **mset, u_long_int C) 112 | { 113 | int i = 0; 114 | u_long_int k; 115 | //printf("%s %lld\n", __func__, C); 116 | while ((k = BIG1 << i) <= C) 117 | { 118 | //循环测试每个bit是否为1 119 | //if (i < (sizeof(mset) / sizeof(*mset)) && (C & k) != 0) 120 | if (i < mset_size && (C & k) != 0) 121 | { 122 | //printf("%s i = %d\n", __func__, i); 123 | //printf("%d \t", i); 124 | printf("%s\t", mset[i]); 125 | } 126 | 127 | i++; 128 | } 129 | } 130 | 131 | //求从set中前N个元素 中选择m个的组合 132 | void combination(char* set, int N, int m) 133 | { 134 | u_long_int C = (BIG1 << m ) - 1; 135 | while (C <= (( BIG1 << N) - (BIG1 << (N - m)))) 136 | { 137 | print(set, C); 138 | printf("\n"); 139 | 140 | C = next_n(C); 141 | } 142 | } 143 | 144 | void mcombination(char **mset, int N, int m) 145 | { 146 | u_long_int C = (BIG1 << m ) - BIG1; 147 | //printf("%s %lld\n", __func__, C); 148 | //printf("%d \n", (( 1 << N) - (1 << (N - m)))); 149 | 150 | u_long_int diff = ((BIG1 << N) - (BIG1 << (N - m))); 151 | //printf("[%s] diff = %lld \n", __func__, diff);exit(-1); 152 | 153 | //while (C <= ((bit << N) - (bit << (N - m)))) 154 | while (C <= diff) 155 | { 156 | mprint(mset, C); 157 | printf("\n"); 158 | 159 | C = next_n(C); 160 | //printf("%s %lld\n", __func__, C); 161 | } 162 | } 163 | 164 | 165 | int main(int argc, char *argv[]) 166 | { 167 | //u_long_int t = 1ULL; 168 | //t = 1ULL << 33; 169 | //printf("t = %llu \n", t); 170 | 171 | //t = 0ULL << 32; 172 | //printf("t = %llu \n", t); 173 | 174 | //printf("%ld\n", sizeof(t)); 175 | 176 | //combination(set, 8, 5); 177 | //printf("sizeof(mset) = %ld\n", sizeof(mset) / sizeof(*mset)); 178 | 179 | // 双色球 33 红球选 6 个 180 | mcombination(mset, 33, 6); 181 | 182 | 183 | //u_long_int ret = next_n(2113929216ULL); 184 | 185 | return 0; 186 | } 187 | 188 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 189 | 190 | -------------------------------------------------------------------------------- /other/db_model.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: Jerry Yang(hy0kle@gmail.com) 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define SQL_BUF_LEN 2048 31 | 32 | static const char *demo_fields[] = { 33 | "id", 34 | "nickname", 35 | "mobile", 36 | "email", 37 | "create_time", 38 | NULL, 39 | }; 40 | 41 | int main(int argc, char *argv[]) 42 | { 43 | size_t array_count = sizeof(demo_fields) / sizeof(char *); 44 | printf("array_count: %zu\n", array_count); 45 | 46 | char sql_buf[SQL_BUF_LEN]; 47 | char *p = sql_buf; 48 | p += snprintf(p, SQL_BUF_LEN, "SELECT "); 49 | size_t i = 0; 50 | 51 | const char **field = demo_fields; 52 | for (; *field; field++, i++) { 53 | printf("field: %s, index: %zd\n", *field, i); 54 | p += snprintf(p, SQL_BUF_LEN - (p - sql_buf), "%s%s", i > 0 ? ", " : "", *field); 55 | } 56 | p += snprintf(p, SQL_BUF_LEN - (p - sql_buf), " FROM demo"); 57 | printf("SQL: %s\n", sql_buf); 58 | 59 | return 0; 60 | } 61 | 62 | /* vim:set ft=c ts=4 sw=4 et fdm=marker: */ 63 | 64 | -------------------------------------------------------------------------------- /other/errno-msg.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: Jerry Yang(hy0kle@gmail.com) 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | int error_number; 13 | 14 | for (error_number = EPERM; error_number <= ELAST; error_number++) { 15 | printf("errno: %d\tstrerror: %s\n", error_number, strerror(error_number)); 16 | } 17 | 18 | return 0; 19 | } 20 | 21 | /* vim:set ft=c ts=4 sw=4 et fdm=marker: */ 22 | 23 | -------------------------------------------------------------------------------- /other/func_args.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: hy0kle@gmail.com 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | /** 31 | * 一个例子充分理解 C 语言的函数调用时形参与实参的关系, 32 | * 以及对于传值和传引用的疑惑. 33 | * 34 | * 一个例子,貌似是面试题. 35 | * 我第一次看到,相当然的认为在调用 test() 以后, 36 | * t 变成了一个野指针,但实际运行后发现, test() 调用中并没能改为实参 t 本身的值. 37 | * 充分说明了, c 语言的函数调用只有传值,没有传引用的说法. 38 | * 所谓的传引用,实际是传了一个指针进去,而指针变量本身也个内存的容器, 39 | * 它里面的值是另外一个内存容器(即变量)的地址值, 40 | * 在函数体中,通过取一级 * 运算,可以使用在函数中操作函数外的内存空间; 41 | * 但是,由于函数调用时会为每个参数在栈上开辟空间,换句话说, 42 | * 每个实际参数在进入函数调用的时候,都会使用一份拷贝(通常大的数组会传地址值进去,否则需要大内存来拷贝一份大数组), 43 | * 函数调用结束后,并不能改变实参本身的值, 44 | * 因为作用域,函数体内的局部变量在函数执行完后,全部自动销毁了, 45 | * 不能影响实参. 46 | * 47 | * 结合本例子,实参 t 在进入 test(int *p) 时,与形参 p 对应, 48 | * 系统会在栈为开辟内存空间,将 t 的内容拷贝到 p 中, 49 | * p 是 t 在函数栈空间上的一份拷贝, 50 | * 所以在在试图改变 p 的值,函数体外的 t 不会受到影响, 51 | * 因为 p = &tmp; 只是修改了栈上的复制版本. 52 | * 函数调用结束后,栈上的变量全部释放, t 的值保持原样. 53 | * 54 | * 有一些术语,想给别人解释的时候老说不清,现理清了,记一下 55 | * *p 在 = 右边表示取 p 指向的内存空间中的值; 56 | * *p 在 = 左边表示给 p 指向的内存赋值. 57 | * */ 58 | 59 | void test(int *p) 60 | { 61 | int tmp = 555; 62 | 63 | p = &tmp; 64 | return; 65 | } 66 | 67 | int main(int argc, char *argv[]) 68 | { 69 | int a = 123; 70 | int *t = &a; 71 | 72 | test(t); 73 | 74 | printf(" a = %d\n", a); 75 | printf("*t = %d\n", *t); 76 | 77 | return 0; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /other/md5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * gcc md5.c -o md5 -lcrypto 7 | * */ 8 | 9 | #define STR_BUF_LEN 2048 10 | 11 | int main( int argc, char *argv[] ) 12 | { 13 | unsigned char data[STR_BUF_LEN] = "123abctest"; 14 | unsigned char md[16]; 15 | int i; 16 | char tmp[3] = {0}; 17 | char buf[33]= {0}; 18 | 19 | if (argc > 1 && argv[1][0]) 20 | { 21 | snprintf((char *)data, STR_BUF_LEN, "%s", argv[1]); 22 | } 23 | 24 | MD5(data, strlen((char *)data), md); 25 | for (i = 0; i < 16; i++){ 26 | sprintf(tmp, "%2.2x", md[i]); 27 | strcat(buf, tmp); 28 | } 29 | printf("md5(\"%s\") = %s\n", data, buf); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /other/random_hex.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: Jerry Yang(hy0kle@gmail.com) 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define BUF_LEN 64 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | char out_buf[BUF_LEN + 1] = {0}; 35 | printf("sizeof(out_buf): %u\n", sizeof(out_buf)); 36 | 37 | FILE *fp = fopen("/dev/urandom", "r"); 38 | char *charset = "0123456789abcdef"; 39 | unsigned int j; 40 | 41 | if (fp == NULL || fread(out_buf, BUF_LEN, 1,fp) == 0) { 42 | printf("Can not open file: /dev/urandom.\n"); 43 | exit(0); 44 | } 45 | 46 | for (j = 0; j < BUF_LEN; j++) 47 | out_buf[j] = charset[out_buf[j] & 0x0F]; 48 | if (fp) fclose(fp); 49 | 50 | printf("random_hex: %s\n", out_buf); 51 | 52 | return 0; 53 | } 54 | 55 | /* vim:set ft=c ts=4 sw=4 et fdm=marker: */ 56 | 57 | -------------------------------------------------------------------------------- /other/shift_bit.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: Jerry Yang(hy0kle@gmail.com) 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | int main(int argc, char *argv[]) 32 | { 33 | int i; 34 | 35 | for (i = 0; i < 64; i++) 36 | { 37 | printf("1 << %d\t= %lu\n", i, (unsigned long int)(1UL << i)); 38 | } 39 | 40 | 41 | printf("1 | 2 = %d\n", 1 | 2); 42 | printf("1 | 2 | 4 = %d\n", 1 | 2 | 4); 43 | return 0; 44 | } 45 | 46 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 47 | 48 | -------------------------------------------------------------------------------- /other/strftime.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: Jerry Yang(hy0kle@gmail.com) 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #define BUFLEN 256 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | time_t t = time(NULL); 35 | char buf[BUFLEN]; 36 | strftime(buf, BUFLEN, "%Y-%m-%d %H:%M:%S", localtime(&t)); //format date and time. 37 | printf("Date-Tims: %s\n", buf); 38 | 39 | return 0; 40 | } 41 | 42 | /* vim:set ft=c ts=4 sw=4 et fdm=marker: */ 43 | 44 | -------------------------------------------------------------------------------- /other/struct.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: hy0kle@gmail.com 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | typedef struct _point_t 32 | { 33 | int x; 34 | int y; 35 | } point_t; 36 | 37 | void dump(point_t p) 38 | { 39 | printf("point.x = %d, point.y = %d\n", p.x, p.y); 40 | } 41 | 42 | inline point_t point_make(int x, int y) 43 | { 44 | point_t p; 45 | 46 | p.x = x; 47 | p.y = y; 48 | 49 | return p; 50 | } 51 | 52 | int main(int argc, char *argv[]) 53 | { 54 | point_t p; /** 开辟内存 */ 55 | p.x = 1; 56 | p.y = 22; 57 | 58 | /** 开辟一块新内存 */ 59 | point_t t = point_make(5, 99); 60 | 61 | dump(t); 62 | dump(p); 63 | 64 | /** 65 | * 将 &t 指向的内存中内容拷贝到 &p 指向的内存中 66 | * 此时 t 和 p 拥有同样的内容 67 | * p 原来的内容被覆盖 68 | * */ 69 | p = t; 70 | dump(p); 71 | 72 | return 0; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /other/typedef-enum.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: hy0kle@gmail.com 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | typedef enum 32 | { 33 | GameSceneLayerTagGame = 1, 34 | GameSceneLayerTagInput, 35 | 36 | } GameSceneLayerTags; 37 | 38 | typedef enum 39 | { 40 | GameSceneNodeTagBullet = 1, 41 | GameSceneNodeTagBulletSpriteBatch, 42 | GameSceneNodeTagBulletCache, 43 | GameSceneNodeTagShip, 44 | 45 | } GameSceneNodeTags; 46 | 47 | int main(int argc, char *argv[]) 48 | { 49 | printf("GameSceneNodeTags->GameSceneNodeTagBulletSpriteBatch: %d\n", GameSceneNodeTagBulletSpriteBatch); 50 | 51 | GameSceneNodeTags node_tag = GameSceneNodeTagShip; 52 | printf("node_tag: %d\n", node_tag); 53 | 54 | return 0; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /php/Flexihash.php: -------------------------------------------------------------------------------- 1 | target, ... } 68 | * @comment 位置对应节点,用于lookup中根据位置确定要访问的节点 69 | */ 70 | private $_positionToTarget = array(); 71 | 72 | /** 73 | * Internal map of targets to lists of positions that target is hashed to. 74 | * @var array { target => [ position, position, ... ], ... } 75 | * @comment 节点对应位置,用于删除节点 76 | */ 77 | private $_targetToPositions = array(); 78 | 79 | /** 80 | * Whether the internal map of positions to targets is already sorted. 81 | * @var boolean 82 | * @comment 是否已排序 83 | */ 84 | private $_positionToTargetSorted = false; 85 | 86 | /** 87 | * Constructor 88 | * @param object $hasher Flexihash_Hasher 89 | * @param int $replicas Amount of positions to hash each target to. 90 | * @comment 构造函数,确定要使用的hash方法和需拟节点数,虚拟节点数越多,分布越均匀,但程序的分布式运算越慢 91 | */ 92 | public function __construct(Flexihash_Hasher $hasher = null, $replicas = null) 93 | { 94 | $this->_hasher = $hasher ? $hasher : new Flexihash_Crc32Hasher(); 95 | if (!empty($replicas)) $this->_replicas = $replicas; 96 | } 97 | 98 | /** 99 | * Add a target. 100 | * @param string $target 101 | * @chainable 102 | * @comment 添加节点,根据虚拟节点数,将节点分布到多个虚拟位置上 103 | */ 104 | public function addTarget($target) 105 | { 106 | if (isset($this->_targetToPositions[$target])) 107 | { 108 | throw new Flexihash_Exception("Target '$target' already exists."); 109 | } 110 | 111 | $this->_targetToPositions[$target] = array(); 112 | 113 | // hash the target into multiple positions 114 | for ($i = 0; $i < $this->_replicas; $i++) 115 | { 116 | $position = $this->_hasher->hash($target . $i); 117 | $this->_positionToTarget[$position] = $target; // lookup 118 | $this->_targetToPositions[$target][] = $position; // target removal 119 | } 120 | 121 | $this->_positionToTargetSorted = false; 122 | $this->_targetCount++; 123 | 124 | return $this; 125 | } 126 | 127 | /** 128 | * Add a list of targets. 129 | * @param array $targets 130 | * @chainable 131 | */ 132 | public function addTargets($targets) 133 | { 134 | foreach ($targets as $target) 135 | { 136 | $this->addTarget($target); 137 | } 138 | 139 | return $this; 140 | } 141 | 142 | /** 143 | * Remove a target. 144 | * @param string $target 145 | * @chainable 146 | */ 147 | public function removeTarget($target) 148 | { 149 | if (!isset($this->_targetToPositions[$target])) 150 | { 151 | throw new Flexihash_Exception("Target '$target' does not exist."); 152 | } 153 | 154 | foreach ($this->_targetToPositions[$target] as $position) 155 | { 156 | unset($this->_positionToTarget[$position]); 157 | } 158 | 159 | unset($this->_targetToPositions[$target]); 160 | 161 | $this->_targetCount--; 162 | 163 | return $this; 164 | } 165 | 166 | /** 167 | * A list of all potential targets 168 | * @return array 169 | */ 170 | public function getAllTargets() 171 | { 172 | return array_keys($this->_targetToPositions); 173 | } 174 | 175 | /** 176 | * Looks up the target for the given resource. 177 | * @param string $resource 178 | * @return string 179 | */ 180 | public function lookup($resource) 181 | { 182 | $targets = $this->lookupList($resource, 1); 183 | if (empty($targets)) throw new Flexihash_Exception('No targets exist'); 184 | return $targets[0]; 185 | } 186 | 187 | /** 188 | * Get a list of targets for the resource, in order of precedence. 189 | * Up to $requestedCount targets are returned, less if there are fewer in total. 190 | * 191 | * @param string $resource 192 | * @param int $requestedCount The length of the list to return 193 | * @return array List of targets 194 | * @comment 查找当前的资源对应的节点, 195 | * 节点为空则返回空,节点只有一个则返回该节点, 196 | * 对当前资源进行hash,对所有的位置进行排序,在有序的位置列上寻找当前资源的位置 197 | * 当全部没有找到的时候,将资源的位置确定为有序位置的第一个(形成一个环) 198 | * 返回所找到的节点 199 | */ 200 | public function lookupList($resource, $requestedCount) 201 | { 202 | if (!$requestedCount) 203 | throw new Flexihash_Exception('Invalid count requested'); 204 | 205 | // handle no targets 206 | if (empty($this->_positionToTarget)) 207 | return array(); 208 | 209 | // optimize single target 210 | if ($this->_targetCount == 1) 211 | return array_unique(array_values($this->_positionToTarget)); 212 | 213 | // hash resource to a position 214 | $resourcePosition = $this->_hasher->hash($resource); 215 | 216 | $results = array(); 217 | $collect = false; 218 | 219 | $this->_sortPositionTargets(); 220 | 221 | // search values above the resourcePosition 222 | foreach ($this->_positionToTarget as $key => $value) 223 | { 224 | // start collecting targets after passing resource position 225 | if (!$collect && $key > $resourcePosition) 226 | { 227 | $collect = true; 228 | } 229 | 230 | // only collect the first instance of any target 231 | if ($collect && !in_array($value, $results)) 232 | { 233 | $results []= $value; 234 | } 235 | 236 | // return when enough results, or list exhausted 237 | if (count($results) == $requestedCount || count($results) == $this->_targetCount) 238 | { 239 | return $results; 240 | } 241 | } 242 | 243 | // loop to start - search values below the resourcePosition 244 | foreach ($this->_positionToTarget as $key => $value) 245 | { 246 | if (!in_array($value, $results)) 247 | { 248 | $results []= $value; 249 | } 250 | 251 | // return when enough results, or list exhausted 252 | if (count($results) == $requestedCount || count($results) == $this->_targetCount) 253 | { 254 | return $results; 255 | } 256 | } 257 | 258 | // return results after iterating through both "parts" 259 | return $results; 260 | } 261 | 262 | public function __toString() 263 | { 264 | return sprintf( 265 | '%s{targets:[%s]}', 266 | get_class($this), 267 | implode(',', $this->getAllTargets()) 268 | ); 269 | } 270 | 271 | public function debug() 272 | { 273 | $p2t = $this->_positionToTarget; 274 | ksort($p2t, SORT_REGULAR | SORT_NUMERIC); 275 | $output = sprintf("%s\n", str_repeat('-', 80)); 276 | $output .= sprintf("positionToTarget: %s\ntargetToPositions: %s", print_r($p2t, true), print_r($this->_targetToPositions, true)); 277 | $output .= sprintf("%s\n", str_repeat('=', 80)); 278 | 279 | return $output; 280 | } 281 | 282 | // ---------------------------------------- 283 | // private methods 284 | 285 | /** 286 | * Sorts the internal mapping (positions to targets) by position 287 | */ 288 | private function _sortPositionTargets() 289 | { 290 | // sort by key (position) if not already 291 | if (!$this->_positionToTargetSorted) 292 | { 293 | ksort($this->_positionToTarget, SORT_REGULAR); 294 | //ksort($this->_positionToTarget, SORT_REGULAR | SORT_NUMERIC); 295 | $this->_positionToTargetSorted = true; 296 | } 297 | } 298 | 299 | } 300 | 301 | 302 | /** 303 | * Hashes given values into a sortable fixed size address space. 304 | * 305 | * @author Paul Annesley 306 | * @package Flexihash 307 | * @licence http://www.opensource.org/licenses/mit-license.php 308 | */ 309 | interface Flexihash_Hasher 310 | { 311 | 312 | /** 313 | * Hashes the given string into a 32bit address space. 314 | * 315 | * Note that the output may be more than 32bits of raw data, for example 316 | * hexidecimal characters representing a 32bit value. 317 | * 318 | * The data must have 0xFFFFFFFF possible values, and be sortable by 319 | * PHP sort functions using SORT_REGULAR. 320 | * 321 | * @param string 322 | * @return mixed A sortable format with 0xFFFFFFFF possible values 323 | */ 324 | public function hash($string); 325 | 326 | } 327 | 328 | 329 | /** 330 | * Uses CRC32 to hash a value into a signed 32bit int address space. 331 | * Under 32bit PHP this (safely) overflows into negatives ints. 332 | * 333 | * @author Paul Annesley 334 | * @package Flexihash 335 | * @licence http://www.opensource.org/licenses/mit-license.php 336 | */ 337 | class Flexihash_Crc32Hasher 338 | implements Flexihash_Hasher 339 | { 340 | 341 | /* (non-phpdoc) 342 | * @see Flexihash_Hasher::hash() 343 | */ 344 | public function hash($string) 345 | { 346 | return crc32($string); 347 | } 348 | 349 | } 350 | 351 | 352 | /** 353 | * Uses CRC32 to hash a value into a 32bit binary string data address space. 354 | * 355 | * @author Paul Annesley 356 | * @package Flexihash 357 | * @licence http://www.opensource.org/licenses/mit-license.php 358 | */ 359 | class Flexihash_Md5Hasher 360 | implements Flexihash_Hasher 361 | { 362 | 363 | /* (non-phpdoc) 364 | * @see Flexihash_Hasher::hash() 365 | */ 366 | public function hash($string) 367 | { 368 | return substr(md5($string), 0, 8); // 8 hexits = 32bit 369 | 370 | // 4 bytes of binary md5 data could also be used, but 371 | // performance seems to be the same. 372 | } 373 | 374 | } 375 | 376 | 377 | /** 378 | * An exception thrown by Flexihash. 379 | * 380 | * @author Paul Annesley 381 | * @package Flexihash 382 | * @licence http://www.opensource.org/licenses/mit-license.php 383 | */ 384 | class Flexihash_Exception extends Exception 385 | { 386 | } 387 | 388 | /** test code */ 389 | $fhObj = new Flexihash(null, 3); 390 | $nodes_config = array( 391 | 'db.mysql.001', 392 | 'db.mysql.002', 393 | 'db.mysql.003', 394 | ); 395 | $data_sets = array( 396 | '128 1024 2048', 397 | 'just as abc', 398 | 'php java go', 399 | 'libevent ES', 400 | 'memcache redis', 401 | 'nginx lighttpd', 402 | 'linux vs bsd', 403 | 'MySQL PgSQL', 404 | ); 405 | 406 | $fhObj->addTargets($nodes_config); 407 | print_r($fhObj->debug()); 408 | lookup($fhObj, $data_sets); 409 | 410 | $fhObj->addTarget('db.mysql.007'); 411 | print_r($fhObj->debug()); 412 | lookup($fhObj, $data_sets); 413 | 414 | function lookup($fhObj, $data_sets) { 415 | echo sprintf("%s\n", str_repeat('#', 80)); 416 | foreach ($data_sets as $dt) { 417 | $slot = $fhObj->lookup($dt); 418 | echo sprintf("%s\t\t%s\n", $dt, $slot); 419 | } 420 | } 421 | -------------------------------------------------------------------------------- /php/inter.php: -------------------------------------------------------------------------------- 1 | $cnt_b) { 14 | $f_loop = $b; 15 | $s_loop = $a; 16 | $f_cnt = $cnt_b; 17 | $s_cnt = $cnt_a; 18 | } else { 19 | $f_loop = $a; 20 | $s_loop = $b; 21 | $f_cnt = $cnt_a; 22 | $s_cnt = $cnt_b; 23 | } 24 | 25 | $inter_set = array(); 26 | 27 | $i = 0; 28 | $k = 0; 29 | for (/***/; $i < $f_cnt; /***/) { 30 | for (/***/; $k < $s_cnt && $i < $f_cnt; /***/) { 31 | /** 如果相等,放入交集容器,同时将两个数组比较元素向前移动1位 */ 32 | if ($f_loop[$i] == $s_loop[$k]) { 33 | $inter_set[] = $s_loop[$k]; 34 | $i++; 35 | $k++; 36 | } elseif ($f_loop[$i] > $s_loop[$k]) { 37 | /** 如果外层元素大,将内层元素向前移动1位 */ 38 | $k++; 39 | } elseif ($f_loop[$i] < $s_loop[$k]) { 40 | /** 如果内层元素大,将外层元素向前移动1位 */ 41 | $i++; 42 | } 43 | } 44 | } 45 | 46 | return $inter_set; 47 | } 48 | 49 | function union($a, $b) { 50 | $cnt_a = count($a); 51 | $cnt_b = count($b); 52 | 53 | $total = $cnt_a + $cnt_b; 54 | 55 | if ($a[0] > $b[0]) { 56 | $f_loop = $b; 57 | $s_loop = $a; 58 | $f_cnt = $cnt_b; 59 | $s_cnt = $cnt_a; 60 | } else { 61 | $f_loop = $a; 62 | $s_loop = $b; 63 | $f_cnt = $cnt_a; 64 | $s_cnt = $cnt_b; 65 | } 66 | 67 | //print_r($f_loop); 68 | //print_r($s_loop); 69 | //print_r($f_cnt); 70 | //print_r($s_cnt); 71 | //exit; 72 | 73 | $union_set[] = $f_loop[0]; 74 | 75 | $i = 1; // 首元素小的数组索引 76 | $k = 0; 77 | 78 | for ($t = 0; $t < $total; /***/) { 79 | /** 其中长数组多出来的元素,直接追加 */ 80 | if ($i >= $f_cnt && $k < $s_cnt) { 81 | for (/***/; $k < $s_cnt; $k++) { 82 | $union_set[] = $s_loop[$k]; 83 | } 84 | break; 85 | } 86 | 87 | if ($k >= $s_cnt && $i < $f_cnt) { 88 | for (/***/; $i < $f_cnt; $i++) { 89 | $union_set[] = $f_loop[$i]; 90 | } 91 | break; 92 | } 93 | 94 | /** 一次比较,将两个元素同时压入 */ 95 | if ($f_loop[$i] < $s_loop[$k]) { 96 | $union_set[] = $f_loop[$i++]; 97 | $union_set[] = $s_loop[$k++]; 98 | } else { 99 | $union_set[] = $s_loop[$k++]; 100 | $union_set[] = $f_loop[$i++]; 101 | } 102 | $t += 2; 103 | } 104 | 105 | return $union_set; 106 | } 107 | 108 | $a = [1, 2, 34, 56, 78, 90, 110, 120, 256, 1024]; 109 | $b = [2, 56, 67, 89, 90, 128]; 110 | 111 | echo '$a = '; 112 | print_r($a); 113 | echo '$b = '; 114 | print_r($b); 115 | 116 | $inter_set = inter($a, $b); 117 | echo '$inter_set = '; 118 | print_r($inter_set); 119 | 120 | $union_set = union($a, $b); 121 | echo '$union_set = '; 122 | print_r($union_set); 123 | /* vim:set ts=4 sw=4 et fdm=marker: */ 124 | 125 | -------------------------------------------------------------------------------- /php/monkey.php: -------------------------------------------------------------------------------- 1 | 0); 10 | assert($cond > 0); 11 | 12 | $circle = array(); 13 | for ($i = 0; $i < $total; $i++) { 14 | $circle[] = $i + 1; 15 | } 16 | 17 | $number = 0; 18 | while (1) { 19 | if (count($circle) == 1) { 20 | break; 21 | } 22 | 23 | foreach ($circle as $index => $v) { 24 | $number++; 25 | if (0 == $number % $cond) { 26 | unset($circle[$index]); 27 | } 28 | } 29 | } 30 | 31 | return array_pop($circle); 32 | } 33 | 34 | echo 'The monkey King is: ', out_of_game(10, 3), PHP_EOL; 35 | 36 | // 数学法 37 | // 编号从0开始,如果编号要从1开始,结果要加1 38 | function josephus($n, $k) { 39 | $s = 0; 40 | for ($i = 2; $i <= $n; $i++) { 41 | $s = ($s + $k) % $i; 42 | } 43 | 44 | return $s; 45 | } 46 | echo 'The monkey King is(begin with 0): ', josephus(10, 3), PHP_EOL; 47 | /* vim:set ts=4 sw=4 et fdm=marker: */ 48 | 49 | -------------------------------------------------------------------------------- /php/qsort.php: -------------------------------------------------------------------------------- 1 | $tmp) { 19 | $right_arr[] = $arr[$i]; 20 | } else { 21 | $left_arr[] = $arr[$i]; 22 | } 23 | } 24 | 25 | return array_merge(qsort($left_arr), array($tmp), qsort($right_arr)); 26 | } 27 | 28 | $input = [9, 12, 3, 45, 89, 1, 234, 127, 1024]; 29 | $output = qsort($input); 30 | print_r($output); 31 | /* vim:set ts=4 sw=4 et fdm=marker: */ 32 | 33 | -------------------------------------------------------------------------------- /php/send-red-pack.php: -------------------------------------------------------------------------------- 1 | 1); 17 | assert($number > 0); 18 | 19 | $conf = array(); 20 | $cntr = array(); 21 | 22 | $total = 0; 23 | for ($i = 0; $total < $number - 1; $i++) { 24 | $rand = mt_rand(1, $money); 25 | if ($rand == $money || isset($cntr[$rand])) { 26 | continue; 27 | } else { 28 | $cntr[$rand] = 1; 29 | $total++; 30 | } 31 | } 32 | $cntr[$money] = 1; 33 | ksort($cntr, SORT_NUMERIC); 34 | //print_r($cntr); 35 | $iter = 0; 36 | foreach ($cntr as $rd => $val) { 37 | $conf[] = $rd - $iter; 38 | $iter = $rd; 39 | } 40 | 41 | return $conf; 42 | } 43 | 44 | $start_time = microtime(true); 45 | $conf = generate_conf($money, $number); 46 | print_r($conf); 47 | echo 'sum($conf) = ', array_sum($conf), PHP_EOL; 48 | $end_time = microtime(true); 49 | echo 'generate_conf() spend time: ', ($end_time - $start_time) , PHP_EOL; 50 | 51 | function red_pack($money, $number) { 52 | $conf = array(); 53 | for ($i = 0; $i < $number; $i++) { 54 | $conf[] = 1; 55 | } 56 | 57 | $money -= $number; 58 | 59 | while ($money > 0) { 60 | $rand_money = mt_rand(1, $money); 61 | $rand_key = mt_rand(0, $number - 1); 62 | 63 | $conf[$rand_key] += $rand_money; 64 | $money -= $rand_money; 65 | } 66 | 67 | return $conf; 68 | } 69 | 70 | $start_time = microtime(true); 71 | $conf = red_pack($money, $number); 72 | print_r($conf); 73 | echo 'sum($conf) = ', array_sum($conf), PHP_EOL; 74 | $end_time = microtime(true); 75 | echo 'red_pack() spend time: ', ($end_time - $start_time) , PHP_EOL; 76 | /* vim:set ts=4 sw=4 et fdm=marker: */ 77 | 78 | -------------------------------------------------------------------------------- /tree/Makefile: -------------------------------------------------------------------------------- 1 | GCC = gcc 2 | GCCFLAGS = -g -finline-functions -Wall -Winline -pipe 3 | 4 | PROJECT_1 = bitree 5 | PROJECT_2 = binary-tree 6 | PROJECT_3 = search-tree 7 | 8 | OBJS_1 = bitree.o 9 | OBJS_2 = binary-tree.o 10 | OBJS_3 = search-tree.o 11 | 12 | all : $(PROJECT_1) $(PROJECT_2) $(PROJECT_3) 13 | @echo "Start compile all" 14 | rm -f *.o 15 | @echo "complete" 16 | 17 | $(PROJECT_1): $(OBJS_1) 18 | @echo "start compile $(PROJECT_1)" 19 | $(GCC) -g -o $@ $^ 20 | 21 | $(PROJECT_2): $(OBJS_2) 22 | @echo "start compile $(PROJECT_2)" 23 | $(GCC) -g -o $@ $^ 24 | 25 | $(PROJECT_3): $(OBJS_3) 26 | @echo "start compile $(PROJECT_3)" 27 | $(GCC) -g -o $@ $^ 28 | 29 | %.o : %.c 30 | $(GCC) $(GCCFLAGS) -c $< -o $@ 31 | 32 | .PHONY: clean 33 | clean: 34 | rm -rf $(PROJECT_1) $(PROJECT_2) $(OBJS_1) $(OBJS_2) 35 | -------------------------------------------------------------------------------- /tree/binary-tree.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | /** 3 | * @describe: 4 | * @author: hy0kle@gmail.com 5 | * */ 6 | typedef struct _smarty_str_t 7 | { 8 | unsigned int count; /** 重复出现的次数 */ 9 | size_t len; 10 | char *data; 11 | } smarty_str_t; 12 | 13 | typedef struct _binary_tree_t 14 | { 15 | smarty_str_t node_data; 16 | struct _binary_tree_t *left; 17 | struct _binary_tree_t *right; 18 | } binary_tree_t; 19 | 20 | binary_tree_t *root = NULL; 21 | 22 | binary_tree_t *create_new_node(const char *data) 23 | { 24 | assert(NULL != data); 25 | //printf("create_new_node data %s\n", data); 26 | 27 | size_t size = sizeof(binary_tree_t); 28 | size_t len = strlen(data); 29 | 30 | binary_tree_t *node = (binary_tree_t *)malloc(size); 31 | if (NULL == node) 32 | { 33 | fprintf(stderr, "Can NOT malloc() for node, need size:%lu \n", size); 34 | exit(1); 35 | } 36 | 37 | size = sizeof(char) * len + 1; 38 | node->node_data.data = (char *)malloc(size); 39 | if (NULL == node->node_data.data) 40 | { 41 | fprintf(stderr, "Can NOT malloc() for node->node_data.data, need size:%lu \n", size); 42 | exit(1); 43 | } 44 | node->node_data.len = len; 45 | node->node_data.count = 1; 46 | snprintf(node->node_data.data, size, "%s", data); 47 | 48 | node->left = NULL; 49 | node->right = NULL; 50 | 51 | return node; 52 | } 53 | 54 | binary_tree_t *insert(binary_tree_t **tree, const char *src_data) 55 | { 56 | assert(NULL != src_data); 57 | 58 | if (NULL == *tree) 59 | { 60 | *tree = create_new_node(src_data); 61 | //printf("tree->node_data.data: %s\n", (*tree)->node_data.data); 62 | return *tree; 63 | } 64 | 65 | size_t src_len = strlen(src_data); 66 | int n = (*tree)->node_data.len > src_len ? src_len : (*tree)->node_data.len; 67 | int cmp_ret = strncmp(src_data, (*tree)->node_data.data, n); 68 | //printf("tree->node_data.data: %s\n", (*tree)->node_data.data); 69 | 70 | /** fix cmp result */ 71 | if (0 == cmp_ret && src_len != (*tree)->node_data.len) 72 | { 73 | cmp_ret = src_len - (*tree)->node_data.len; 74 | } 75 | 76 | if (0 == cmp_ret) 77 | { 78 | (*tree)->node_data.count++; 79 | return *tree; 80 | } 81 | else if (cmp_ret < 0) 82 | { 83 | return insert(&((*tree)->left), src_data); 84 | } 85 | else 86 | { 87 | return insert(&((*tree)->right), src_data); 88 | } 89 | } 90 | 91 | void print_node(const binary_tree_t *node) 92 | { 93 | assert(NULL != node); 94 | 95 | printf("|%sdata%s: %s%s%s\t", BLUE, NORMAL, MAGENTA, node->node_data.data, NORMAL); 96 | printf("| %scount%s: %s%d%s\t |\n", 97 | BLUE, NORMAL, CYAN, node->node_data.count, NORMAL); 98 | 99 | return; 100 | } 101 | 102 | /** 103 | * l: left 104 | * d: root 105 | * r: right 106 | * */ 107 | void ldr_print(const binary_tree_t *tree) 108 | { 109 | if (NULL != tree) 110 | { 111 | ldr_print(tree->left); 112 | print_node(tree); 113 | ldr_print(tree->right); 114 | } 115 | } 116 | 117 | void rdl_print(const binary_tree_t *tree) 118 | { 119 | if (NULL != tree) 120 | { 121 | rdl_print(tree->right); 122 | print_node(tree); 123 | rdl_print(tree->left); 124 | } 125 | } 126 | 127 | void dlr_print(const binary_tree_t *tree) 128 | { 129 | if (NULL != tree) 130 | { 131 | print_node(tree); 132 | dlr_print(tree->left); 133 | dlr_print(tree->right); 134 | } 135 | } 136 | 137 | const binary_tree_t *find(const binary_tree_t *tree, const char *src_data) 138 | { 139 | if (NULL == tree) 140 | { 141 | return NULL; 142 | } 143 | 144 | size_t src_len = strlen(src_data); 145 | int n = tree->node_data.len > src_len ? src_len : tree->node_data.len; 146 | int cmp_ret = strncmp(src_data, tree->node_data.data, n); 147 | 148 | /** fix cmp result */ 149 | if (0 == cmp_ret && src_len != tree->node_data.len) 150 | { 151 | cmp_ret = src_len - tree->node_data.len; 152 | } 153 | 154 | if (0 == cmp_ret) 155 | { 156 | return tree; 157 | } 158 | else if (cmp_ret < 0) 159 | { 160 | return find(tree->left, src_data); 161 | } 162 | else 163 | { 164 | return find(tree->right, src_data); 165 | } 166 | } 167 | 168 | static char *test_data[] = { 169 | "5", 170 | "7", 171 | "abc", 172 | "test", 173 | "t", 174 | "abs", 175 | "123", 176 | "test", 177 | "1", 178 | "9", 179 | NULL, 180 | }; 181 | 182 | int main(int argc, char *argv[]) 183 | { 184 | int i = 0; 185 | const binary_tree_t *tmp_node = NULL; 186 | root = create_new_node("hy"); 187 | 188 | for (; test_data[i]; i++) 189 | { 190 | printf("input data: %s\n", test_data[i]); 191 | insert(&root, test_data[i]); 192 | } 193 | printf("\n"); 194 | 195 | printf("---%sleft root right%s---\n", RED, NORMAL); 196 | ldr_print(root); 197 | printf("---"); 198 | 199 | printf("\n\n"); 200 | printf("---%sright root left%s---\n", YELLOW, NORMAL); 201 | rdl_print(root); 202 | printf("---"); 203 | 204 | printf("\n\n"); 205 | printf("---%sroot left right%s---\n", GREEN, NORMAL); 206 | dlr_print(root); 207 | printf("---\n\n"); 208 | 209 | static char *f_data[] = { 210 | "test", 211 | "hy0l", 212 | "gmail", 213 | "9", 214 | NULL, 215 | }; 216 | printf("--- %sFind logic%s ---\n", MAGENTA, NORMAL); 217 | for (i = 0; f_data[i]; i++) 218 | { 219 | if (NULL == (tmp_node = find(root, f_data[i]))) 220 | { 221 | printf("Can NOT find %s%s%s from tree.\n", RED, f_data[i], NORMAL); 222 | } 223 | else { 224 | printf("Find -> %s%s%s from tree :\n ", RED, f_data[i], NORMAL); 225 | print_node(tmp_node); 226 | } 227 | } 228 | 229 | return 0; 230 | } 231 | 232 | -------------------------------------------------------------------------------- /tree/bitree.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: hy0kle@gmail.com 4 | * */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "bitree.h" 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | 36 | return 0; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /tree/bitree.h: -------------------------------------------------------------------------------- 1 | #ifndef _BITREE_H 2 | #define _BITREE_H 3 | 4 | #include 5 | 6 | /** define structure for binary nodes */ 7 | typedef struct _smt_str_t 8 | { 9 | u_char *str; 10 | size_t len; 11 | unsigned int count; 12 | } smt_str_t; 13 | 14 | typedef struct _bitree_node_t 15 | { 16 | void *data; 17 | struct _bitree_node_t *left; 18 | struct _bitree_node_t *right; 19 | } bitree_node_t; 20 | 21 | /** define a structure for binary trees. */ 22 | typedef struct _bitree_t 23 | { 24 | int size; 25 | int (*compare)(const void *key1, const void *key2); 26 | void (*destroy)(void *data); 27 | bitree_node_t *root; 28 | } bitree_t; 29 | 30 | /** public interface */ 31 | void bitree_init(bitree_t *tree, void (*destroy)(void *data)); 32 | void bitree_destroy(bitree_t *tree); 33 | int bitree_insert_left(bitree_t *tree, bitree_node_t *node, const void *data); 34 | int bitree_insert_right(bitree_t *tree, bitree_node_t *node, const void *data); 35 | void bitree_remove_left(bitree_t *tree, bitree_node_t *node); 36 | void bitree_remove_right(bitree_t *tree, bitree_node_t *node); 37 | int bitree_merge(bitree_t *merge, bitree_t *left, bitree_t *right, const void *data); 38 | 39 | #define bitree_size(tree) ((tree)->size) 40 | #define bitree_root(tree) ((tree)->rott) 41 | #define bitree_is_eob(node) (NULL == (node)) 42 | #define bitree_is_leaf(node) (NULL == (node)->left && NULL == (node)->right) 43 | #define bitree_data(node) ((node)->data) 44 | #define bitree_left(node) ((node)->left) 45 | #define bitree_right(node) ((node)->right) 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /tree/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON_H__ 2 | #define __COMMON_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | /** 宏形式 */ 30 | #define GREEN "\e[1;32m" 31 | #define BLUE "\e[1;34m" 32 | #define YELLOW "\e[1;33m" 33 | #define RED "\e[1;31m" 34 | 35 | /** const 指针形式 */ 36 | char *MAGENTA = "\e[01;35m"; 37 | char *CYAN = "\e[01;36m"; 38 | char *NORMAL = "\e[0m"; 39 | 40 | #define logprintf(format, arg...) fprintf(stderr, "%s[LOG]%s %s:%d:%s "format"\n",\ 41 | RED, NORMAL,__FILE__, __LINE__, __func__, ##arg) 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /tree/search-tree.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @describe: 3 | * @author: hy0kle@gmail.com 4 | * */ 5 | #include "common.h" 6 | 7 | #define TEST_DATA_NUM 8 8 | /** 9 | * 查找树 ADT 二叉查找树 10 | * */ 11 | typedef int node_value; 12 | typedef struct _tree_node_t tree_node_t; 13 | struct _tree_node_t 14 | { 15 | node_value element; 16 | tree_node_t *left; 17 | tree_node_t *right; 18 | }; 19 | 20 | /** 21 | * 接口申明 22 | * */ 23 | tree_node_t *make_empty(tree_node_t *tree); 24 | tree_node_t *find(const node_value search, tree_node_t *tree); 25 | tree_node_t *find_min(tree_node_t *tree); 26 | tree_node_t *find_max(tree_node_t *tree); 27 | tree_node_t *insert(const node_value value, tree_node_t *tree); 28 | tree_node_t *delete(const node_value value, tree_node_t *tree); 29 | 30 | /** debug function */ 31 | void print_node(const tree_node_t *tree) 32 | { 33 | assert(NULL != tree); 34 | 35 | printf("%stree->element%s = %s%d%s\n", GREEN, NORMAL, CYAN, tree->element, NORMAL); 36 | return; 37 | } 38 | 39 | /** 40 | * l: left 41 | * d: root 42 | * r: right 43 | */ 44 | void ldr_print(const tree_node_t *tree) 45 | { 46 | if (NULL != tree) 47 | { 48 | ldr_print(tree->left); 49 | print_node(tree); 50 | ldr_print(tree->right); 51 | } 52 | } 53 | 54 | int main(int argc, char *argv[]) 55 | { 56 | tree_node_t *root = NULL; 57 | node_value data[TEST_DATA_NUM] = {6, 2, 8, 1, 4, 9, 10, 11}; 58 | root = insert(7, root); 59 | 60 | int i = 0; 61 | for (; i < TEST_DATA_NUM; i++) 62 | { 63 | insert(data[i], root); 64 | } 65 | 66 | logprintf("---left root right---"); 67 | ldr_print(root); 68 | 69 | tree_node_t *tmp = find_min(root); 70 | logprintf("%sfind_min()%s = %d", YELLOW, NORMAL, tmp->element); 71 | 72 | tmp = find_max(root); 73 | logprintf("%sfind_max()%s = %d", YELLOW, NORMAL, tmp->element); 74 | 75 | node_value search = 8; 76 | tmp = find(search, root); 77 | if (NULL != tmp) 78 | { 79 | logprintf("%ssearch: %d is in tree%s", MAGENTA, search, NORMAL); 80 | } 81 | 82 | return 0; 83 | } 84 | 85 | tree_node_t *make_empty(tree_node_t *tree) 86 | { 87 | if (NULL != tree) 88 | { 89 | make_empty(tree->left); 90 | make_empty(tree->right); 91 | free(tree); 92 | } 93 | 94 | return NULL; 95 | } 96 | 97 | tree_node_t *find(const node_value search, tree_node_t *tree) 98 | { 99 | if (NULL == tree) 100 | { 101 | return NULL; 102 | } 103 | else if (search < tree->element) 104 | { 105 | return find(search, tree->left); 106 | } 107 | else if (search > tree->element) 108 | { 109 | return find(search, tree->right); 110 | } 111 | else 112 | { 113 | return tree; 114 | } 115 | } 116 | 117 | /** 118 | * 递归实现 119 | * */ 120 | tree_node_t *find_min(tree_node_t *tree) 121 | { 122 | if (NULL == tree) 123 | { 124 | return NULL; 125 | } 126 | else if (NULL == tree->left) 127 | { 128 | return tree; 129 | } 130 | else 131 | { 132 | return find_min(tree->left); 133 | } 134 | } 135 | 136 | /** 137 | * 迭代实现 138 | * */ 139 | tree_node_t *find_max(tree_node_t *tree) 140 | { 141 | if (NULL != tree) 142 | { 143 | while (NULL != tree->right) 144 | { 145 | tree = tree->right; 146 | } 147 | } 148 | 149 | return tree; 150 | } 151 | 152 | /** 153 | * 暂不处理重复元素 154 | * */ 155 | tree_node_t *insert(const node_value value, tree_node_t *tree) 156 | { 157 | if (NULL == tree) 158 | { 159 | size_t size = sizeof(tree_node_t); 160 | tree = malloc(size); 161 | if (NULL == tree) 162 | { 163 | logprintf("out of space! 申请内存失败! need size: %ld", size); 164 | exit(1); 165 | } 166 | 167 | tree->element = value; 168 | tree->left = NULL; 169 | tree->right= NULL; 170 | } 171 | else if (value < tree->element) 172 | { 173 | tree->left = insert(value, tree->left); 174 | } 175 | else if (value > tree->element) 176 | { 177 | tree->right = insert(value, tree->right); 178 | } 179 | else 180 | { 181 | /** 等于的情况不处理 */ 182 | ; 183 | } 184 | 185 | return tree; 186 | } 187 | 188 | /** 189 | * 删除-正如许多数据结构,最困难的操作是删除 190 | * 如果节点是一片树叶,那么它可以被立即删除; 191 | * 如果节点有一个儿子,则该节点可以在其父节点调整指针绕过该节点后被删除; 192 | * 如果有两个儿子节点,一般的删除策略是用其右子树的最小的数据(很容易找到)代替该节点的数据并递归地删除那个节点(现在它是空的).右子树中的最小的节点不可能有左儿子,所以第二次 delete 要容易. 193 | * */ 194 | tree_node_t *delete(const node_value value, tree_node_t *tree) 195 | { 196 | 197 | } 198 | 199 | --------------------------------------------------------------------------------