├── .gitignore ├── README.md ├── boostpy ├── cppclass │ ├── Makefile │ ├── person.cc │ └── test.py └── helloworld │ ├── Makefile │ ├── hello_boostpy.cc │ └── test.py ├── code-stats ├── multiprocess_time.txt └── stat_codes.py ├── coroutine ├── fib_async_await.py ├── fib_asyncio.py └── test_yield.py ├── ctypes ├── matrix_mul.c └── matrix_mul.py ├── decorator ├── decorator_adv.py └── decorator_example.py ├── echo-server ├── Makefile ├── epoll-echo-server.c ├── libuv-echo-client.c ├── libuv-echo-server.c ├── libuv-helloworld.c ├── select-echo-server.c └── socket-echo-server.c ├── learncpp11 ├── Makefile ├── auto_decltype.cpp ├── class.cpp ├── container.cpp ├── initialize.cpp ├── lambda_expr.cpp ├── misc.cpp ├── move_and_forward.cpp ├── new_type_and_keywords.cpp ├── random.cpp ├── regex.cpp ├── smart_pointer.cpp └── template.cpp ├── learncthehardway ├── Makefile ├── c-skeleton │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── src │ │ ├── dbg.h │ │ └── libex29.c │ └── tests │ │ ├── dbg.h │ │ ├── libex29_tests.c │ │ ├── minunit.h │ │ └── runtests.sh ├── dbg.h ├── devpkg │ ├── Makefile │ ├── README │ ├── bstrlib.c │ ├── bstrlib.h │ ├── commands.c │ ├── commands.h │ ├── db.c │ ├── db.h │ ├── dbg.h │ ├── devpkg.c │ ├── shell.c │ └── shell.h ├── ex1.c ├── ex10.c ├── ex11.c ├── ex12.c ├── ex13.c ├── ex14.c ├── ex15.c ├── ex16.c ├── ex17.c ├── ex18.c ├── ex19.c ├── ex19.h ├── ex2.c ├── ex20.c ├── ex22.c ├── ex22.h ├── ex22_main.c ├── ex23.c ├── ex24.c ├── ex25.c ├── ex26.sh ├── ex27.c ├── ex29.c ├── ex3.c ├── ex31.c ├── ex4.c ├── ex6.c ├── ex7.c ├── ex8.c ├── ex9.c ├── libex29.c ├── liblcthw │ ├── .ycm_extra_conf.py │ ├── LICENSE │ ├── Makefile │ ├── README.md │ ├── bin │ │ ├── netclient.c │ │ └── urlor.c │ ├── src │ │ └── lcthw │ │ │ ├── bstree.c │ │ │ ├── bstree.h │ │ │ ├── bstrlib.c │ │ │ ├── bstrlib.h │ │ │ ├── darray.c │ │ │ ├── darray.h │ │ │ ├── darray_algos.c │ │ │ ├── darray_algos.h │ │ │ ├── dbg.h │ │ │ ├── hashmap.c │ │ │ ├── hashmap.h │ │ │ ├── hashmap_algos.c │ │ │ ├── hashmap_algos.h │ │ │ ├── list.c │ │ │ ├── list.h │ │ │ ├── list_algos.c │ │ │ ├── list_algos.h │ │ │ ├── queue.h │ │ │ ├── radixmap.c │ │ │ ├── radixmap.h │ │ │ ├── ringbuffer.c │ │ │ ├── ringbuffer.h │ │ │ ├── stack.h │ │ │ ├── stats.c │ │ │ ├── stats.h │ │ │ ├── string_algos.c │ │ │ ├── string_algos.h │ │ │ ├── tstree.c │ │ │ └── tstree.h │ ├── tests │ │ ├── bstree_tests.c │ │ ├── darray_algos_tests.c │ │ ├── darray_tests.c │ │ ├── dbg.h │ │ ├── hash.txt │ │ ├── hashmap_algos_tests.c │ │ ├── hashmap_tests.c │ │ ├── list_algos_tests.c │ │ ├── list_tests.c │ │ ├── minunit.h │ │ ├── queue_tests.c │ │ ├── radixmap_tests.c │ │ ├── ringbuffer_tests.c │ │ ├── runtests.sh │ │ ├── stack_tests.c │ │ ├── stats_tests.c │ │ ├── string_algos_tests.c │ │ └── tstree_tests.c │ └── urls.txt ├── object.c └── object.h ├── protobuf ├── proto │ ├── __init__.py │ ├── addressbook.proto │ └── addressbook_pb2.py ├── serialized.txt └── test_addressbook.py ├── py-refresh ├── py_records.txt ├── py_trigger.txt ├── refresh_class.py └── test_refresh.py ├── pylibtravel ├── docopt │ ├── example.sh │ ├── py-grep │ ├── test_file1 │ ├── test_path1 │ │ ├── inner_path │ │ │ └── test_file4 │ │ └── test_file2 │ └── test_path2 │ │ └── test_file3 ├── grpc │ ├── echo_client.py │ ├── echo_server.proto │ ├── echo_server.py │ ├── echo_server_pb2.py │ └── run_codegen.py └── mmap │ ├── del_rule.py │ ├── test.conf │ ├── test.conf.bak │ └── test.sh ├── redis-py ├── redis_friends.py └── test_redis.py ├── roi ├── LICENSE ├── Makefile ├── README.md ├── src │ ├── dbg.h │ ├── entity.h │ ├── gclient.cpp │ ├── gserver.cpp │ ├── olist.cpp │ ├── olist.h │ ├── proto.cpp │ └── proto.h └── tests │ ├── dbg.h │ ├── minunit.h │ ├── olist_tests.cpp │ └── runtests.sh ├── shared_memory ├── Makefile └── test_boost_shared_memory.cc └── ssh └── get_mysql_dump.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.pyc 3 | *.out 4 | *.dat 5 | *.o 6 | *.so 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A collection of sabers to do kinds of trivial stuff. 2 | -------------------------------------------------------------------------------- /boostpy/cppclass/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ --std=c++11 -I /usr/include/python2.7/ -fPIC -shared -o person.so person.cc -lboost_python 3 | -------------------------------------------------------------------------------- /boostpy/cppclass/person.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace boost::python; 6 | 7 | struct Person 8 | { 9 | void set_name(std::string name) { this->name = name; } 10 | std::string print_info(); 11 | void set_items(list& prices, list& discounts); 12 | 13 | 14 | std::string name; 15 | std::vector item_prices; 16 | std::vector item_discounts; 17 | }; 18 | 19 | std::string Person::print_info() 20 | { 21 | std::ostringstream info; 22 | double total_price = 0; 23 | auto it_price = item_prices.begin(); 24 | auto it_discount = item_discounts.begin(); 25 | while(it_price != item_prices.end() && it_discount != item_discounts.end()) 26 | { 27 | total_price += (*it_price) * (1 - *it_discount); 28 | ++it_price; 29 | ++it_discount; 30 | } 31 | info << name <<" $"<(prices[i]); 40 | double discount = extract(discounts[i]); 41 | item_prices.push_back(price); 42 | item_discounts.push_back(discount); 43 | } 44 | } 45 | 46 | BOOST_PYTHON_MODULE(person) 47 | { 48 | class_("Person") 49 | .def("set_name", &Person::set_name) 50 | .def("print_info", &Person::print_info) 51 | .def("set_items", &Person::set_items) 52 | ; 53 | } 54 | -------------------------------------------------------------------------------- /boostpy/cppclass/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | sys.path.append('.') 4 | 5 | 6 | def test(): 7 | import person 8 | p = person.Person() 9 | p.set_name('Qie') 10 | p.set_items([100, 123.456, 888.8], [0.3, 0.1, 0.5]) 11 | print p.print_info() 12 | 13 | 14 | if __name__ == "__main__": 15 | test() 16 | -------------------------------------------------------------------------------- /boostpy/helloworld/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ -I /usr/include/python2.7/ -fPIC -shared -o hello_boostpy.so hello_boostpy.cc -lboost_python 3 | -------------------------------------------------------------------------------- /boostpy/helloworld/hello_boostpy.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char const* greet() 4 | { 5 | return "hello, boost"; 6 | } 7 | 8 | BOOST_PYTHON_MODULE(hello_boostpy) 9 | { 10 | using namespace boost::python; 11 | def("greet", greet); 12 | } 13 | -------------------------------------------------------------------------------- /boostpy/helloworld/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | sys.path.append('.') 4 | 5 | 6 | def test(): 7 | import hello_boostpy 8 | return hello_boostpy.greet() 9 | 10 | 11 | if __name__ == "__main__": 12 | print test() 13 | -------------------------------------------------------------------------------- /code-stats/multiprocess_time.txt: -------------------------------------------------------------------------------- 1 | real 0m39.087s 2 | user 0m17.996s 3 | sys 0m8.516s 4 | 5 | 6 | real 0m41.527s 7 | user 0m18.028s 8 | sys 0m8.864s 9 | 10 | real 5m3.009s 11 | user 0m17.676s 12 | sys 0m8.464s 13 | 14 | 15 | remove sleep 16 | 17 | real 0m36.350s 18 | user 0m17.136s 19 | sys 0m8.172s 20 | 21 | real 0m44.212s 22 | user 0m17.824s 23 | sys 0m8.716s 24 | 25 | real 4m44.543s 26 | user 0m17.680s 27 | sys 0m8.492s 28 | -------------------------------------------------------------------------------- /code-stats/stat_codes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import os 3 | import subprocess 4 | import shlex 5 | import random 6 | from os.path import join 7 | from collections import defaultdict 8 | from multiprocessing.dummy import Process, Queue 9 | 10 | ignore_paths = ['common/cdata', 'common_server/data', 'client/data', 'common_server/bt', 'common_server/Lib', 'common/Lib', 'common_server/lib-dynload-x64', 'common_server/lib-dynload-x86'] 11 | 12 | P_NUM = 8 13 | 14 | cmd_prefix = 'svn blame ' 15 | 16 | def stat_file(fnames, res_queue): 17 | code_stats = defaultdict(int) 18 | for fname in fnames: 19 | print 'processing ', fname 20 | cmd = cmd_prefix + fname 21 | args = shlex.split(cmd) 22 | blame_file_name = 'blame_' + os.path.basename(fname) + str(random.randint(0, 100)) + '.py' 23 | with open(blame_file_name, 'w') as f: 24 | subprocess.call(args, stdout=f) 25 | 26 | with open(blame_file_name, 'r') as f: 27 | for line in f: 28 | args = line.split() 29 | if len(args) >= 2: 30 | author = args[1] 31 | if '@' in author: 32 | author = author.split('@')[0] 33 | code_stats[author] += 1 34 | os.remove(blame_file_name) 35 | 36 | res_queue.put(code_stats) 37 | 38 | def stat_files(): 39 | all_files = [] 40 | for root, dirs, files in os.walk('/home/gzguoyubo/mf/tw2/res/entities/custom_type'): 41 | ignore = False 42 | for ig_path in ignore_paths: 43 | if ig_path in root: 44 | ignore = True 45 | if ignore: 46 | continue 47 | for fname in files: 48 | if not fname.endswith('.py'): 49 | continue 50 | abs_file_path = join(root, fname) 51 | all_files.append(abs_file_path) 52 | 53 | file_sections = [] 54 | file_total_nums = len(all_files) 55 | for i in xrange(P_NUM): 56 | start = i * file_total_nums / P_NUM 57 | stop = start + file_total_nums / P_NUM 58 | if i == P_NUM - 1: 59 | stop = -1 60 | file_sections.append(all_files[start : stop]) 61 | 62 | res_queue = Queue() 63 | processes = [] 64 | for section in file_sections: 65 | p = Process(target=stat_file, args=(section, res_queue)) 66 | p.start() 67 | processes.append(p) 68 | 69 | for p in processes: 70 | p.join() 71 | 72 | total_stats = defaultdict(int) 73 | while not res_queue.empty(): 74 | stat = res_queue.get() 75 | for author, cnt in stat.iteritems(): 76 | total_stats[author] += cnt 77 | 78 | print total_stats 79 | 80 | 81 | if __name__ == '__main__': 82 | stat_files() 83 | 84 | -------------------------------------------------------------------------------- /coroutine/fib_async_await.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import asyncio 3 | import random 4 | 5 | async def smart_fib(n): 6 | index = 0 7 | a = 0 8 | b = 1 9 | while index < n: 10 | sleep_secs = random.uniform(0, 0.2) 11 | await asyncio.sleep(sleep_secs) 12 | print('Smart one think {} secs to get {}'.format(sleep_secs, b)) 13 | a, b = b, a + b 14 | index += 1 15 | 16 | async def stupid_fib(n): 17 | index = 0 18 | a = 0 19 | b = 1 20 | while index < n: 21 | sleep_secs = random.uniform(0, 0.4) 22 | await asyncio.sleep(sleep_secs) 23 | print('Stupid one think {} secs to get {}'.format(sleep_secs, b)) 24 | a, b = b, a + b 25 | index += 1 26 | 27 | if __name__ == '__main__': 28 | loop = asyncio.get_event_loop() 29 | tasks = [ 30 | asyncio.ensure_future(smart_fib(10)), 31 | asyncio.ensure_future(stupid_fib(10)), 32 | ] 33 | loop.run_until_complete(asyncio.wait(tasks)) 34 | print('All fib finished.') 35 | loop.close() 36 | -------------------------------------------------------------------------------- /coroutine/fib_asyncio.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import asyncio 3 | import random 4 | 5 | @asyncio.coroutine 6 | def smart_fib(n): 7 | index = 0 8 | a = 0 9 | b = 1 10 | while index < n: 11 | sleep_secs = random.uniform(0, 0.2) 12 | yield from asyncio.sleep(sleep_secs) 13 | print('Smart one think {} secs to get {}'.format(sleep_secs, b)) 14 | a, b = b, a + b 15 | index += 1 16 | 17 | @asyncio.coroutine 18 | def stupid_fib(n): 19 | index = 0 20 | a = 0 21 | b = 1 22 | while index < n: 23 | sleep_secs = random.uniform(0, 0.4) 24 | yield from asyncio.sleep(sleep_secs) 25 | print('Stupid one think {} secs to get {}'.format(sleep_secs, b)) 26 | a, b = b, a + b 27 | index += 1 28 | 29 | if __name__ == '__main__': 30 | loop = asyncio.get_event_loop() 31 | tasks = [ 32 | asyncio.async(smart_fib(10)), 33 | asyncio.async(stupid_fib(10)), 34 | ] 35 | loop.run_until_complete(asyncio.wait(tasks)) 36 | print('All fib finished.') 37 | loop.close() 38 | 39 | -------------------------------------------------------------------------------- /coroutine/test_yield.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import time 3 | import random 4 | def old_fib(n): 5 | res = [0] * n 6 | index = 0 7 | a = 0 8 | b = 1 9 | while index < n: 10 | res[index] = b 11 | a, b = b, a + b 12 | index += 1 13 | return res 14 | 15 | def fib(n): 16 | index = 0 17 | a = 0 18 | b = 1 19 | while index < n: 20 | yield b 21 | a, b = b, a + b 22 | index += 1 23 | 24 | def stupid_fib(n): 25 | index = 0 26 | a = 0 27 | b = 1 28 | while index < n: 29 | sleep_cnt = yield b 30 | print('let me think {0} secs'.format(sleep_cnt)) 31 | time.sleep(sleep_cnt) 32 | a, b = b, a + b 33 | index += 1 34 | 35 | def copy_fib(n): 36 | print('I am copy from fib') 37 | yield from fib(n) 38 | print('Copy end') 39 | 40 | def copy_stupid_fib(n): 41 | print('I am copy from stupid fib') 42 | yield from stupid_fib(n) 43 | print('Copy end') 44 | 45 | if __name__ == '__main__': 46 | print('-'*10 + 'test old fib' + '-'*10) 47 | for fib_res in old_fib(20): 48 | print(fib_res) 49 | 50 | print('-'*10 + 'test yield fib' + '-'*10) 51 | for fib_res in fib(20): 52 | print(fib_res) 53 | 54 | print('-'*10 + 'test yield send' + '-'*10) 55 | N = 20 56 | sfib = stupid_fib(N) 57 | fib_res = next(sfib) 58 | while True: 59 | print(fib_res) 60 | try: 61 | fib_res = sfib.send(random.uniform(0, 0.5)) 62 | except StopIteration: 63 | break 64 | 65 | print('-'*10 + 'test yield from' + '-'*10) 66 | for fib_res in copy_fib(20): 67 | print(fib_res) 68 | 69 | print('-'*10 + 'test yield from and send' + '-'*10) 70 | N = 20 71 | csfib = copy_stupid_fib(N) 72 | fib_res = next(csfib) 73 | while True: 74 | print(fib_res) 75 | try: 76 | fib_res = csfib.send(random.uniform(0, 0.5)) 77 | except StopIteration: 78 | break 79 | 80 | 81 | -------------------------------------------------------------------------------- /ctypes/matrix_mul.c: -------------------------------------------------------------------------------- 1 | #include "stdio.h" 2 | 3 | int mul(int res[], int ma[], int mb[], int l, int m, int n) 4 | { 5 | int i = 0; 6 | int j = 0; 7 | int k = 0; 8 | for(i=0; i= func._cache_size: 15 | lucky_key = random.choice(list(func._cache.keys())) 16 | func._cache.pop(lucky_key, None) 17 | print('func {} pop cache key {}'.format(func.__name__, lucky_key)) 18 | func._cache[key] = res 19 | return func._cache[key] 20 | return decorator(_cache) 21 | 22 | @func_cache(size=3) 23 | def add_two_number(a, b): 24 | return a + b 25 | 26 | @func_cache() 27 | def product_two_number(a, b): 28 | return a * b 29 | 30 | if __name__ == "__main__": 31 | print('add_two_number func name is {}'.format(add_two_number.__name__)) 32 | print('1. add_two_number(1, 2)') 33 | add_two_number(1, 2) 34 | print('2. add_two_number(2, 3)') 35 | add_two_number(2, 3) 36 | print('3. add_two_number(1, b=2)') 37 | add_two_number(1, b=2) 38 | print('4. add_two_number(1, 2)') 39 | add_two_number(1, 2) 40 | print('5. product_two_number(1, 2)') 41 | product_two_number(1, 2) 42 | print('6. add_two_number(1, 3)') 43 | add_two_number(1, 3) 44 | -------------------------------------------------------------------------------- /decorator/decorator_example.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from functools import wraps 3 | import random 4 | 5 | def func_cache(size=10): 6 | def func_wrapper(func): 7 | cache = {} 8 | @wraps(func) 9 | def inner_deco(*args, **kwargs): 10 | key = (args, frozenset(kwargs.items())) 11 | if key not in cache: 12 | print('func {} is not cached with arguments {} {}'.format( 13 | func.__name__, args, kwargs)) 14 | res = func(*args, **kwargs) 15 | if len(cache) >= size: 16 | lucky_key = random.choice(list(cache.keys())) 17 | print('func {} cache pop {}'.format( 18 | func.__name__, lucky_key)) 19 | cache.pop(lucky_key, None) 20 | cache[key] = res 21 | return cache[key] 22 | return inner_deco 23 | return func_wrapper 24 | 25 | @func_cache(size=3) 26 | def add_two_number(a, b): 27 | return a + b 28 | 29 | @func_cache() 30 | def product_two_number(a, b): 31 | return a * b 32 | 33 | if __name__ == "__main__": 34 | print('add_two_number func name is {}'.format(add_two_number.__name__)) 35 | print('1. add_two_number(1, 2)') 36 | add_two_number(1, 2) 37 | print('2. add_two_number(2, 3)') 38 | add_two_number(2, 3) 39 | print('3. add_two_number(1, b=2)') 40 | add_two_number(1, b=2) 41 | print('4. add_two_number(1, 2)') 42 | add_two_number(1, 2) 43 | print('5. product_two_number(1, 2)') 44 | product_two_number(1, 2) 45 | print('6. add_two_number(1, 3)') 46 | add_two_number(1, 3) 47 | -------------------------------------------------------------------------------- /echo-server/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-g -Wall 2 | PREFIX?=/usr/local 3 | 4 | LDFLAGS=-L${PREFIX}/lib 5 | LDLIBS=-luv -pthread 6 | 7 | all: socket-echo-server select-echo-server epoll-echo-server libuv-helloworld libuv-echo-server libuv-echo-client 8 | 9 | clean: 10 | rm -f *.o 11 | rm -f libuv-echo-client epoll-echo-server socket-echo-server select-echo-server libuv-echo-server libuv-helloworld 12 | rm -rf *.dSYM 13 | -------------------------------------------------------------------------------- /echo-server/epoll-echo-server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define DEFAULT_PORT 7000 13 | #define BACKLOG 5 14 | #define MAX_EVENTS 10 15 | 16 | int fd_A[BACKLOG]; 17 | 18 | void error(const char* msg) 19 | { 20 | perror(msg); 21 | exit(1); 22 | } 23 | 24 | void echo_message(int newsockfd) 25 | { 26 | char buffer[256]; 27 | int n; 28 | bzero(buffer, 256); 29 | n = read(newsockfd, buffer, 255); 30 | if(n < 0) 31 | perror("Error when reading socket.\n"); 32 | if(n == 0) 33 | return; 34 | printf("Here is the message: %s", buffer); 35 | n = write(newsockfd, buffer, strlen(buffer)); 36 | if(n < 0) 37 | perror("Error when writing socket.\n"); 38 | } 39 | 40 | int main() 41 | { 42 | int sockfd, bind_res; 43 | socklen_t clilen; 44 | struct sockaddr_in server_addr, client_addr; 45 | clilen = sizeof(client_addr); 46 | 47 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 48 | if(sockfd < 0) 49 | error("Error when create socket.\n"); 50 | 51 | bzero((char *)&server_addr, sizeof(server_addr)); 52 | server_addr.sin_family = AF_INET; 53 | server_addr.sin_addr.s_addr = INADDR_ANY; 54 | server_addr.sin_port = htons(DEFAULT_PORT); 55 | bind_res = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); 56 | if(bind_res < 0) 57 | error("Error when binding socket.\n"); 58 | 59 | listen(sockfd, BACKLOG); 60 | 61 | struct epoll_event ev, events[MAX_EVENTS]; 62 | int i, nfds, newsock, epollfd; 63 | 64 | epollfd = epoll_create(MAX_EVENTS); 65 | if (epollfd < 0) 66 | { 67 | error("Error when create epoll fd.\n"); 68 | } 69 | ev.events = EPOLLIN; 70 | ev.data.fd = sockfd; 71 | if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &ev) == -1) 72 | { 73 | error("Error when add listen sock to epoll.\n"); 74 | } 75 | 76 | while(1) 77 | { 78 | nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); 79 | if (nfds == -1) 80 | { 81 | error("Error when epoll wait.\n"); 82 | } 83 | for (i=0; i 2 | #include 3 | #include 4 | #include 5 | 6 | uv_loop_t *loop; 7 | #define DEFAULT_PORT 7000 8 | 9 | void my_write_helper(uv_stream_t *); 10 | 11 | void alloc_buf(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) 12 | { 13 | buf->base = (char*) malloc(suggested_size); 14 | buf->len = suggested_size; 15 | } 16 | 17 | void on_write(uv_write_t *req, int status) 18 | { 19 | if (status) 20 | { 21 | fprintf(stderr, "Write error %s.\n", uv_strerror(status)); 22 | } 23 | printf("Wrote.\n"); 24 | free(req); 25 | } 26 | 27 | void on_read(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) 28 | { 29 | if (nread < 0) 30 | { 31 | if (nread != UV_EOF) 32 | fprintf(stderr, "Read error %s\n", uv_err_name(nread)); 33 | uv_close((uv_handle_t*) stream, NULL); 34 | } else if (nread > 0) 35 | { 36 | printf("Read %s", buf->base); 37 | } 38 | 39 | if (buf->base) 40 | free(buf->base); 41 | 42 | my_write_helper(stream); 43 | } 44 | 45 | void my_write_helper(uv_stream_t *stream) 46 | { 47 | printf("Enter a string:"); 48 | char input[1024] = {0}; 49 | fgets(input, sizeof(input), stdin); 50 | int len = strlen(input); 51 | uv_buf_t wrbuf = uv_buf_init(input, len); 52 | uv_write_t *wreq = (uv_write_t*) malloc(sizeof(uv_write_t)); 53 | uv_write(wreq, stream, &wrbuf, 1, on_write); 54 | } 55 | 56 | void on_connect(uv_connect_t *req, int status) 57 | { 58 | if (status < 0) 59 | { 60 | fprintf(stderr, "On connect error %s.\n", uv_strerror(status)); 61 | return; 62 | } 63 | printf("Connected.\n"); 64 | uv_stream_t *stream = req->handle; 65 | my_write_helper(stream); 66 | uv_read_start(stream, alloc_buf, on_read); 67 | } 68 | 69 | int main() 70 | { 71 | loop = uv_default_loop(); 72 | uv_tcp_t *socket = (uv_tcp_t*)malloc(sizeof(uv_tcp_t)); 73 | 74 | uv_tcp_init(loop, socket); 75 | 76 | uv_connect_t *connect = (uv_connect_t*)malloc(sizeof(uv_connect_t)); 77 | 78 | struct sockaddr_in dest; 79 | uv_ip4_addr("127.0.0.1", DEFAULT_PORT, &dest); 80 | uv_tcp_connect(connect, socket, (const struct sockaddr*)&dest, on_connect); 81 | 82 | return uv_run(loop, UV_RUN_DEFAULT); 83 | } 84 | -------------------------------------------------------------------------------- /echo-server/libuv-echo-server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define DEFAULT_PORT 7000 6 | #define DEFAULT_BACKLOG 128 7 | uv_loop_t *loop; 8 | struct sockaddr_in addr; 9 | 10 | 11 | void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) 12 | { 13 | buf->base = (char*) malloc(suggested_size); 14 | buf->len = suggested_size; 15 | } 16 | 17 | void echo_write(uv_write_t *req, int status) 18 | { 19 | if (status) 20 | { 21 | fprintf(stderr, "Write error %s.\n", uv_strerror(status)); 22 | } 23 | free(req); 24 | } 25 | 26 | void echo_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) 27 | { 28 | if (nread < 0) 29 | { 30 | if (nread != UV_EOF) 31 | fprintf(stderr, "Read error %s\n", uv_err_name(nread)); 32 | uv_close((uv_handle_t*) client, NULL); 33 | } else if (nread > 0) 34 | { 35 | uv_write_t *req = (uv_write_t*) malloc(sizeof(uv_write_t)); 36 | uv_buf_t wrbuf = uv_buf_init(buf->base, nread); 37 | uv_write(req, client, &wrbuf, 1, echo_write); 38 | } 39 | 40 | if (buf->base) 41 | free(buf->base); 42 | } 43 | 44 | void on_new_connection(uv_stream_t *server, int status) 45 | { 46 | if(status < 0) 47 | { 48 | fprintf(stderr, "On new connection error %s.\n", uv_strerror(status)); 49 | return; 50 | } 51 | printf("new connection is coming...\n"); 52 | uv_tcp_t *client = (uv_tcp_t*)malloc(sizeof(uv_tcp_t)); 53 | uv_tcp_init(loop, client); 54 | if(uv_accept(server, (uv_stream_t*)client) == 0) 55 | { 56 | uv_read_start((uv_stream_t*)client, alloc_buffer, echo_read); 57 | } else 58 | { 59 | uv_close((uv_handle_t*)client, NULL); 60 | } 61 | } 62 | 63 | int main() 64 | { 65 | loop = uv_default_loop(); 66 | 67 | uv_tcp_t server; 68 | uv_tcp_init(loop, &server); 69 | 70 | uv_ip4_addr("0.0.0.0", DEFAULT_PORT, &addr); 71 | 72 | uv_tcp_bind(&server, (const struct sockaddr*)&addr, 0); 73 | int r = uv_listen((uv_stream_t*)&server, DEFAULT_BACKLOG, on_new_connection); 74 | if (r) 75 | { 76 | fprintf(stderr, "Listen error %s.\n", uv_strerror(r)); 77 | return 1; 78 | } 79 | return uv_run(loop, UV_RUN_DEFAULT); 80 | } 81 | -------------------------------------------------------------------------------- /echo-server/libuv-helloworld.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | uv_loop_t* loop = malloc(sizeof(uv_loop_t)); 8 | uv_loop_init(loop); 9 | 10 | printf("quiting\n"); 11 | uv_run(loop, UV_RUN_DEFAULT); 12 | 13 | uv_loop_close(loop); 14 | free(loop); 15 | return 0; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /echo-server/select-echo-server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define DEFAULT_PORT 7000 12 | #define BACKLOG 5 13 | 14 | int fd_A[BACKLOG]; 15 | 16 | void error(const char* msg) 17 | { 18 | perror(msg); 19 | exit(1); 20 | } 21 | 22 | void echo_message(int newsockfd) 23 | { 24 | char buffer[256]; 25 | int n; 26 | bzero(buffer, 256); 27 | n = read(newsockfd, buffer, 255); 28 | if(n < 0) 29 | perror("Error when reading socket.\n"); 30 | if(n == 0) 31 | return; 32 | printf("Here is the message: %s", buffer); 33 | n = write(newsockfd, buffer, strlen(buffer)); 34 | if(n < 0) 35 | perror("Error when writing socket.\n"); 36 | } 37 | 38 | int main() 39 | { 40 | int sockfd, bind_res; 41 | socklen_t clilen; 42 | struct sockaddr_in server_addr, client_addr; 43 | 44 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 45 | if(sockfd < 0) 46 | error("Error when create socket.\n"); 47 | 48 | bzero((char *)&server_addr, sizeof(server_addr)); 49 | server_addr.sin_family = AF_INET; 50 | server_addr.sin_addr.s_addr = INADDR_ANY; 51 | server_addr.sin_port = htons(DEFAULT_PORT); 52 | bind_res = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); 53 | if(bind_res < 0) 54 | error("Error when binding socket.\n"); 55 | 56 | listen(sockfd, BACKLOG); 57 | 58 | fd_set fdsr; 59 | struct timeval tv; 60 | tv.tv_sec = 1; 61 | tv.tv_usec = 0; 62 | int i = 0, conn_amount = 0, ret = 0; 63 | int maxsock = sockfd; 64 | int newfd; 65 | clilen = sizeof(client_addr); 66 | while(1) 67 | { 68 | FD_ZERO(&fdsr); 69 | FD_SET(sockfd, &fdsr); 70 | for (i=0; i maxsock) 109 | { 110 | maxsock = newfd; 111 | } 112 | } 113 | else 114 | { 115 | printf("Now can't accept more connections.\n"); 116 | send(newfd, "bye", 4, 0); 117 | close(newfd); 118 | continue; 119 | } 120 | } 121 | } 122 | 123 | close(sockfd); 124 | return 0; 125 | } 126 | -------------------------------------------------------------------------------- /echo-server/socket-echo-server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define DEFAULT_PORT 7000 10 | 11 | void error(const char* msg) 12 | { 13 | perror(msg); 14 | exit(1); 15 | } 16 | 17 | void echo_message(int newsockfd) 18 | { 19 | char buffer[256]; 20 | int n; 21 | while(1) 22 | { 23 | bzero(buffer, 256); 24 | n = read(newsockfd, buffer, 255); 25 | if(n < 0) 26 | error("Error when reading socket.\n"); 27 | if(n == 0) 28 | return; 29 | printf("Here is the message: %s", buffer); 30 | n = write(newsockfd, buffer, strlen(buffer)); 31 | if(n < 0) 32 | error("Error when writing socket.\n"); 33 | } 34 | } 35 | 36 | int main() 37 | { 38 | int sockfd, newsockfd, pid, bind_res; 39 | socklen_t clilen; 40 | struct sockaddr_in server_addr, client_addr; 41 | 42 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 43 | if(sockfd < 0) 44 | error("Error when create socket.\n"); 45 | 46 | bzero((char *)&server_addr, sizeof(server_addr)); 47 | server_addr.sin_family = AF_INET; 48 | server_addr.sin_addr.s_addr = INADDR_ANY; 49 | server_addr.sin_port = htons(DEFAULT_PORT); 50 | bind_res = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); 51 | if(bind_res < 0) 52 | error("Error when binding socket.\n"); 53 | 54 | listen(sockfd, 5); 55 | clilen = sizeof(client_addr); 56 | while(1) 57 | { 58 | newsockfd = accept(sockfd, (struct sockaddr *)&client_addr, &clilen); 59 | if(newsockfd < 0) 60 | error("Error when accept socket.\n"); 61 | pid = fork(); 62 | if(pid < 0) 63 | error("Error when fork.\n"); 64 | if(pid == 0) 65 | { 66 | close(sockfd); 67 | echo_message(newsockfd); 68 | exit(0); 69 | } 70 | else 71 | { 72 | close(newsockfd); 73 | } 74 | } 75 | 76 | close(sockfd); 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /learncpp11/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++-4.9 2 | CPPFLAGS=-g -std=c++11 -O2 -Wall -Wextra -rdynamic -DNDEBUG $(OPTFLAGS) 3 | LDLIBS=$(OPTLIBS) 4 | 5 | SOURCES=$(wildcard *.cpp) 6 | TARGETS=$(patsubst %.cpp,%,$(SOURCES)) 7 | 8 | all: $(TARGETS) 9 | 10 | clean: 11 | rm -rf $(TARGETS) 12 | find . -name "*.gc*" -exec rm {} \; 13 | rm -rf `find . -name "*.dSYM" -print` 14 | 15 | -------------------------------------------------------------------------------- /learncpp11/class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | class TestClass 6 | { 7 | public: 8 | TestClass() = default; 9 | TestClass(const int i, const char c): member_i(i), member_c(c) {} 10 | TestClass(const int i): TestClass(i, 0) { member_c = 'T';} 11 | TestClass(const TestClass&) = default; 12 | //TestClass(const TestClass&) = delete; 13 | TestClass& operator=(const TestClass&); 14 | 15 | virtual void print_msg() {cout< alloc; 79 | auto p = alloc.allocate(10); 80 | alloc.construct(p, 10); 81 | cout<member_i<<'\t'<member_c<print_msg(); 97 | SubTestClass stc(10); 98 | TestClass tc6 = (TestClass)stc; 99 | tc6.print_msg(); 100 | 101 | cout<<"test inherit base class contructor:\n"; 102 | SubTestClass stc2(1024, 'H'); 103 | stc2.print_msg(); 104 | 105 | cout<<"test multi inherit constructor:\n"; 106 | MultiSubClass mtc(1024); 107 | mtc.print_msg(); 108 | return 0; 109 | } 110 | 111 | -------------------------------------------------------------------------------- /learncpp11/initialize.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | 9 | // class member initialization 10 | class InitClass 11 | { 12 | public: 13 | void print_class() 14 | { 15 | cout< error_msg(int typ) 26 | { 27 | switch(typ) 28 | { 29 | case 1: 30 | return {"type1", "msg1"}; 31 | case 2: 32 | return {"type2", "msg2"}; 33 | default: 34 | return {}; 35 | } 36 | } 37 | 38 | // return pair using list initialization 39 | pair get_pair(int typ) 40 | { 41 | if(typ == 1) return {"key", "value"}; 42 | return pair("default key", "default value"); 43 | } 44 | 45 | // class member(of class type) initialization 46 | class InitClassMgr 47 | { 48 | public: 49 | vector init_objs = {InitClass()}; 50 | }; 51 | 52 | int main() 53 | { 54 | // simple list initialization 55 | int single_int1 = 0; 56 | int single_int2 = {0}; 57 | cout<<"test list initialization:\n"< v1 = {"ab", "cd", "ef"}; 66 | list l2{"gh", "ij", "kl"}; 67 | //vector v3("mn", "op", "qr"); // wrong initialization format 68 | cout<<"test vector/list list initialization:\n"< m1 = 72 | { 73 | {"a", "A"}, 74 | {"b", "B"}, 75 | {"c", "C"} 76 | }; 77 | m1.insert({"d", "D"}); 78 | set s1 = {"a", "b", "c"}; 79 | cout<<"test map/set list initialization:\n"< err_msg1 = error_msg(1); 83 | vector err_msg2 = error_msg(2); 84 | vector err_msg3 = error_msg(3); 85 | cout<<"test return value list initialization:\n"< p1 = get_pair(1); 89 | pair p2 = get_pair(2); 90 | cout<<"test return pair list initialization:\n"< *pv = new vector{0, 1, 2, 3, 4}; 99 | int *pi = new int[5]{0, 1, 2, 3, 4}; 100 | cout<<"test new alloator using list initialization:\n"<<(*pv)[2]<<'\t'< 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | // lambda: [capture list] (parameter list) -> return type { function body } 9 | cout<<"Test simple lambda f1:\n"; 10 | auto f1 = [] { return 1; }; 11 | auto f2 = [] () { return 2; }; 12 | cout< border) cout< border) cout< border) cout< border) cout< border) cout< border) {cout< double 53 | {if(i % 5) return i * 5.0; else return i;}; 54 | transform(begin(test_data), end(test_data), begin(test_data), f10); 55 | for_each(begin(test_data), end(test_data), f6); 56 | cout< 2 | #include 3 | using namespace std; 4 | 5 | int out_i = 0; 6 | constexpr int sz() { return 42; } 7 | constexpr int new_sz(int cnt) { return sz() * cnt; } 8 | 9 | // noexcept 10 | void no_except() noexcept 11 | { 12 | throw 1; 13 | } 14 | 15 | void no_except2() noexcept(noexcept(no_except())) 16 | {} 17 | 18 | int main() 19 | { 20 | // long long 21 | long large = LONG_MAX; 22 | long long long_large = LLONG_MAX; 23 | long long long_long_large = 1LL << 63; 24 | cout<<"test long long: "< 2 | #include 3 | 4 | int main() 5 | { 6 | std::cout<<"test default random engine:\n"; 7 | std::default_random_engine e; 8 | e.seed(time(0)); 9 | for(size_t i = 0; i < 10; i++) 10 | std::cout< u(0, 9); 17 | for(size_t i = 0; i < 10; i++) 18 | std::cout< u2(0, 1); 25 | for(size_t i = 0; i < 10; i++) 26 | std::cout< n(4, 1.5); 33 | std::vector vals(9); 34 | for(size_t i = 0; i < 250; i++) 35 | { 36 | unsigned v = lround(n(e)); 37 | if(v < vals.size()) vals[v]++; 38 | } 39 | 40 | for(size_t i = 0; i < vals.size(); i++) 41 | { 42 | std::cout< bers(2); 50 | for(size_t i = 0; i < 200; i++) 51 | { 52 | if(b(e)) bers[1]++; 53 | else bers[0]++; 54 | } 55 | std::cout<<"True: "< 2 | #include 3 | #include 4 | #include 5 | 6 | /* 7 | * sudo add-apt-repository ppa:ubuntu-toolchain-r/test 8 | * sudo apt-get update 9 | * sudo apt=get install gcc-4.9 g++-4.9 c++-4.9 10 | */ 11 | 12 | int main() 13 | { 14 | std::cout<<"test regex simple usage:\n"; 15 | std::string email_pattern("(\\w)+(\\.\\w+)*@(\\w)+((\\.\\w+)+)"); 16 | try 17 | { 18 | std::regex email_regex(email_pattern); 19 | std::smatch results; 20 | std::string test_email_str = "My email is yubo1911@163.com"; 21 | if(std::regex_search(test_email_str, results, email_regex)) 22 | { 23 | std::cout< test_filenames = {"regex.cpp", "iostream.h", "template.CPP", "class.hPP", "Ah, regex.cpp", "regex.cpp Ah"}; 37 | for(auto fn : test_filenames) 38 | { 39 | if(std::regex_match(fn, cpp_regex)) 40 | { 41 | std::cout<<"cpp file: "<str()< test_phones = {"010-82224567", "(010-83332345", "(020)62334567", "(021) 22346543", "0357-4223456", "0358-465788"}; 75 | for(auto fn : test_phones) 76 | { 77 | if(std::regex_match(fn, results, phone_regex)) 78 | { 79 | if(results[1].matched) 80 | { 81 | if(!results[3].matched) continue; 82 | if(results[4].matched && results[4].str() == "-") continue; 83 | } 84 | else 85 | { 86 | if(results[3].matched) continue; 87 | if(!(results[4].matched && results[4].str() == "-")) continue; 88 | } 89 | std::cout< 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void process(shared_ptr ptr) 8 | { 9 | cout<<"in process use_count:"< clone(int p) 19 | { 20 | return unique_ptr(new int(p)); 21 | } 22 | 23 | void process_unique_ptr(unique_ptr up) 24 | { 25 | cout<<"process unique ptr: "<<*up< p1 = make_shared(""); 32 | if(p1 && p1->empty()) 33 | *p1 = "hello"; 34 | 35 | auto p2 = make_shared("world"); 36 | cout<<*p1<<' '<<*p2< p4(new int(1024)); 48 | //shared_ptr p5 = new int(1024); // wrong, no implicit constructor 49 | cout<<*p4< p5(new int(1024)); 53 | process(p5); 54 | int v5 = *p5; 55 | cout<<"v5: "<(p6)); 59 | int v6 = *p6; 60 | cout<<"v6: "< p8(p7, print_at_delete); 70 | p8 = make_shared(1025); 71 | 72 | cout<<"test unique_ptr base usage:"< up1(new int(1024)); 74 | cout<<"up1: "<<*up1< up2(up1.release()); 76 | cout<<"up2: "<<*up2< up3(up1); // wrong, unique_ptr can not copy 78 | //up2 = up1; // wrong, unique_ptr can not copy 79 | unique_ptr up4(new int(1025)); 80 | up4.reset(up2.release()); 81 | cout<<"up4: "<<*up4< up6(p9, print_at_delete); 92 | unique_ptr up7(new int(1025)); 93 | up6.reset(up7.release()); 94 | 95 | cout<<"test weak_ptr basic usage:"<(1024); 97 | weak_ptr wp1(p10); 98 | cout<<"p10 use_count: "< p11 = wp1.lock(); 101 | if(p11) cout<<"wp1: "<<*p11<<" use count: "< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int add(int i, int j) { return i + j; } 9 | struct divide 10 | { 11 | int operator()(int i, int j) 12 | { 13 | return i / j; 14 | } 15 | }; 16 | 17 | template class Bar 18 | { 19 | friend T; 20 | protected: 21 | int val = 100; 22 | }; 23 | 24 | class Foo 25 | { 26 | public: 27 | void print_bar(Bar &bar) {std::cout<<"bar:\t"< using twin = std::pair; 31 | template using str_int = std::pair; 32 | 33 | template> 34 | int compare(const T &v1, const T &v2, F f=F()) 35 | { 36 | if(f(v1, v2)) return -1; 37 | if(f(v2, v1)) return 1; 38 | return 0; 39 | } 40 | 41 | template 42 | //decltype(*beg) get_begin(It beg) 43 | auto get_begin(It beg) -> decltype(*beg) 44 | { 45 | return *beg; 46 | } 47 | 48 | template 49 | std::ostream &print_variadic(std::ostream &os, const T &t) 50 | { 51 | return os< 55 | std::ostream &print_variadic(std::ostream &os, const T &t, const Args&... rest) 56 | { 57 | os<:\n"; 64 | /* wrong. lambda and some other functions can't be represented by function ptr. 65 | std::map> binops = { 66 | {"+", add}, 67 | {"-", std::minus()}, 68 | {"*", [](int i, int j) {return i * j; }}, 69 | {"/", divide()}, 70 | }; 71 | */ 72 | std::map> binops = { 73 | {"+", add}, 74 | {"-", std::minus()}, 75 | {"*", [](int i, int j) {return i * j; }}, 76 | {"/", divide()}, 77 | }; 78 | std::cout<<"+:\t"< done.\n"< bar; 86 | Foo foo; 87 | foo.print_bar(bar); 88 | std::cout<<"test friend template type done.\n"< twin_str = {"abc", "def"}; 92 | std::cout<<"twin_str:\t"< strno = {"abc", 100}; 94 | std::cout<<"strno:\t"< numbers = {1, 2, 3, 4, 5}; 105 | std::cout<<"get_begin:\t"< 5 | #include 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define debug(M, ...) 10 | #else 11 | #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 17 | 18 | #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 21 | 22 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 23 | 24 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 25 | 26 | #define check_mem(A) check((A), "Out of memory.") 27 | 28 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /learncthehardway/c-skeleton/src/libex29.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dbg.h" 4 | 5 | int print_a_message(const char *msg) 6 | { 7 | printf("A STRING: %s\n", msg); 8 | 9 | return 0; 10 | } 11 | 12 | int uppercase(const char *msg) 13 | { 14 | int i = 0; 15 | 16 | for (i=0; msg[i] != '\0'; i++) 17 | { 18 | printf("%c", toupper(msg[i])); 19 | } 20 | 21 | printf("\n"); 22 | return 0; 23 | } 24 | 25 | int lowercase(const char *msg) 26 | { 27 | int i = 0; 28 | for (i=0; msg[i] != '\0'; i++) 29 | { 30 | printf("%c", tolower(msg[i])); 31 | } 32 | 33 | printf("\n"); 34 | return 0; 35 | } 36 | 37 | int fail_on_purpose(const char *msg) 38 | { 39 | return 1; 40 | } 41 | -------------------------------------------------------------------------------- /learncthehardway/c-skeleton/tests/dbg.h: -------------------------------------------------------------------------------- 1 | #ifndef _dbg_h 2 | #define _dbg_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define debug(M, ...) 10 | #else 11 | #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 17 | 18 | #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 21 | 22 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 23 | 24 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 25 | 26 | #define check_mem(A) check((A), "Out of memory.") 27 | 28 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /learncthehardway/c-skeleton/tests/libex29_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | 4 | typedef int (*lib_function)(const char *data); 5 | char *lib_file = "build/libYOUR_LIBRARY.so"; 6 | void *lib = NULL; 7 | 8 | int check_function(const char *func_to_run, const char *data, int expected) 9 | { 10 | lib_function func = dlsym(lib, func_to_run); 11 | check(func != NULL, "Did not find %s function in the library %s: %s", func_to_run, lib_file, dlerror()); 12 | 13 | int rc = func(data); 14 | check(rc == expected, "Function %s return %d for data: %s", func_to_run, rc, data); 15 | 16 | return 1; 17 | error: 18 | return 0; 19 | } 20 | 21 | char *test_dlopen() 22 | { 23 | lib = dlopen(lib_file, RTLD_NOW); 24 | mu_assert(lib != NULL, "Failed to open the library to test."); 25 | return NULL; 26 | } 27 | 28 | char *test_functions() 29 | { 30 | mu_assert(check_function("print_a_message", "Hello", 0), "print_a_message failed"); 31 | mu_assert(check_function("uppercase", "Hello", 0), "uppercase failed"); 32 | mu_assert(check_function("lowercase", "Hello", 0), "lowercase failed"); 33 | return NULL; 34 | } 35 | 36 | char *test_failures() 37 | { 38 | mu_assert(check_function("fail_on_purpose", "Hello", 1), "fail_on_purpose should fail"); 39 | return NULL; 40 | } 41 | 42 | char *test_dlclose() 43 | { 44 | int rc = dlclose(lib); 45 | mu_assert(rc == 0, "Failed to close lib"); 46 | return NULL; 47 | } 48 | 49 | char *all_tests() 50 | { 51 | mu_suite_start(); 52 | 53 | mu_run_test(test_dlopen); 54 | mu_run_test(test_functions); 55 | mu_run_test(test_failures); 56 | mu_run_test(test_dlclose); 57 | 58 | return NULL; 59 | } 60 | 61 | RUN_TESTS(all_tests); 62 | -------------------------------------------------------------------------------- /learncthehardway/c-skeleton/tests/minunit.h: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #ifndef _minunit_h 3 | #define _minunit_h 4 | 5 | #include 6 | #include 7 | #include "dbg.h" 8 | 9 | #define mu_suite_start() char *message = NULL 10 | 11 | #define mu_assert(test, message) if (!(test)) {log_err(message); return message;} 12 | #define mu_run_test(test) debug("\n--------%s", ""#test); \ 13 | message = test(); tests_run++; if (message) return message; 14 | 15 | #define RUN_TESTS(name) int main(int argc, char *argv[]) \ 16 | {\ 17 | argc = 1;\ 18 | debug("------RUNNING: %s", argv[0]);\ 19 | printf("------\nRUNNING: %s\n", argv[0]);\ 20 | char *result = name();\ 21 | if (result != 0) \ 22 | {\ 23 | printf("FAILED: %s\n", result);\ 24 | }\ 25 | else\ 26 | {\ 27 | printf("ALL TESTS PASSED\n");\ 28 | }\ 29 | printf("Tests run: %d\n", tests_run);\ 30 | exit(result != 0);\ 31 | } 32 | 33 | int tests_run; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /learncthehardway/c-skeleton/tests/runtests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Running unit test:" 4 | 5 | for i in tests/*_tests 6 | do 7 | if test -f $i 8 | then 9 | if $VALGRIND ./$i 2>> tests/tests.log 10 | then 11 | echo $i PASS 12 | else 13 | echo "ERROR in test $i: here's tests/tests.log" 14 | echo "---" 15 | tail tests/tests.log 16 | exit 1 17 | fi 18 | fi 19 | done 20 | 21 | echo "" 22 | -------------------------------------------------------------------------------- /learncthehardway/dbg.h: -------------------------------------------------------------------------------- 1 | #ifndef _dbg_h 2 | #define _dbg_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define debug(M, ...) 10 | #else 11 | #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 17 | 18 | #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 21 | 22 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 23 | 24 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 25 | 26 | #define check_mem(A) check((A), "Out of memory.") 27 | 28 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /learncthehardway/devpkg/Makefile: -------------------------------------------------------------------------------- 1 | PREFIX?=/usr/local 2 | CFLAGS=-g -Wall -I${PREFIX}/apr/include/apr-1 -I${PREFIX}/apr/include/apr-util-1 -D_LARGEFILE64_SOURCE=1 3 | 4 | all: devpkg 5 | 6 | devpkg: bstrlib.o db.o shell.o commands.o 7 | 8 | LDFLAGS=-L${PREFIX}/apr/lib 9 | LDLIBS=-lapr-1 -pthread -laprutil-1 10 | 11 | install: all 12 | install -d ${DESTDIR}/${PREFIX}/bin/ 13 | install devpkg ${DESTDIR}/${PREFIX}/bin/ 14 | 15 | clean: 16 | rm -f *.o 17 | rm -f devpkg 18 | rm -rf *.dSYM 19 | -------------------------------------------------------------------------------- /learncthehardway/devpkg/README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yubo1911/saber/aba4efee1afa10ef582f705fbd1d4d2a4829c413/learncthehardway/devpkg/README -------------------------------------------------------------------------------- /learncthehardway/devpkg/commands.h: -------------------------------------------------------------------------------- 1 | #ifndef _commands_h 2 | #define _commands_h 3 | 4 | #include 5 | 6 | #define DEPENDS_PATH "/tmp/DEPENDS" 7 | #define TAR_GZ_SRC "/tmp/pkg-src.tar.gz" 8 | #define TAR_BZ2_SRC "/tmp/pkg-src.tar.bz2" 9 | #define BUILD_DIR "/tmp/pkg-build" 10 | #define GIT_PAT "*.git" 11 | #define DEPEND_PAT "*DEPENDS" 12 | #define TAR_GZ_PAT "*.tar.gz" 13 | #define TAR_BZ2_PAT "*.tar.bz2" 14 | #define CONFIG_SCRIPT "/tmp/pkg-build/configure" 15 | 16 | enum CommandType 17 | { 18 | COMMAND_NONE, COMMAND_INSTALL, COMMAND_LIST, COMMAND_FETCH, 19 | COMMAND_INIT, COMMAND_BUILD 20 | }; 21 | 22 | int Command_fetch(apr_pool_t *p, const char *url, int fetch_only); 23 | int Command_install(apr_pool_t *p, const char *url, const char *configure_opts, 24 | const char *make_opts, const char *install_opts); 25 | int Command_depends(apr_pool_t *p, const char *path); 26 | int Command_build(apr_pool_t *p, const char *url, const char *configure_opts, 27 | const char *make_opts, const char *install_opts); 28 | 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /learncthehardway/devpkg/db.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "db.h" 6 | #include "bstrlib.h" 7 | #include "dbg.h" 8 | 9 | static FILE *DB_open(const char *path, const char *mode) 10 | { 11 | return fopen(path, mode); 12 | } 13 | 14 | static void DB_close(FILE *db) 15 | { 16 | fclose(db); 17 | } 18 | 19 | static bstring DB_load() 20 | { 21 | FILE *db = NULL; 22 | bstring data = NULL; 23 | 24 | db = DB_open(DB_FILE, "r"); 25 | check(db, "Failed to open database: %s", DB_FILE); 26 | 27 | data = bread((bNread)fread, db); 28 | check(data, "Failed to read from db file: %s", DB_FILE); 29 | 30 | DB_close(db); 31 | return data; 32 | 33 | error: 34 | if (db) DB_close(db); 35 | if (data) bdestroy(data); 36 | return NULL; 37 | } 38 | 39 | int DB_update(const char *url) 40 | { 41 | if (DB_find(url)) 42 | { 43 | log_info("Already recorded as installed: %s", url); 44 | } 45 | 46 | FILE *db = DB_open(DB_FILE, "a+"); 47 | check(db, "Failed to open database file: %s", DB_FILE); 48 | 49 | bstring line = bfromcstr(url); 50 | bconchar(line, '\n'); 51 | int rc = fwrite(line->data, blength(line), 1, db); 52 | check(rc == 1, "Failed to append to the db"); 53 | 54 | return 0; 55 | 56 | error: 57 | if (db) DB_close(db); 58 | return -1; 59 | } 60 | 61 | int DB_find(const char *url) 62 | { 63 | bstring data = NULL; 64 | bstring line = bfromcstr(url); 65 | int res = -1; 66 | 67 | data = DB_load(); 68 | check(data, "Failed to load data: %s", DB_FILE); 69 | 70 | if (binstr(data, 0, line) == BSTR_ERR) 71 | { 72 | res = 0; 73 | } 74 | else 75 | { 76 | res = 1; 77 | } 78 | 79 | error: // fall through 80 | if (data) bdestroy(data); 81 | if (line) bdestroy(line); 82 | 83 | return res; 84 | } 85 | 86 | int DB_init() 87 | { 88 | apr_pool_t *p = NULL; 89 | apr_pool_initialize(); 90 | apr_pool_create(&p, NULL); 91 | 92 | if (access(DB_DIR, W_OK | X_OK) == -1) 93 | { 94 | apr_status_t rc = apr_dir_make_recursive(DB_DIR, 95 | APR_UREAD | APR_UWRITE | APR_UEXECUTE | 96 | APR_GREAD | APR_GWRITE | APR_GEXECUTE, p); 97 | check(rc == APR_SUCCESS, "Failed to make database dir: %s", DB_DIR); 98 | } 99 | 100 | if (access(DB_FILE, W_OK) == -1) 101 | { 102 | FILE *db = DB_open(DB_FILE, "w"); 103 | check(db, "Failed to open database: %s", DB_FILE); 104 | DB_close(db); 105 | } 106 | 107 | apr_pool_destroy(p); 108 | return 0; 109 | 110 | error: 111 | apr_pool_destroy(p); 112 | return -1; 113 | 114 | } 115 | 116 | int DB_list() 117 | { 118 | bstring data = DB_load(); 119 | check(data, "Failed to load data: %s", DB_FILE); 120 | 121 | printf("%s", bdata(data)); 122 | bdestroy(data); 123 | return 0; 124 | 125 | error: 126 | return -1; 127 | } 128 | 129 | -------------------------------------------------------------------------------- /learncthehardway/devpkg/db.h: -------------------------------------------------------------------------------- 1 | #ifndef _db_h 2 | #define _db_h 3 | 4 | #define DB_FILE "/usr/local/.devpkg/db" 5 | #define DB_DIR "/usr/local/.devpkg" 6 | 7 | int DB_init(); 8 | int DB_list(); 9 | int DB_update(const char *url); 10 | int DB_find(const char *url); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /learncthehardway/devpkg/dbg.h: -------------------------------------------------------------------------------- 1 | #ifndef _dbg_h 2 | #define _dbg_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define debug(M, ...) 10 | #else 11 | #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 17 | 18 | #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 21 | 22 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 23 | 24 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 25 | 26 | #define check_mem(A) check((A), "Out of memory.") 27 | 28 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /learncthehardway/devpkg/devpkg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "dbg.h" 8 | #include "db.h" 9 | #include "commands.h" 10 | 11 | int main(int argc, const char const *argv[]) 12 | { 13 | apr_pool_t *p = NULL; 14 | apr_pool_initialize(); 15 | apr_pool_create(&p, NULL); 16 | 17 | apr_getopt_t *opt; 18 | apr_status_t rv; 19 | 20 | char ch = '\0'; 21 | const char *optarg = NULL; 22 | const char *config_opts = NULL; 23 | const char *install_opts = NULL; 24 | const char *make_opts = NULL; 25 | const char *url = NULL; 26 | enum CommandType request = COMMAND_NONE; 27 | 28 | rv = apr_getopt_init(&opt, p, argc, argv); 29 | while (apr_getopt(opt, "I:Lc:m:i:d:SF:B:", &ch, &optarg) == APR_SUCCESS) 30 | { 31 | switch (ch) 32 | { 33 | case 'I': 34 | request = COMMAND_INSTALL; 35 | url = optarg; 36 | break; 37 | 38 | case 'L': 39 | request = COMMAND_LIST; 40 | break; 41 | 42 | case 'c': 43 | config_opts = optarg; 44 | break; 45 | 46 | case 'm': 47 | make_opts = optarg; 48 | break; 49 | 50 | case 'i': 51 | install_opts = optarg; 52 | break; 53 | 54 | case 'S': 55 | request = COMMAND_INIT; 56 | break; 57 | 58 | case 'F': 59 | request = COMMAND_FETCH; 60 | url = optarg; 61 | break; 62 | 63 | case 'B': 64 | request = COMMAND_BUILD; 65 | url = optarg; 66 | break; 67 | } 68 | } 69 | 70 | switch (request) 71 | { 72 | case COMMAND_INSTALL: 73 | check(url, "You must at least give a URL."); 74 | Command_install(p, url, config_opts, make_opts, install_opts); 75 | break; 76 | 77 | case COMMAND_LIST: 78 | DB_list(); 79 | break; 80 | 81 | case COMMAND_FETCH: 82 | check(url, "You must give a URL."); 83 | Command_fetch(p, url, 1); 84 | log_info("Downloaded to %s and in /tmp/", BUILD_DIR); 85 | break; 86 | 87 | case COMMAND_BUILD: 88 | check(url, "You must at least give a URL."); 89 | Command_build(p, url, config_opts, make_opts, install_opts); 90 | break; 91 | 92 | case COMMAND_INIT: 93 | rv = DB_init(); 94 | check(rv == 0, "Failed to make the database."); 95 | break; 96 | 97 | default: 98 | sentinel("Invalid command given."); 99 | } 100 | 101 | return 0; 102 | 103 | error: 104 | return 1; 105 | } 106 | -------------------------------------------------------------------------------- /learncthehardway/devpkg/shell.c: -------------------------------------------------------------------------------- 1 | #include "shell.h" 2 | #include "db.h" 3 | #include "dbg.h" 4 | #include 5 | 6 | int Shell_exec(Shell template, ...) 7 | { 8 | apr_pool_t *p = NULL; 9 | int rc = -1; 10 | apr_status_t rv = APR_SUCCESS; 11 | va_list argp; 12 | const char *key = NULL; 13 | const char *arg = NULL; 14 | int i = 0; 15 | int rep_count = 0; 16 | 17 | rv = apr_pool_create(&p, NULL); 18 | check(rv == APR_SUCCESS, "Failed to create pool"); 19 | 20 | va_start(argp, template); 21 | for (key = va_arg(argp, const char *); 22 | key != NULL; 23 | key = va_arg(argp, const char *)) 24 | { 25 | arg = va_arg(argp, const char *); 26 | 27 | for (i=0; template.args[i] != NULL; i++) 28 | { 29 | if (strcmp(template.args[i], key) == 0) 30 | { 31 | template.args[i] = arg; 32 | rep_count++; 33 | break; 34 | } 35 | } 36 | } 37 | 38 | check(template.rep_count == rep_count, "Failed to replace args. Wrong count"); 39 | 40 | rc = Shell_run(p, &template); 41 | apr_pool_destroy(p); 42 | va_end(argp); 43 | return rc; 44 | 45 | error: 46 | if(p) apr_pool_destroy(p); 47 | return rc; 48 | } 49 | 50 | int Shell_run(apr_pool_t *p, Shell *cmd) 51 | { 52 | apr_procattr_t *attr; 53 | apr_status_t rv; 54 | apr_proc_t newproc; 55 | 56 | rv = apr_procattr_create(&attr, p); 57 | check(rv == APR_SUCCESS, "Failed to create proc attr"); 58 | 59 | rv = apr_procattr_io_set(attr, APR_NO_PIPE, APR_NO_PIPE, APR_NO_PIPE); 60 | check(rv == APR_SUCCESS, "Failed to set IO of command"); 61 | 62 | rv = apr_procattr_dir_set(attr, cmd->dir); 63 | check(rv == APR_SUCCESS, "Failed to set root to %s", cmd->dir); 64 | 65 | rv = apr_procattr_cmdtype_set(attr, APR_PROGRAM_PATH); 66 | check(rv == APR_SUCCESS, "Failed to set cmd type"); 67 | 68 | rv = apr_proc_create(&newproc, cmd->exe, cmd->args, NULL, attr, p); 69 | check(rv == APR_SUCCESS, "Failed to run command"); 70 | 71 | rv = apr_proc_wait(&newproc, &cmd->exit_code, &cmd->exit_why, APR_WAIT); 72 | check(rv == APR_CHILD_DONE, "Failed to wait"); 73 | 74 | check(cmd->exit_code == 0, "%s exit badly", cmd->exe); 75 | check(cmd->exit_why == APR_PROC_EXIT, "%s was killed or crashed", cmd->exe); 76 | 77 | return 0; 78 | 79 | error: 80 | return -1; 81 | } 82 | 83 | Shell CLEANUP_SH = 84 | { 85 | .exe = "rm", 86 | .dir = "/tmp", 87 | .rep_count = 0, 88 | .args = {"rm", "-rf", "/tmp/pkg-build", "/tmp/pkg-src.tar.gz", 89 | "/tmp/pkg-src.tar.bz2", "/tmp/DEPENDS", NULL} 90 | }; 91 | 92 | Shell GIT_SH = 93 | { 94 | .exe = "git", 95 | .dir = "/tmp", 96 | .rep_count = 1, 97 | .args = {"git", "clone", "URL", "pkg-build", NULL} 98 | }; 99 | 100 | Shell TAR_SH = 101 | { 102 | .exe = "tar", 103 | .dir = "/tmp/pkg-build", 104 | .rep_count = 1, 105 | .args = {"tar", "-xzf", "FILE", "--strip-components", "1", NULL} 106 | }; 107 | 108 | Shell CURL_SH = 109 | { 110 | .exe = "curl", 111 | .dir = "/tmp", 112 | .rep_count = 2, 113 | .args = {"curl", "-L", "-o", "TARGET", "URL", NULL} 114 | }; 115 | 116 | Shell CONFIGURE_SH = 117 | { 118 | .exe = "./configure", 119 | .dir = "/tmp/pkg-build", 120 | .rep_count = 1, 121 | .args = {"configure", "OPTS", NULL} 122 | }; 123 | 124 | Shell MAKE_SH = 125 | { 126 | .exe = "make", 127 | .dir = "/tmp/pkg-build", 128 | .rep_count = 1, 129 | .args = {"make", "OPTS", NULL} 130 | }; 131 | 132 | Shell INSTALL_SH = 133 | { 134 | .exe = "sudo", 135 | .dir = "/tmp/pkg-build", 136 | .rep_count = 1, 137 | .args = {"sudo", "make", "TARGET", NULL} 138 | }; 139 | 140 | 141 | -------------------------------------------------------------------------------- /learncthehardway/devpkg/shell.h: -------------------------------------------------------------------------------- 1 | #ifndef _shell_h 2 | #define _shell_h 3 | 4 | #define MAX_COMMAND_ARGS 100 5 | 6 | #include 7 | 8 | typedef struct Shell 9 | { 10 | const char *dir; 11 | const char *exe; 12 | 13 | apr_procattr_t *attr; 14 | apr_proc_t proc; 15 | apr_exit_why_e exit_why; 16 | int exit_code; 17 | int rep_count; 18 | 19 | const char *args[MAX_COMMAND_ARGS]; 20 | } Shell; 21 | 22 | int Shell_run(apr_pool_t *p, Shell *cmd); 23 | int Shell_exec(Shell cmd, ...); 24 | 25 | extern Shell CLEANUP_SH; 26 | extern Shell GIT_SH; 27 | extern Shell TAR_SH; 28 | extern Shell CURL_SH; 29 | extern Shell CONFIGURE_SH; 30 | extern Shell MAKE_SH; 31 | extern Shell INSTALL_SH; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /learncthehardway/ex1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | puts("Hello world."); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /learncthehardway/ex10.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int i = 0; 6 | 7 | for (i=1; i 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int i = 0; 6 | 7 | while (i 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int i = 0; 6 | 7 | if (argc == 1) 8 | { 9 | printf("You only have one argument. You suck.\n"); 10 | } 11 | else if (argc > 1 && argc < 4) 12 | { 13 | printf("Here are your arguments:\n"); 14 | 15 | for (i=0; i 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | if (argc != 2) 6 | { 7 | printf("You need one argument.\n"); 8 | return 1; 9 | } 10 | 11 | int i = 0; 12 | for (i=0; argv[1][i] != '\0'; ++i) 13 | { 14 | char letter = argv[1][i]; 15 | 16 | switch(letter) 17 | { 18 | case 'a': 19 | case 'A': 20 | printf("%d: A\n", i); 21 | break; 22 | 23 | case 'e': 24 | case 'E': 25 | printf("%d: E\n", i); 26 | break; 27 | 28 | case 'i': 29 | case 'I': 30 | printf("%d: I\n", i); 31 | break; 32 | 33 | case 'o': 34 | case 'O': 35 | printf("%d: O\n", i); 36 | break; 37 | 38 | case 'u': 39 | case 'U': 40 | printf("%d: U\n", i); 41 | break; 42 | 43 | case 'y': 44 | case 'Y': 45 | if (i > 2) 46 | { 47 | printf("%d: Y\n", i); 48 | } 49 | else 50 | { 51 | printf("%d: %c is not a vowel\n", i, letter); 52 | } 53 | break; 54 | 55 | default: 56 | printf("%d: %c is not a vowel\n", i, letter); 57 | } 58 | } 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /learncthehardway/ex14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int can_print_it(char ch); 5 | void print_letters(char arg[]); 6 | 7 | void print_arguments(int argc, char *argv[]) 8 | { 9 | int i = 0; 10 | 11 | for (i=0; i 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int ages[] = {10, 20, 15, 18, 23}; 6 | char *names[] = { 7 | "Alan", "Frank", 8 | "John", "Lucy", "Tom" 9 | }; 10 | 11 | int count = sizeof(ages) / sizeof(int); 12 | int i = 0; 13 | 14 | for (i=0; i 2 | #include 3 | #include 4 | #include 5 | 6 | struct Person { 7 | char *name; 8 | int age; 9 | int height; 10 | int weight; 11 | }; 12 | 13 | struct Person *Person_create(char *name, int age, int height, int weight) 14 | { 15 | struct Person *who = (struct Person *)malloc(sizeof(struct Person)); 16 | assert(who != NULL); 17 | 18 | who->name = strdup(name); 19 | who->age = age; 20 | who->height = height; 21 | who->weight = weight; 22 | 23 | return who; 24 | } 25 | 26 | void Person_destroy(struct Person *who) 27 | { 28 | assert(who != NULL); 29 | 30 | free(who->name); 31 | free(who); 32 | } 33 | 34 | void Person_print(struct Person *who) 35 | { 36 | printf("Name: %s\n", who->name); 37 | printf("\tAge: %d\n", who->age); 38 | printf("\tHeight: %d\n", who->height); 39 | printf("\tWidth: %d\n", who->weight); 40 | } 41 | 42 | int main(int argc, char *argv[]) 43 | { 44 | struct Person *joe = Person_create( 45 | "Joe Alex", 32, 64, 140); 46 | struct Person *frank = Person_create( 47 | "Frank Blank", 20, 72, 180); 48 | 49 | printf("Joe is at memory location: %p.\n", joe); 50 | Person_print(joe); 51 | 52 | printf("Frank is at memory location: %p.\n", frank); 53 | Person_print(frank); 54 | 55 | joe->age += 20; 56 | joe->height -=2; 57 | joe->weight += 40; 58 | Person_print(joe); 59 | 60 | frank->age += 20; 61 | frank->weight += 20; 62 | Person_print(frank); 63 | 64 | Person_destroy(joe); 65 | Person_destroy(frank); 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /learncthehardway/ex18.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void die(const char *message) 7 | { 8 | if (errno) 9 | { 10 | perror(message); 11 | } 12 | else{ 13 | printf("ERROR: %s.\n", message); 14 | } 15 | 16 | exit(1); 17 | } 18 | 19 | typedef int (*compare_cb)(int a, int b); 20 | 21 | int *bubble_sort(int *numbers, int count, compare_cb cmp) 22 | { 23 | int temp = 0; 24 | int i = 0; 25 | int j = 0; 26 | int *target = malloc(count * sizeof(int)); 27 | 28 | if(!target) 29 | { 30 | die("Memory Error"); 31 | } 32 | 33 | memcpy(target, numbers, count * sizeof(int)); 34 | for (i=0; i 0) 39 | { 40 | temp = target[j+1]; 41 | target[j+1] = target[j]; 42 | target[j] = temp; 43 | } 44 | } 45 | } 46 | 47 | return target; 48 | } 49 | 50 | int sorted_order(int a, int b) 51 | { 52 | return a - b; 53 | } 54 | 55 | int reverse_order(int a, int b) 56 | { 57 | return b - a; 58 | } 59 | 60 | int strange_order(int a, int b) 61 | { 62 | if (a == 0 || b == 0) 63 | { 64 | return 0; 65 | } 66 | else 67 | { 68 | return a % b; 69 | } 70 | } 71 | 72 | void test_sorting(int *numbers, int count, compare_cb cmp) 73 | { 74 | int i = 0; 75 | int *sorted = bubble_sort(numbers, count, cmp); 76 | 77 | if(!sorted) 78 | { 79 | die("Failed to sort as requested"); 80 | } 81 | 82 | for (i=0; i 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | puts("Hello world."); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /learncthehardway/ex20.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dbg.h" 4 | 5 | void test_debug() 6 | { 7 | debug("I have brown hair."); 8 | 9 | debug("I am %d years old.", 26); 10 | } 11 | 12 | void test_log_err() 13 | { 14 | log_err("I believe everything is broken."); 15 | log_err("There are %d problems in %s.", 7, "space"); 16 | } 17 | 18 | void test_log_warn() 19 | { 20 | log_warn("You can safely ignore this."); 21 | log_warn("Maybe take a look at %s", "/etc/passwd"); 22 | } 23 | 24 | void test_log_info() 25 | { 26 | log_info("Well I did something mundane."); 27 | log_info("It happened %f times today.", 1.3f); 28 | } 29 | 30 | int test_check(char *file_name) 31 | { 32 | FILE *input = NULL; 33 | char *block = NULL; 34 | 35 | block = malloc(100); 36 | check_mem(block); 37 | 38 | input = fopen(file_name, "r"); 39 | check(input, "Failed to open %s.", file_name); 40 | 41 | free(block); 42 | fclose(input); 43 | return 0; 44 | 45 | error: 46 | if(block) free(block); 47 | if(input) fclose(input); 48 | return -1; 49 | } 50 | 51 | int test_sentinel(int code) 52 | { 53 | char *temp = malloc(100); 54 | check_mem(temp); 55 | 56 | switch(code) 57 | { 58 | case 1: 59 | log_info("It worked"); 60 | break; 61 | default: 62 | sentinel("I shouldn't run."); 63 | } 64 | 65 | free(temp); 66 | return 0; 67 | 68 | error: 69 | if(temp) free(temp); 70 | return -1; 71 | } 72 | 73 | int test_check_mem() 74 | { 75 | char *test = NULL; 76 | check_mem(test); 77 | 78 | free(test); 79 | return 1; 80 | 81 | error: 82 | return -1; 83 | } 84 | 85 | int test_check_debug() 86 | { 87 | int i = 0; 88 | check_debug(i != 0, "Oops. I am 0."); 89 | 90 | return 0; 91 | 92 | error: 93 | return -1; 94 | } 95 | 96 | int main(int argc, char *argv[]) 97 | { 98 | check(argc == 2, "Need one argument."); 99 | 100 | test_debug(); 101 | test_log_err(); 102 | test_log_warn(); 103 | test_log_info(); 104 | 105 | check(test_check("ex20.c") == 0, "failed with ex20.c"); 106 | check(test_check(argv[1]) == -1, "failed with argv"); 107 | check(test_sentinel(1) == 0, "test sentinel failed"); 108 | check(test_sentinel(100) == -1, "test sentinel failed"); 109 | check(test_check_mem() == -1, "test check mem failed"); 110 | check(test_check_debug() == -1, "test check debug failed"); 111 | 112 | return 0; 113 | 114 | error: 115 | return -1; 116 | } 117 | -------------------------------------------------------------------------------- /learncthehardway/ex22.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ex22.h" 3 | #include "dbg.h" 4 | 5 | int THE_SIZE = 1000; 6 | static int THE_AGE = 37; 7 | 8 | int get_age() 9 | { 10 | return THE_AGE; 11 | } 12 | 13 | void set_age(int age) 14 | { 15 | THE_AGE = age; 16 | } 17 | 18 | double update_ratio(double new_ratio) 19 | { 20 | static double ratio = 1.0; 21 | 22 | double old_ratio = ratio; 23 | ratio = new_ratio; 24 | 25 | return old_ratio; 26 | } 27 | 28 | void print_size() 29 | { 30 | log_info("I think the size is: %d", THE_SIZE); 31 | } 32 | -------------------------------------------------------------------------------- /learncthehardway/ex22.h: -------------------------------------------------------------------------------- 1 | #ifndef _ex22_h 2 | #define _ex22_h 3 | 4 | extern int THE_SIZE; 5 | 6 | int get_age(); 7 | void set_age(int age); 8 | 9 | double update_ratio(double ratio); 10 | 11 | void print_size(); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /learncthehardway/ex22_main.c: -------------------------------------------------------------------------------- 1 | #include "ex22.h" 2 | #include "dbg.h" 3 | 4 | const char *MY_NAME = "Zed A. Shaw"; 5 | 6 | void scope_demo(int count) 7 | { 8 | log_info("count is %d", count); 9 | 10 | if (count > 10) 11 | { 12 | int count = 100; 13 | log_info("count in this scope is %d", count); 14 | } 15 | 16 | log_info("count is at exit %d", count); 17 | 18 | count = 3000; 19 | 20 | log_info("count after assign %d", count); 21 | } 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | log_info("My name is %s, age %d", MY_NAME, get_age()); 26 | 27 | set_age(100); 28 | 29 | log_info("My age is now %d", get_age()); 30 | 31 | log_info("The size is %d", THE_SIZE); 32 | print_size(); 33 | 34 | THE_SIZE = 9; 35 | log_info("The size is now %d", THE_SIZE); 36 | print_size(); 37 | 38 | log_info("Ratio at first %f", update_ratio(2.0)); 39 | log_info("Ratio again %f", update_ratio(10.0)); 40 | log_info("Ratio once more %f", update_ratio(300.0)); 41 | 42 | int count = 4; 43 | scope_demo(count); 44 | scope_demo(count * 20); 45 | 46 | log_info("count after calling scope_demo %d", count); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /learncthehardway/ex23.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dbg.h" 4 | 5 | int normal_copy(char *from, char *to, int count) 6 | { 7 | int i = 0; 8 | 9 | for (i=0; i 0); 36 | } 37 | } 38 | 39 | return count; 40 | } 41 | 42 | int zeds_device(char *from, char *to, int count) 43 | { 44 | { 45 | int n = (count + 7) / 8; 46 | 47 | switch(count % 8) 48 | { 49 | case 0: 50 | again: *to++ = *from++; 51 | case 7: *to++ = *from++; 52 | case 6: *to++ = *from++; 53 | case 5: *to++ = *from++; 54 | case 4: *to++ = *from++; 55 | case 3: *to++ = *from++; 56 | case 2: *to++ = *from++; 57 | case 1: *to++ = *from++; 58 | if (--n > 0) goto again; 59 | } 60 | } 61 | 62 | return count; 63 | } 64 | 65 | int valid_copy(char *data, int count, char expects) 66 | { 67 | int i = 0; 68 | for (i=0; i 2 | #include "dbg.h" 3 | 4 | #define MAX_DATA 100 5 | 6 | typedef enum EyeColor 7 | { 8 | BLUE_EYES, GREEN_EYES, BROWN_EYES, 9 | BLACK_EYES, OTHER_EYES 10 | } EyeColor; 11 | 12 | const char *EYE_COLOR_NAMES[] = 13 | { 14 | "Blue", "Green", "Brown", "Black", "Other" 15 | }; 16 | 17 | typedef struct Person 18 | { 19 | int age; 20 | char first_name[MAX_DATA]; 21 | char last_name[MAX_DATA]; 22 | EyeColor eyes; 23 | float income; 24 | }Person; 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | Person you = {.age = 0}; 29 | int i = 0; 30 | char *in = NULL; 31 | 32 | printf("What's your first name?\n"); 33 | in = fgets(you.first_name, MAX_DATA - 1, stdin); 34 | check(in != NULL, "Failed to read first name."); 35 | 36 | printf("What's your last name?\n"); 37 | in = fgets(you.last_name, MAX_DATA - 1, stdin); 38 | check(in != NULL, "Failed to read last name"); 39 | 40 | printf("How old are you?\n"); 41 | int rc = fscanf(stdin, "%d", &you.age); 42 | check(rc > 0, "You have to enter a number"); 43 | 44 | printf("What color are your eyes?\n"); 45 | for (i=0; i<=OTHER_EYES; ++i) 46 | { 47 | printf("%d) %s\n", i+1, EYE_COLOR_NAMES[i]); 48 | } 49 | printf(">"); 50 | 51 | int eyes = -1; 52 | rc = fscanf(stdin, "%d", &eyes); 53 | check(rc > 0, "You have to enter a number"); 54 | 55 | you.eyes = eyes -1; 56 | check(you.eyes <= OTHER_EYES && you.eyes >= 0, "Do it right. That's not an option"); 57 | 58 | printf("How much do you make an hour?\n"); 59 | rc = fscanf(stdin, "%f", &you.income); 60 | check(rc > 0, "Enter a float point number"); 61 | 62 | printf("------RESULTS-----\n"); 63 | 64 | printf("First name: %s", you.first_name); 65 | printf("Last name: %s", you.last_name); 66 | printf("Age: %d\n", you.age); 67 | printf("Eyes: %s\n", EYE_COLOR_NAMES[you.eyes]); 68 | printf("Income: %f\n", you.income); 69 | 70 | return 0; 71 | 72 | error: 73 | return -1; 74 | } 75 | -------------------------------------------------------------------------------- /learncthehardway/ex25.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "dbg.h" 5 | 6 | #define MAX_DATA 100 7 | 8 | int read_string(char **out_string, int max_buffer) 9 | { 10 | *out_string = calloc(1, max_buffer + 1); 11 | check_mem(*out_string); 12 | 13 | char *result = fgets(*out_string, max_buffer, stdin); 14 | check(result != NULL, "Input error"); 15 | 16 | return 0; 17 | error: 18 | if (*out_string) free(*out_string); 19 | *out_string = NULL; 20 | return -1; 21 | } 22 | 23 | int read_int(int *out_int) 24 | { 25 | char *input = NULL; 26 | int rc = read_string(&input, MAX_DATA); 27 | check(rc == 0, "Failed to read number."); 28 | 29 | *out_int = atoi(input); 30 | free(input); 31 | return 0; 32 | error: 33 | if (input) free(input); 34 | return -1; 35 | } 36 | 37 | int read_scan(const char *fmt, ...) 38 | { 39 | int i = 0; 40 | int rc = 0; 41 | int *out_int = NULL; 42 | char *out_char = NULL; 43 | char **out_string = NULL; 44 | int max_buffer = 0; 45 | 46 | va_list argp; 47 | va_start(argp, fmt); 48 | 49 | for (i=0; fmt[i] != '\0'; ++i) 50 | { 51 | if (fmt[i] == '%') 52 | { 53 | i++; 54 | switch(fmt[i]) 55 | { 56 | case '\0': 57 | sentinel("Invalid format, you ended with %%"); 58 | break; 59 | 60 | case 'd': 61 | out_int = va_arg(argp, int *); 62 | rc = read_int(out_int); 63 | check(rc == 0, "Failed to read int"); 64 | break; 65 | 66 | case 'c': 67 | out_char = va_arg(argp, char *); 68 | *out_char = fgetc(stdin); 69 | break; 70 | 71 | case 's': 72 | max_buffer = va_arg(argp, int); 73 | out_string = va_arg(argp, char **); 74 | rc = read_string(out_string, max_buffer); 75 | check(rc == 0, "Failed to read string"); 76 | break; 77 | 78 | default: 79 | sentinel("Invalid format"); 80 | } 81 | } 82 | else 83 | { 84 | fgetc(stdin); 85 | } 86 | 87 | check(!feof(stdin) && !ferror(stdin), "Input error"); 88 | } 89 | 90 | va_end(argp); 91 | return 0; 92 | 93 | error: 94 | va_end(argp); 95 | return -1; 96 | } 97 | 98 | int main(int argc, char *argv[]) 99 | { 100 | char *first_name = NULL; 101 | char initial = ' '; 102 | char *last_name = NULL; 103 | int age = 0; 104 | 105 | printf("What's your first name? "); 106 | int rc = read_scan("%s", MAX_DATA, &first_name); 107 | check(rc == 0, "Failed first name"); 108 | 109 | printf("What's your initial? "); 110 | rc = read_scan("%c\n", &initial); 111 | check(rc == 0, "Failed initial"); 112 | 113 | printf("What's your last name? "); 114 | rc = read_scan("%s", MAX_DATA, &last_name); 115 | check(rc == 0, "Failed last name"); 116 | 117 | printf("How old are you? "); 118 | rc = read_scan("%d", &age); 119 | check(rc == 0, "Failed age"); 120 | 121 | printf("-----Results-----\n"); 122 | printf("First name: %s", first_name); 123 | printf("Initial: %c\n", initial); 124 | printf("Last name: %s", last_name); 125 | printf("Age:%d\n", age); 126 | 127 | free(first_name); 128 | free(last_name); 129 | return 0; 130 | 131 | error: 132 | return -1; 133 | } 134 | -------------------------------------------------------------------------------- /learncthehardway/ex26.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | cd /tmp 5 | curl -L -O http://archive.apache.org/dist/apr/apr-1.4.6.tar.gz 6 | tar -xzvf apr-1.4.6.tar.gz 7 | cd apr-1.4.6 8 | 9 | ./configure 10 | make 11 | sudo make install 12 | 13 | cd /tmp 14 | rm -rf apr-1.4.6 apr-1.4.6.tar.gz 15 | 16 | curl -L -O http://archive.apache.org/dist/apr/apr-util-1.4.1.tar.gz 17 | tar -xzvf apr-util-1.4.1.tar.gz 18 | cd apr-util-1.4.1 19 | 20 | ./configure --with-apr=/usr/local/apr 21 | make 22 | sudo make install 23 | 24 | cd /tmp 25 | rm -rf apr-util-1.4.1* apr-1.4.6* 26 | -------------------------------------------------------------------------------- /learncthehardway/ex27.c: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #include 3 | #include 4 | 5 | #include "dbg.h" 6 | 7 | void copy(char to[], char from[]) 8 | { 9 | int i = 0; 10 | 11 | while((to[i] = from[i]) != '\0') 12 | { 13 | i++; 14 | } 15 | } 16 | 17 | int safecopy(int from_len, char *from, int to_len, char *to) 18 | { 19 | assert(from != NULL && to != NULL && "from and to can't be NULL."); 20 | 21 | int i = 0; 22 | int max = from_len > to_len - 1 ? to_len - 1 : from_len; 23 | 24 | if (from_len < 0 || to_len <= 0) return -1; 25 | 26 | for (i=0; i 0, "Failed to safecopy."); 47 | check(to[to_len - 1] == '\0', "String not terminated"); 48 | 49 | debug("Result is '%s': %d", to, to_len); 50 | 51 | rc = safecopy(from_len * -1, from, to_len, to); 52 | check(rc == -1, "safecopy should fail."); 53 | check(to[to_len - 1] == '\0', "String not terminated"); 54 | 55 | rc = safecopy(from_len, from, 0, to); 56 | check(rc == -1, "safecopy should fail."); 57 | check(to[to_len - 1] == '\0', "String not terminated"); 58 | return 0; 59 | 60 | error: 61 | return -1; 62 | 63 | 64 | } 65 | 66 | 67 | -------------------------------------------------------------------------------- /learncthehardway/ex29.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dbg.h" 4 | 5 | typedef int (*lib_function)(const char *data); 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | int rc = 0; 10 | check(argc == 4, "USAGE: ex29 libex29.so funcname data"); 11 | 12 | char *lib_file = argv[1]; 13 | char *func_to_run = argv[2]; 14 | char *data = argv[3]; 15 | 16 | void *lib = dlopen(lib_file, RTLD_NOW); 17 | check(lib != NULL, "Failed to open the library %s: %s", lib_file, dlerror()); 18 | 19 | lib_function func = dlsym(lib, func_to_run); 20 | check(func != NULL, "Didn't find %s in the library %s: %s", func_to_run, lib_file, dlerror()); 21 | 22 | rc = func(data); 23 | check(rc == 0, "Function %s return %d for data %s", func_to_run, rc, data); 24 | 25 | rc = dlclose(lib); 26 | check(rc == 0, "Failed to close %s", lib_file); 27 | 28 | return 0; 29 | 30 | error: 31 | return 1; 32 | } 33 | -------------------------------------------------------------------------------- /learncthehardway/ex3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int age = 10; 6 | int height = 72; 7 | printf("I am %d years old.\n", age); 8 | printf("I am %d inches tall.\n", height); 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /learncthehardway/ex31.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int i = 0; 6 | 7 | while (i < 10000) 8 | { 9 | usleep(3000); 10 | } 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /learncthehardway/ex4.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int age = 10; 6 | int height; 7 | printf("I am %d years old.\n"); 8 | printf("I am %d inches tall.\n", height); 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /learncthehardway/ex6.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int distance = 100; 6 | float power = 2.345f; 7 | double super_power = 56789.4532; 8 | char initial = 'A'; 9 | char first_name[] = "Zed"; 10 | char last_name[] = "Shaw"; 11 | 12 | printf("You are %.5d miles away.\n", distance); 13 | printf("You have %.6f levels of power.\n", power); 14 | printf("You have %.3f awesome super powers.\n", super_power); 15 | printf("I have an initial %10c.\n", initial); 16 | printf("I have a first name %10s.\n", first_name); 17 | printf("I have a last name %10s.\n", last_name); 18 | printf("My whole name is %s.%c. %s.\n", first_name, initial, last_name); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /learncthehardway/ex7.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int bugs = 100; 6 | double bug_rate = 1.2; 7 | 8 | printf("You have %d bugs at the imaginary rate of %f.\n", bugs, bug_rate); 9 | 10 | long universe_of_defects = 1L * 1024L * 1024L * 1024L; 11 | printf("The entire universe has %ld bugs.\n", universe_of_defects); 12 | 13 | double expected_bugs = bugs * bug_rate; 14 | printf("You are expected to have %f bugs.\n", expected_bugs); 15 | 16 | double part_of_universe = expected_bugs / universe_of_defects; 17 | printf("This is only a %e portion of the universe.\n", part_of_universe); 18 | 19 | char nul_byte = '\0'; 20 | int care_percentage = bugs * nul_byte; 21 | printf("Which means you should care %d%%.\n", care_percentage); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /learncthehardway/ex8.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int areas[] = {10, 12, 13, 14, 20}; 6 | char name[] = "Zed"; 7 | char full_name[] = { 8 | 'Z', 'e', 'd', 9 | ' ', 'A', '.', ' ', 10 | 'S', 'h', 'a', 'w', '\0' 11 | }; 12 | 13 | printf("The size of an int: %ld.\n", sizeof(int)); 14 | printf("The size of areas (int[]): %ld.\n", sizeof(areas)); 15 | printf("The number of ints in areas: %ld.\n", sizeof(areas) / sizeof(int)); 16 | printf("The first area is %d, the 2nd %d.\n", areas[0], areas[1]); 17 | 18 | printf("The size of a char: %ld.\n", sizeof(char)); 19 | printf("The size of name (char[]): %ld.\n", sizeof(name)); 20 | printf("The number of chars in name: %ld.\n", sizeof(name) / sizeof(char)); 21 | 22 | printf("The size of full name: %ld.\n", sizeof(full_name)); 23 | printf("The number of chars in full name: %ld.\n", sizeof(full_name) / sizeof(char)); 24 | 25 | printf("name=\"%s\" and full_name=\"%s\".\n", name, full_name); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /learncthehardway/ex9.c: -------------------------------------------------------------------------------- 1 | # include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int numbers[4] = {0}; 6 | char name[4] = {'a'}; 7 | 8 | printf("numbers %d %d %d %d.\n", 9 | numbers[0], numbers[1], 10 | numbers[2], numbers[3]); 11 | 12 | printf("name each %c %c %c %c.\n", 13 | name[0], name[1], 14 | name[2], name[3]); 15 | 16 | printf("name %s.\n", name); 17 | 18 | numbers[0] = 1; 19 | numbers[1] = 2; 20 | numbers[2] = 3; 21 | numbers[3] = 4; 22 | 23 | name[0] = 'Z'; 24 | name[1] = 'e'; 25 | name[2] = 'd'; 26 | name[3] = '\0'; 27 | 28 | printf("numbers %d %d %d %d.\n", 29 | numbers[0], numbers[1], 30 | numbers[2], numbers[3]); 31 | 32 | printf("name each %c %c %c %c.\n", 33 | name[0], name[1], 34 | name[2], name[3]); 35 | 36 | printf("name %s.\n", name); 37 | 38 | char *another = "Zed"; 39 | 40 | printf("another each %c %c %c %c.\n", 41 | another[0], another[1], 42 | another[2], another[3]); 43 | 44 | printf("another %s.\n", another); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /learncthehardway/libex29.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dbg.h" 4 | 5 | int print_a_message(const char *msg) 6 | { 7 | printf("A STRING: %s\n", msg); 8 | 9 | return 0; 10 | } 11 | 12 | int uppercase(const char *msg) 13 | { 14 | int i = 0; 15 | 16 | for (i=0; msg[i] != '\0'; i++) 17 | { 18 | printf("%c", toupper(msg[i])); 19 | } 20 | 21 | printf("\n"); 22 | return 0; 23 | } 24 | 25 | int lowercase(const char *msg) 26 | { 27 | int i = 0; 28 | for (i=0; msg[i] != '\0'; i++) 29 | { 30 | printf("%c", tolower(msg[i])); 31 | } 32 | 33 | printf("\n"); 34 | return 0; 35 | } 36 | 37 | int fail_on_purpose(const char *msg) 38 | { 39 | return 1; 40 | } 41 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yubo1911/saber/aba4efee1afa10ef582f705fbd1d4d2a4829c413/learncthehardway/liblcthw/LICENSE -------------------------------------------------------------------------------- /learncthehardway/liblcthw/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -DNDEBUG $(OPTFLAGS) 2 | LDLIBS=-ldl -lm $(OPTLIBS) 3 | PREFIX?=/usr/local 4 | 5 | SOURCES=$(wildcard src/**/*.c src/*.c) 6 | OBJECTS=$(patsubst %.c,%.o,$(SOURCES)) 7 | 8 | TEST_SRC=$(wildcard tests/*_tests.c) 9 | TESTS=$(patsubst %.c,%,$(TEST_SRC)) 10 | 11 | PROGRAMS_SRC=$(wildcard bin/*.c) 12 | PROGRAMS=$(patsubst %.c,%,$(PROGRAMS_SRC)) 13 | 14 | TARGET=build/liblcthw.a 15 | SO_TARGET=$(patsubst %.a,%.so,$(TARGET)) 16 | 17 | all: $(TARGET) $(SO_TARGET) tests $(PROGRAMS) 18 | 19 | dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS) 20 | dev: all 21 | 22 | $(TARGET): CFLAGS += -fPIC 23 | $(TARGET): build $(OBJECTS) 24 | ar rcs $@ $(OBJECTS) 25 | ranlib $@ 26 | 27 | $(PROGRAMS): LDLIBS += $(TARGET) 28 | 29 | $(SO_TARGET): $(TARGET) $(OBJECTS) 30 | $(CC) -shared -o $@ $(OBJECTS) 31 | 32 | build: 33 | @mkdir -p build 34 | @mkdir -p bin 35 | 36 | .PHONY: tests 37 | tests: LDLIBS += $(TARGET) 38 | tests: $(TESTS) 39 | sh ./tests/runtests.sh 40 | 41 | valgrind: 42 | VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE) 43 | 44 | clean: 45 | rm -rf build $(OBJECTS) $(TESTS) $(PROGRAMS) 46 | rm -f tests/tests.log 47 | find . -name "*.gc*" -exec rm {} \; 48 | find . -name "cachegrind.out.*" -exec rm {} \; 49 | find . -name "callgrind.out.*" -exec rm {} \; 50 | rm -rf `find . -name "*.dSYM" -print` 51 | 52 | install: all 53 | install -d $(DESTDIR)/$(PREFIX)/lib/ 54 | install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/ 55 | 56 | BADFUNC='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)' 57 | check: 58 | @echo Files with potentially dangerous functions. 59 | @egrep $(BADFUNC) $(SOURCES) || true 60 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yubo1911/saber/aba4efee1afa10ef582f705fbd1d4d2a4829c413/learncthehardway/liblcthw/README.md -------------------------------------------------------------------------------- /learncthehardway/liblcthw/bin/urlor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | TSTree *add_route_data(TSTree *routes, bstring line) 5 | { 6 | struct bstrList *data = bsplit(line, ' '); 7 | check(data->qty == 2, "Line '%s' does not have 2 columns.", bdata(line)); 8 | 9 | routes = TSTree_insert(routes, bdata(data->entry[0]), blength(data->entry[0]), 10 | bstrcpy(data->entry[1])); 11 | 12 | bstrListDestroy(data); 13 | 14 | return routes; 15 | 16 | error: 17 | return NULL; 18 | } 19 | 20 | TSTree *load_routes(const char *file) 21 | { 22 | TSTree *routes = NULL; 23 | bstring line = NULL; 24 | FILE *routes_map = NULL; 25 | 26 | routes_map = fopen(file, "r"); 27 | check(routes_map != NULL, "Failed to open routes map: %s", file); 28 | 29 | while((line = bgets((bNgetc)fgetc, routes_map, '\n')) != NULL) 30 | { 31 | check(btrimws(line) == BSTR_OK, "Failed to trime line."); 32 | routes = add_route_data(routes, line); 33 | check(routes != NULL, "Failed to add route."); 34 | bdestroy(line); 35 | } 36 | 37 | fclose(routes_map); 38 | return routes; 39 | 40 | error: 41 | if(routes_map) fclose(routes_map); 42 | if(line) bdestroy(line); 43 | 44 | return NULL; 45 | } 46 | 47 | bstring match_url(TSTree *routes, bstring url) 48 | { 49 | bstring route = TSTree_search(routes, bdata(url), blength(url)); 50 | 51 | if(route == NULL) 52 | { 53 | printf("No exact match found. trying prefix.\n"); 54 | route = TSTree_search_prefix(routes, bdata(url), blength(url)); 55 | } 56 | 57 | return route; 58 | } 59 | 60 | bstring read_line(const char *prompt) 61 | { 62 | printf("%s", prompt); 63 | 64 | bstring result = bgets((bNgetc)fgetc, stdin, '\n'); 65 | check_debug(result != NULL, "stdin closed."); 66 | 67 | check(btrimws(result) == BSTR_OK, "Failed to trim."); 68 | 69 | return result; 70 | 71 | error: 72 | return NULL; 73 | } 74 | 75 | void bdestroy_cb(void *value, void *ignored) 76 | { 77 | (void)ignored; 78 | bdestroy((bstring)value); 79 | } 80 | 81 | void destroy_routes(TSTree *routes) 82 | { 83 | TSTree_traverse(routes, bdestroy_cb, NULL); 84 | TSTree_destroy(routes); 85 | } 86 | 87 | int main(int argc, char *argv[]) 88 | { 89 | bstring url = NULL; 90 | bstring route = NULL; 91 | check(argc == 2, "USAGE: urlor "); 92 | 93 | TSTree *routes = load_routes(argv[1]); 94 | check(routes != NULL, "Your route file has an error."); 95 | 96 | while(1) 97 | { 98 | url = read_line("URL> "); 99 | check_debug(url != NULL, "goodbye."); 100 | 101 | route = match_url(routes, url); 102 | 103 | if(route) 104 | { 105 | printf("MATCH %s == %s\n", bdata(url), bdata(route)); 106 | } 107 | else 108 | { 109 | printf("FAIL %s\n", bdata(url)); 110 | } 111 | 112 | bdestroy(url); 113 | } 114 | 115 | destroy_routes(routes); 116 | return 0; 117 | 118 | error: 119 | destroy_routes(routes); 120 | return 1; 121 | } 122 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/bstree.h: -------------------------------------------------------------------------------- 1 | #ifndef _lcthw_BSTree_h 2 | #define _lcthw_BSTree_h 3 | 4 | typedef int (*BSTree_compare)(void *a, void *b); 5 | 6 | typedef struct BSTreeNode 7 | { 8 | void *key; 9 | void *data; 10 | 11 | struct BSTreeNode *left; 12 | struct BSTreeNode *right; 13 | struct BSTreeNode *parent; 14 | } BSTreeNode; 15 | 16 | typedef struct BSTree 17 | { 18 | int count; 19 | BSTree_compare compare; 20 | BSTreeNode *root; 21 | } BSTree; 22 | 23 | typedef int (*BSTree_tranverse_cb)(BSTreeNode *node); 24 | 25 | BSTree *BSTree_create(BSTree_compare compare); 26 | void BSTree_destroy(BSTree *map); 27 | 28 | int BSTree_set(BSTree *map, void *key, void *data); 29 | void *BSTree_get(BSTree *map, void *key); 30 | 31 | int BSTree_tranverse(BSTree *map, BSTree_tranverse_cb tranverse_cb); 32 | 33 | void *BSTree_delete(BSTree *map, void *key); 34 | #endif 35 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/darray.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | DArray *DArray_create(size_t element_size, size_t initial_max) 5 | { 6 | DArray *array = malloc(sizeof(DArray)); 7 | check_mem(array); 8 | array->max = initial_max; 9 | check(array->max > 0, "You must set an initial_max > 0."); 10 | 11 | array->contents = calloc(initial_max, sizeof(void *)); 12 | check_mem(array->contents); 13 | 14 | array->end = 0; 15 | array->element_size = element_size; 16 | array->expand_rate = DEFAULT_EXPAND_RATE; 17 | 18 | return array; 19 | 20 | error: 21 | if(array) free(array); 22 | return NULL; 23 | } 24 | 25 | void DArray_clear(DArray *array) 26 | { 27 | int i = 0; 28 | if(array->element_size > 0) 29 | { 30 | for(i = 0; i < array->max; i++) 31 | { 32 | if(array->contents[i] != NULL) 33 | { 34 | free(array->contents[i]); 35 | } 36 | } 37 | } 38 | } 39 | 40 | static inline int DArray_resize(DArray *array, size_t newsize) 41 | { 42 | array->max = newsize; 43 | check(array->max > 0, "The newsize must be > 0."); 44 | 45 | void *contents = realloc(array->contents, array->max * sizeof(void *)); 46 | check_mem(contents); 47 | 48 | array->contents = contents; 49 | return 0; 50 | 51 | error: 52 | return -1; 53 | } 54 | 55 | int DArray_expand(DArray *array) 56 | { 57 | size_t old_max = array->max; 58 | check(DArray_resize(array, array->max + array->expand_rate) == 0, 59 | "Failed to expand array to new size: %d", 60 | array->max + (int)array->expand_rate); 61 | 62 | memset(array->contents + old_max, 0, array->expand_rate + 1); 63 | return 0; 64 | 65 | error: 66 | return -1; 67 | } 68 | 69 | int DArray_contract(DArray *array) 70 | { 71 | int new_size = array->end < (int)array->expand_rate ? (int)array->expand_rate : array->end; 72 | return DArray_resize(array, new_size + 1); 73 | } 74 | 75 | void DArray_destroy(DArray *array) 76 | { 77 | if(array) 78 | { 79 | if(array->contents) free(array->contents); 80 | free(array); 81 | } 82 | } 83 | void DArray_clear_and_destroy(DArray *array) 84 | { 85 | DArray_clear(array); 86 | DArray_destroy(array); 87 | } 88 | 89 | int DArray_push(DArray *array, void *el) 90 | { 91 | array->contents[array->end] = el; 92 | array->end++; 93 | 94 | if(DArray_end(array) >= DArray_max(array)) 95 | { 96 | return DArray_expand(array); 97 | } 98 | else 99 | { 100 | return 0; 101 | } 102 | } 103 | 104 | void *DArray_pop(DArray *array) 105 | { 106 | check(array->end - 1 >= 0, "Attempt to pop from empty array"); 107 | 108 | void *el = DArray_remove(array, array->end - 1); 109 | array->end--; 110 | 111 | if(DArray_end(array) > (int)array->expand_rate && DArray_end(array) % array->expand_rate) 112 | { 113 | DArray_contract(array); 114 | } 115 | 116 | return el; 117 | error: 118 | return NULL; 119 | } 120 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/darray.h: -------------------------------------------------------------------------------- 1 | #ifndef _DArray_h 2 | #define _DArray_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | typedef struct DArray 9 | { 10 | int end; 11 | int max; 12 | size_t element_size; 13 | size_t expand_rate; 14 | void **contents; 15 | } DArray; 16 | 17 | DArray *DArray_create(size_t element_size, size_t initial_max); 18 | 19 | void DArray_destroy(DArray *array); 20 | void DArray_clear(DArray *array); 21 | int DArray_expand(DArray *array); 22 | int DArray_contract(DArray *array); 23 | int DArray_push(DArray *array, void *el); 24 | void *DArray_pop(DArray *array); 25 | void DArray_clear_and_destroy(DArray *array); 26 | 27 | #define DArray_last(A) ((A)->contents[(A)->end - 1]) 28 | #define DArray_first(A) ((A)->contents[0]) 29 | #define DArray_end(A) ((A)->end) 30 | #define DArray_count(A) DArray_end(A) 31 | #define DArray_max(A) ((A)->max) 32 | 33 | #define DEFAULT_EXPAND_RATE 300 34 | 35 | static inline void DArray_set(DArray *array, int i, void *el) 36 | { 37 | check(i < array->max, "darray attempt to set past max."); 38 | if(i > array->end) array->end = i; 39 | array->contents[i] = el; 40 | 41 | error: 42 | return; 43 | } 44 | 45 | static inline void *DArray_get(DArray *array, int i) 46 | { 47 | check(i < array->max, "darray attempt to get past max."); 48 | return array->contents[i]; 49 | error: 50 | return NULL; 51 | } 52 | 53 | static inline void *DArray_remove(DArray *array, int i) 54 | { 55 | check(i < array->max, "darray attempt to remove past max."); 56 | void *el = array->contents[i]; 57 | array->contents[i] = NULL; 58 | 59 | return el; 60 | error: 61 | return NULL; 62 | } 63 | 64 | static inline void *DArray_new(DArray *array) 65 | { 66 | check(array->element_size > 0, "Can't use DArray_new on 0 size darrays."); 67 | 68 | return calloc(1, array->element_size); 69 | error: 70 | return NULL; 71 | } 72 | 73 | #define DArray_free(E) free((E)) 74 | #endif 75 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/darray_algos.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int DArray_qsort(DArray *array, DArray_compare cmp) 5 | { 6 | qsort(array->contents, DArray_count(array), sizeof(void *), cmp); 7 | return 0; 8 | } 9 | 10 | int DArray_heapsort(DArray *array, DArray_compare cmp) 11 | { 12 | //return heapsort(array->contents, DArray_count(array), sizeof(void *), cmp); 13 | //since no heapsort in stdlib.h of ubuntu 14.04, use qsort instead. 14 | qsort(array->contents, DArray_count(array), sizeof(void *), cmp); 15 | return 0; 16 | } 17 | 18 | int DArray_mergesort(DArray *array, DArray_compare cmp) 19 | { 20 | //return mergesort(array->contents, DArray_count(array), sizeof(void *), cmp); 21 | //since no heapsort in stdlib.h of ubuntu 14.04, use qsort instead. 22 | qsort(array->contents, DArray_count(array), sizeof(void *), cmp); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/darray_algos.h: -------------------------------------------------------------------------------- 1 | #ifndef darray_algos_h 2 | #undef darray_algos_h 3 | 4 | #include 5 | 6 | typedef int (*DArray_compare)(const void *a, const void *b); 7 | 8 | int DArray_qsort(DArray *array, DArray_compare cmp); 9 | 10 | int DArray_heapsort(DArray *array, DArray_compare cmp); 11 | 12 | int DArray_mergesort(DArray *array, DArray_compare cmp); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/dbg.h: -------------------------------------------------------------------------------- 1 | #ifndef _dbg_h 2 | #define _dbg_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define debug(M, ...) 10 | #else 11 | #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 17 | 18 | #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 21 | 22 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 23 | 24 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 25 | 26 | #define check_mem(A) check((A), "Out of memory.") 27 | 28 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/hashmap.h: -------------------------------------------------------------------------------- 1 | #ifndef _lcthw_Hashmap_h 2 | #define _lcthw_Hashmap_h 3 | 4 | #include 5 | #include 6 | 7 | #define DEFAULT_NUMBER_OF_BUCKETS 100 8 | 9 | typedef int (*Hashmap_compare)(void *a, void *b); 10 | typedef uint32_t(*Hashmap_hash)(void *key); 11 | 12 | typedef struct Hashmap 13 | { 14 | DArray *buckets; 15 | Hashmap_compare compare; 16 | Hashmap_hash hash; 17 | } Hashmap; 18 | 19 | typedef struct HashmapNode 20 | { 21 | void *key; 22 | void *data; 23 | uint32_t hash; 24 | } HashmapNode; 25 | 26 | typedef int (*Hashmap_traverse_cb)(HashmapNode *node); 27 | 28 | Hashmap *Hashmap_create(Hashmap_compare compare, Hashmap_hash); 29 | void Hashmap_destroy(Hashmap *map); 30 | 31 | int Hashmap_set(Hashmap *map, void *key, void *data); 32 | void *Hashmap_get(Hashmap *map, void *key); 33 | 34 | int Hashmap_traverse(Hashmap *map, Hashmap_traverse_cb traverse_cb); 35 | 36 | void *Hashmap_delete(Hashmap *map, void *key); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/hashmap_algos.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const uint32_t FNV_PRIME = 1677619; 5 | const uint32_t FNV_OFFSET_BASIS = 2166136261; 6 | 7 | uint32_t Hashmap_fnvla_hash(void *data) 8 | { 9 | bstring s = (bstring)data; 10 | uint32_t hash = FNV_OFFSET_BASIS; 11 | int i = 0; 12 | 13 | for(i = 0; i < blength(s); i++) 14 | { 15 | hash ^= bchare(s, i, 0); 16 | hash *= FNV_PRIME; 17 | } 18 | 19 | return hash; 20 | } 21 | 22 | const int MOD_ADLER = 65521; 23 | 24 | uint32_t Hashmap_adler32_hash(void *data) 25 | { 26 | bstring s = (bstring)data; 27 | uint32_t a = 1, b = 0; 28 | int i = 0; 29 | 30 | for(i = 0; i < blength(s); i++) 31 | { 32 | a = (a + bchare(s, i, 0)) % MOD_ADLER; 33 | b = (b + a) % MOD_ADLER; 34 | } 35 | 36 | return (b << 16) | a; 37 | } 38 | 39 | uint32_t Hashmap_djb_hash(void *data) 40 | { 41 | bstring s = (bstring)data; 42 | uint32_t hash = 5381; 43 | int i = 0; 44 | 45 | for(i = 0; i < blength(s); i++) 46 | { 47 | hash = ((hash << 5) + hash) + bchare(s, i, 0); 48 | } 49 | 50 | return hash; 51 | } 52 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/hashmap_algos.h: -------------------------------------------------------------------------------- 1 | #ifndef hashmap_algos_h 2 | #define hashmap_algos_h 3 | 4 | #include 5 | 6 | uint32_t Hashmap_fnvla_hash(void *data); 7 | 8 | uint32_t Hashmap_adler32_hash(void *data); 9 | 10 | uint32_t Hashmap_djb_hash(void *data); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | List *List_create() 5 | { 6 | return calloc(1, sizeof(List)); 7 | } 8 | 9 | void List_destroy(List *list) 10 | { 11 | LIST_FOREACH(list, first, next, cur) 12 | { 13 | if (cur->prev) 14 | { 15 | free(cur->prev); 16 | } 17 | } 18 | 19 | free(list->last); 20 | free(list); 21 | } 22 | 23 | void List_clear(List *list) 24 | { 25 | LIST_FOREACH(list, first, next, cur) 26 | { 27 | free(cur->value); 28 | } 29 | } 30 | 31 | void List_clear_destroy(List *list) 32 | { 33 | List_clear(list); 34 | List_destroy(list); 35 | } 36 | 37 | void List_push(List *list, void *value) 38 | { 39 | ListNode *node = calloc(1, sizeof(ListNode)); 40 | check_mem(node); 41 | 42 | node->value = value; 43 | 44 | if (list->last == NULL) 45 | { 46 | list->first = node; 47 | list->last = node; 48 | } 49 | else 50 | { 51 | list->last->next = node; 52 | node->prev = list->last; 53 | list->last = node; 54 | } 55 | list->count++; 56 | 57 | error: 58 | return; 59 | } 60 | 61 | void *List_pop(List *list) 62 | { 63 | ListNode *node = list->last; 64 | return node != NULL ? List_remove(list, node) : NULL; 65 | } 66 | 67 | void List_unshift(List *list, void *value) 68 | { 69 | ListNode *node = calloc(1, sizeof(ListNode)); 70 | check_mem(node); 71 | 72 | node->value = value; 73 | if (list->first == NULL) 74 | { 75 | list->first = node; 76 | list->last = node; 77 | } 78 | else 79 | { 80 | node->next = list->first; 81 | list->first->prev = node; 82 | list->first = node; 83 | } 84 | list->count++; 85 | 86 | error: 87 | return; 88 | } 89 | 90 | void *List_shift(List *list) 91 | { 92 | ListNode *node = list->first; 93 | return node != NULL ? List_remove(list, node) : NULL; 94 | } 95 | 96 | void *List_remove(List *list, ListNode *node) 97 | { 98 | void *result = NULL; 99 | 100 | check(list->first && list->last, "List is empty."); 101 | check(node, "node can't be NULL"); 102 | 103 | if (node == list->first && node == list->last) 104 | { 105 | list->first = NULL; 106 | list->last = NULL; 107 | } 108 | else if (node == list->first) 109 | { 110 | list->first = node->next; 111 | check(list->first != NULL, "Invalid list, somehow got a first that is NULL."); 112 | list->first->prev = NULL; 113 | } 114 | else if (node == list->last) 115 | { 116 | list->last = node->prev; 117 | check(list->last != NULL, "Invalid list, somehow got a last that is NULL."); 118 | list->last->next = NULL; 119 | } 120 | else 121 | { 122 | ListNode *after = node->next; 123 | ListNode *before = node->prev; 124 | after->prev = before; 125 | before->next = after; 126 | } 127 | 128 | list->count--; 129 | result = node->value; 130 | free(node); 131 | 132 | error: 133 | return result; 134 | } 135 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/list.h: -------------------------------------------------------------------------------- 1 | #ifndef lcthw_List_h 2 | #define lcthw_List_h 3 | 4 | #include 5 | 6 | struct ListNode; 7 | 8 | typedef struct ListNode 9 | { 10 | struct ListNode *next; 11 | struct ListNode *prev; 12 | void *value; 13 | } ListNode; 14 | 15 | typedef struct List 16 | { 17 | int count; 18 | ListNode *first; 19 | ListNode *last; 20 | } List; 21 | 22 | List *List_create(); 23 | void List_destroy(List *list); 24 | void List_clear(List *list); 25 | void List_clear_destroy(List *list); 26 | 27 | #define List_count(A) ((A)->count) 28 | #define List_first(A) ((A)->first != NULL ? (A)->first->value : NULL) 29 | #define List_last(A) ((A)->last != NULL ? (A)->last->value : NULL) 30 | 31 | void List_push(List *list, void *value); 32 | void *List_pop(List *list); 33 | 34 | void List_unshift(List *list, void *value); 35 | void *List_shift(List *list); 36 | 37 | void *List_remove(List *list, ListNode *node); 38 | 39 | #define LIST_FOREACH(L, S, M, V) ListNode *_node = NULL;\ 40 | ListNode *V = NULL;\ 41 | for(V = _node = L->S; _node != NULL; V = _node = _node->M) 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/list_algos.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void ListNode_swap(ListNode *a, ListNode *b) 5 | { 6 | void *tmp = a->value; 7 | a->value = b->value; 8 | b->value = tmp; 9 | } 10 | 11 | int List_bubble_sort(List *list, List_compare cmp) 12 | { 13 | int sorted = 0; 14 | 15 | if(List_count(list) <= 1) 16 | { 17 | return 0; 18 | } 19 | 20 | do 21 | { 22 | sorted = 1; 23 | LIST_FOREACH(list, first, next, cur) 24 | { 25 | if(cur->next) 26 | { 27 | if(cmp(cur->value, cur->next->value) > 0) 28 | { 29 | ListNode_swap(cur, cur->next); 30 | sorted = 0; 31 | } 32 | } 33 | } 34 | } while(!sorted); 35 | 36 | return 0; 37 | } 38 | 39 | List *List_merge(List *left, List *right, List_compare cmp) 40 | { 41 | List *result = List_create(); 42 | void *val = NULL; 43 | 44 | while(List_count(left) > 0 || List_count(right) > 0) 45 | { 46 | if(List_count(left) > 0 && List_count(right) > 0) 47 | { 48 | if(cmp(List_first(left), List_first(right)) <= 0) 49 | { 50 | val = List_shift(left); 51 | } 52 | else 53 | { 54 | val = List_shift(right); 55 | } 56 | List_push(result, val); 57 | } 58 | else if(List_count(left) > 0) 59 | { 60 | val = List_shift(left); 61 | List_push(result, val); 62 | } 63 | else if(List_count(right) > 0) 64 | { 65 | val = List_shift(right); 66 | List_push(result, val); 67 | } 68 | } 69 | 70 | return result; 71 | } 72 | 73 | List *List_merge_sort(List *list, List_compare cmp) 74 | { 75 | if(List_count(list) <= 1) 76 | { 77 | return list; 78 | } 79 | 80 | List *left = List_create(); 81 | List *right = List_create(); 82 | int middle = List_count(list) / 2; 83 | 84 | LIST_FOREACH(list, first, next, cur) 85 | { 86 | if(middle > 0) 87 | { 88 | List_push(left, cur->value); 89 | } 90 | else 91 | { 92 | List_push(right, cur->value); 93 | } 94 | middle--; 95 | } 96 | 97 | List *sort_left = List_merge_sort(left, cmp); 98 | List *sort_right = List_merge_sort(right, cmp); 99 | 100 | if(sort_left != left) List_destroy(left); 101 | if(sort_right != right) List_destroy(right); 102 | 103 | return List_merge(sort_left, sort_right, cmp); 104 | } 105 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/list_algos.h: -------------------------------------------------------------------------------- 1 | #ifndef list_algos_h 2 | #define list_algos_h 3 | 4 | #include 5 | 6 | typedef int (*List_compare)(const void *a, const void *b); 7 | 8 | int List_bubble_sort(List *list, List_compare cmp); 9 | List *List_merge_sort(List *list, List_compare cmp); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef lcthw_Queue_h 2 | #define lcthw_Queue_h 3 | #include 4 | 5 | typedef struct Queue 6 | { 7 | List *list; 8 | } Queue; 9 | 10 | Queue *Queue_create() 11 | { 12 | Queue *queue = calloc(1, sizeof(Queue)); 13 | queue->list = List_create(); 14 | return queue; 15 | } 16 | 17 | void Queue_destroy(Queue *queue) 18 | { 19 | List_destroy(queue->list); 20 | free(queue); 21 | } 22 | 23 | void Queue_send(Queue *queue, void *value) 24 | { 25 | List_push(queue->list, value); 26 | } 27 | 28 | void *Queue_peek(Queue *queue) 29 | { 30 | return List_last(queue->list); 31 | } 32 | 33 | void *Queue_recv(Queue *queue) 34 | { 35 | return List_shift(queue->list); 36 | } 37 | 38 | #define Queue_count(A) (List_count(A->list)) 39 | 40 | #define QUEUE_FOREACH(Q, C) LIST_FOREACH((Q)->list, first, next, C) 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/radixmap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | RadixMap *RadixMap_create(size_t max) 8 | { 9 | RadixMap *map = calloc(sizeof(RadixMap), 1); 10 | check_mem(map); 11 | 12 | map->contents = calloc(sizeof(RMElement), max + 1); 13 | check_mem(map->contents); 14 | 15 | map->temp = calloc(sizeof(RMElement), max + 1); 16 | check_mem(map->temp); 17 | 18 | map->max = max; 19 | map->end = 0; 20 | 21 | return map; 22 | error: 23 | return NULL; 24 | } 25 | 26 | void RadixMap_destroy(RadixMap *map) 27 | { 28 | if(map) 29 | { 30 | free(map->contents); 31 | free(map->temp); 32 | free(map); 33 | } 34 | } 35 | 36 | #define ByteOf(x, y) (((uint8_t *)x)[(y)]) 37 | 38 | static inline void radix_sort(short offset, uint64_t max, uint64_t *source, uint64_t *dest) 39 | { 40 | uint64_t count[256] = {0}; 41 | uint64_t *cp = NULL; 42 | uint64_t *sp = NULL; 43 | uint64_t *end = NULL; 44 | uint64_t s = 0; 45 | uint64_t c = 0; 46 | 47 | for(sp = source, end = source + max; sp < end; sp++) 48 | { 49 | count[ByteOf(sp, offset)]++; 50 | } 51 | 52 | for(s = 0, cp = count, end = count + 256; cp < end; cp++) 53 | { 54 | c = *cp; 55 | *cp = s; 56 | s += c; 57 | } 58 | 59 | for(sp = source, end = source + max; sp < end; sp++) 60 | { 61 | cp = count + ByteOf(sp, offset); 62 | dest[*cp] = *sp; 63 | ++(*cp); 64 | } 65 | } 66 | 67 | void RadixMap_sort(RadixMap *map) 68 | { 69 | uint64_t *source = &map->contents[0].raw; 70 | uint64_t *temp = &map->temp[0].raw; 71 | 72 | radix_sort(0, map->end, source, temp); 73 | radix_sort(1, map->end, temp, source); 74 | radix_sort(2, map->end, source, temp); 75 | radix_sort(3, map->end, temp, source); 76 | } 77 | 78 | RMElement *RadixMap_find(RadixMap *map, uint32_t to_find) 79 | { 80 | int low = 0; 81 | int high = map->end - 1; 82 | RMElement *data = map->contents; 83 | 84 | while(low <= high) 85 | { 86 | int middle = low + (high - low) / 2; 87 | uint32_t key = data[middle].data.key; 88 | 89 | if(to_find < key) 90 | { 91 | high = middle - 1; 92 | } 93 | else if(to_find > key) 94 | { 95 | low = middle + 1; 96 | } 97 | else 98 | { 99 | return &data[middle]; 100 | } 101 | } 102 | 103 | return NULL; 104 | } 105 | 106 | int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value) 107 | { 108 | check(key < UINT32_MAX, "Key can't be equal to UINT32_MAX."); 109 | 110 | RMElement element = {.data = {.key = key, .value = value}}; 111 | check(map->end + 1 < map->max, "RadixMap is full."); 112 | 113 | map->contents[map->end++] = element; 114 | 115 | RadixMap_sort(map); 116 | 117 | return 0; 118 | 119 | error: 120 | return -1; 121 | } 122 | 123 | int RadixMap_delete(RadixMap *map, RMElement *el) 124 | { 125 | check(map->end > 0, "There is nothing to delete."); 126 | check(el != NULL, "Can't delete a NULL element."); 127 | 128 | el->data.key = UINT32_MAX; 129 | 130 | if(map->end > 1) 131 | { 132 | RadixMap_sort(map); 133 | } 134 | 135 | map->end--; 136 | 137 | return 0; 138 | error: 139 | return -1; 140 | } 141 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/radixmap.h: -------------------------------------------------------------------------------- 1 | #ifndef _radixmap_h 2 | #define _radixmap_h 3 | 4 | #include 5 | 6 | typedef union RMElement 7 | { 8 | uint64_t raw; 9 | struct 10 | { 11 | uint32_t key; 12 | uint32_t value; 13 | } data; 14 | } RMElement; 15 | 16 | typedef struct RadixMap 17 | { 18 | size_t max; 19 | size_t end; 20 | uint32_t counter; 21 | RMElement *contents; 22 | RMElement *temp; 23 | } RadixMap; 24 | 25 | RadixMap *RadixMap_create(size_t max); 26 | 27 | void RadixMap_destroy(RadixMap *map); 28 | 29 | void RadixMap_sort(RadixMap *map); 30 | 31 | RMElement *RadixMap_find(RadixMap *map, uint32_t key); 32 | 33 | int RadixMap_add(RadixMap *map, uint32_t key, uint32_t value); 34 | 35 | int RadixMap_delete(RadixMap *map, RMElement *el); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/ringbuffer.c: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | RingBuffer *RingBuffer_create(int length) 10 | { 11 | RingBuffer *buffer = calloc(1, sizeof(RingBuffer)); 12 | buffer->length = length + 1; 13 | buffer->start = 0; 14 | buffer->end = 0; 15 | buffer->buffer = calloc(buffer->length, 1); 16 | 17 | return buffer; 18 | } 19 | 20 | void RingBuffer_destroy(RingBuffer *buffer) 21 | { 22 | if(buffer) 23 | { 24 | free(buffer->buffer); 25 | free(buffer); 26 | } 27 | } 28 | 29 | int RingBuffer_write(RingBuffer *buffer, char *data, int length) 30 | { 31 | if(RingBuffer_available_data(buffer) == 0) 32 | { 33 | buffer->start = buffer->end = 0; 34 | } 35 | 36 | check(length <= RingBuffer_available_space(buffer), 37 | "Not enough space: %d request, %d available", 38 | length, RingBuffer_available_data(buffer)); 39 | 40 | void *result = memcpy(RingBuffer_ends_at(buffer), data, length); 41 | check(result != NULL, "Failed to write data into buffer."); 42 | 43 | RingBuffer_commit_write(buffer, length); 44 | 45 | return length; 46 | 47 | error: 48 | return -1; 49 | } 50 | 51 | int RingBuffer_read(RingBuffer *buffer, char *target, int amount) 52 | { 53 | check_debug(amount <= RingBuffer_available_data(buffer), 54 | "Not enough in the buffer: has %d, needs %d", 55 | RingBuffer_available_data(buffer), amount); 56 | void *result = memcpy(target, RingBuffer_starts_at(buffer), amount); 57 | check(result != NULL, "Failed to read buffer into data."); 58 | 59 | RingBuffer_commit_read(buffer, amount); 60 | 61 | if(buffer->end == buffer->start) 62 | { 63 | buffer->start = buffer->end = 0; 64 | } 65 | 66 | return amount; 67 | error: 68 | return -1; 69 | } 70 | 71 | bstring RingBuffer_gets(RingBuffer *buffer, int amount) 72 | { 73 | check(amount > 0, "Need more than 0 for gets, you gave %d", amount); 74 | check_debug(amount <= RingBuffer_available_data(buffer), 75 | "Not enough in the buffer."); 76 | 77 | bstring result = blk2bstr(RingBuffer_starts_at(buffer), amount); 78 | check(result != NULL, "Failed to create gets result."); 79 | check(blength(result) == amount, "Wrong result length."); 80 | 81 | RingBuffer_commit_read(buffer, amount); 82 | assert(RingBuffer_available_data(buffer) >= 0 && "Error in read commit."); 83 | 84 | return result; 85 | error: 86 | return NULL; 87 | } 88 | 89 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/ringbuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef _lcthw_RingBuffer_h 2 | #define _lcthw_RingBuffer_h 3 | 4 | #include 5 | 6 | typedef struct 7 | { 8 | char *buffer; 9 | int length; 10 | int start; 11 | int end; 12 | } RingBuffer; 13 | 14 | RingBuffer *RingBuffer_create(int length); 15 | 16 | void RingBuffer_destroy(RingBuffer *buffer); 17 | 18 | int RingBuffer_read(RingBuffer *buffer, char *target, int amount); 19 | 20 | int RingBuffer_write(RingBuffer *buffer, char *data, int length); 21 | 22 | int RingBuffer_empty(RingBuffer *buffer); 23 | 24 | int RingBuffer_full(RingBuffer *buffer); 25 | 26 | int RingBuffer_available_data(RingBuffer *buffer); 27 | 28 | int RingBuffer_available_space(RingBuffer *buffer); 29 | 30 | bstring RingBuffer_gets(RingBuffer *buffer, int amount); 31 | 32 | #define RingBuffer_available_data(B) (((B)->end + 1) % (B)->length - (B)->start - 1) 33 | 34 | #define RingBuffer_available_space(B) ((B)->length - (B)->end - 1) 35 | 36 | #define RingBuffer_full(B) (RingBuffer_available_data((B)) - (B)->length == 0) 37 | 38 | #define RingBuffer_empty(B) (RingBuffer_available_data((B)) == 0) 39 | 40 | #define RingBuffer_puts(B, D) RingBuffer_write((B), bdata((D), blength(D))) 41 | 42 | #define RingBuffer_get_all(B) RingBuffer_gets((B), RingBuffer_available_data((B))) 43 | 44 | #define RingBuffer_starts_at(B) ((B)->buffer + (B)->start) 45 | 46 | #define RingBuffer_ends_at(B) ((B)->buffer + (B)->end) 47 | 48 | #define RingBuffer_commit_read(B, A) ((B)->start = ((B)->start + (A)) % (B)->length) 49 | 50 | #define RingBuffer_commit_write(B, A) ((B)->end = ((B)->end + (A)) % (B)->length) 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/stack.h: -------------------------------------------------------------------------------- 1 | #ifndef lcthw_Stack_h 2 | #define lcthw_Stack_h 3 | #include 4 | 5 | typedef struct Stack 6 | { 7 | List *list; 8 | } Stack; 9 | 10 | Stack *Stack_create() 11 | { 12 | Stack *stack = calloc(1, sizeof(Stack)); 13 | stack->list = List_create(); 14 | return stack; 15 | } 16 | 17 | void Stack_destroy(Stack *stack) 18 | { 19 | List_destroy(stack->list); 20 | free(stack); 21 | } 22 | 23 | void Stack_push(Stack *stack, void *value) 24 | { 25 | List_push(stack->list, value); 26 | } 27 | 28 | void *Stack_peek(Stack *stack) 29 | { 30 | return List_last(stack->list); 31 | } 32 | 33 | void *Stack_pop(Stack *stack) 34 | { 35 | return List_pop(stack->list); 36 | } 37 | 38 | #define Stack_count(A) (List_count(A->list)) 39 | 40 | #define STACK_FOREACH(S, C) LIST_FOREACH((S)->list, first, next, C) 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/stats.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | Stats *Stats_recreate(double sum, double sumsq, unsigned long n, double min, double max) 7 | { 8 | Stats *st = malloc(sizeof(Stats)); 9 | check_mem(st); 10 | 11 | st->sum = sum; 12 | st->sumsq = sumsq; 13 | st->n = n; 14 | st->min = min; 15 | st->max = max; 16 | 17 | return st; 18 | 19 | error: 20 | return NULL; 21 | } 22 | 23 | Stats *Stats_create() 24 | { 25 | return Stats_recreate(0.0, 0.0, 0L, 0.0, 0.0); 26 | } 27 | 28 | double Stats_mean(Stats *st) 29 | { 30 | return st->sum / st->n; 31 | } 32 | 33 | double Stats_stddev(Stats *st) 34 | { 35 | return sqrt((st->sumsq - (st->sum * st->sum / st->n)) / (st->n - 1)); 36 | } 37 | 38 | void Stats_sample(Stats *st, double s) 39 | { 40 | st->sum += s; 41 | st->sumsq += s * s; 42 | 43 | if(st->n == 0) 44 | { 45 | st->min = s; 46 | st->max = s; 47 | } 48 | else 49 | { 50 | if(st->min > s) st->min = s; 51 | if(st->max < s) st->max = s; 52 | } 53 | 54 | st->n += 1; 55 | } 56 | 57 | void Stats_dump(Stats *st) 58 | { 59 | fprintf(stderr, "sum:%f, sumsq:%f, n:%ld, min:%f, max:%f, mean:%f, stddev:%f", 60 | st->sum, st->sumsq, st->n, st->min, st->max, 61 | Stats_mean(st), Stats_stddev(st)); 62 | } 63 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/stats.h: -------------------------------------------------------------------------------- 1 | #ifndef lcthw_stats_h 2 | #define lcthw_stats_h 3 | 4 | typedef struct Stats 5 | { 6 | double sum; 7 | double sumsq; 8 | unsigned long n; 9 | double min; 10 | double max; 11 | } Stats; 12 | 13 | Stats *Stats_recreate(double sum, double sumsq, unsigned long n, double min, double max); 14 | 15 | Stats *Stats_create(); 16 | 17 | double Stats_mean(Stats *st); 18 | 19 | double Stats_stddev(Stats *st); 20 | 21 | void Stats_sample(Stats *st, double s); 22 | 23 | void Stats_dump(Stats *st); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/string_algos.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static inline void String_setup_skip_chars( 5 | size_t *skip_chars, 6 | const unsigned char *needle, ssize_t nlen) 7 | { 8 | size_t i = 0; 9 | size_t last = nlen - 1; 10 | 11 | for(i = 0; i < UCHAR_MAX + 1; i++) 12 | { 13 | skip_chars[i] = nlen; 14 | } 15 | 16 | for(i = 0; i < last; i++) 17 | { 18 | skip_chars[needle[i]] = last - i; 19 | } 20 | } 21 | 22 | static inline const unsigned char *String_base_search( 23 | const unsigned char *haystack, ssize_t hlen, 24 | const unsigned char *needle, ssize_t nlen, 25 | size_t *skip_chars) 26 | { 27 | size_t i = 0; 28 | size_t last = nlen - 1; 29 | 30 | assert(haystack != NULL && "Given bad haystack to search"); 31 | assert(needle != NULL && "Given bad needle to search for."); 32 | 33 | check(nlen > 0, "nlen can't be <= 0."); 34 | check(hlen > 0, "hlen can't be <= 0."); 35 | 36 | while(hlen >= nlen) 37 | { 38 | for(i = last; haystack[i] == needle[i]; i--) 39 | { 40 | if(i == 0) 41 | { 42 | return haystack; 43 | } 44 | } 45 | 46 | hlen -= skip_chars[haystack[last]]; 47 | haystack += skip_chars[haystack[last]]; 48 | } 49 | 50 | error: 51 | return NULL; 52 | } 53 | 54 | int String_find(bstring in, bstring what) 55 | { 56 | const unsigned char *found = NULL; 57 | 58 | const unsigned char *haystack = (const unsigned char *)bdata(in); 59 | ssize_t hlen = blength(in); 60 | const unsigned char *needle = (const unsigned char *)bdata(what); 61 | ssize_t nlen = blength(what); 62 | size_t skip_chars[UCHAR_MAX + 1] = {0}; 63 | 64 | String_setup_skip_chars(skip_chars, needle, nlen); 65 | 66 | found = String_base_search(haystack, hlen, needle, nlen, skip_chars); 67 | 68 | return found != NULL ? found - haystack : -1; 69 | } 70 | 71 | StringScanner *StringScanner_create(bstring in) 72 | { 73 | StringScanner *scan = calloc(1, sizeof(StringScanner)); 74 | check_mem(scan); 75 | 76 | scan->in = in; 77 | scan->haystack = (const unsigned char *)bdata(in); 78 | scan->hlen = blength(in); 79 | 80 | assert(scan != NULL && "fuck"); 81 | return scan; 82 | error: 83 | free(scan); 84 | return NULL; 85 | } 86 | 87 | static inline void StringScanner_set_needle(StringScanner *scan, bstring tofind) 88 | { 89 | scan->needle = (const unsigned char *)bdata(tofind); 90 | scan->nlen = blength(tofind); 91 | 92 | String_setup_skip_chars(scan->skip_chars, scan->needle, scan->nlen); 93 | } 94 | 95 | static inline void StringScanner_reset(StringScanner *scan) 96 | { 97 | scan->haystack = (const unsigned char *)bdata(scan->in); 98 | scan->hlen = blength(scan->in); 99 | } 100 | 101 | int StringScanner_scan(StringScanner *scan, bstring tofind) 102 | { 103 | const unsigned char *found = NULL; 104 | ssize_t found_at = 0; 105 | 106 | if(scan->hlen <= 0) 107 | { 108 | StringScanner_reset(scan); 109 | return -1; 110 | } 111 | 112 | if((const unsigned char *)bdata(tofind) != scan->needle) 113 | { 114 | StringScanner_set_needle(scan, tofind); 115 | } 116 | 117 | found = String_base_search( 118 | scan->haystack, scan->hlen, 119 | scan->needle, scan->nlen, 120 | scan->skip_chars); 121 | 122 | if(found) 123 | { 124 | found_at = found - (const unsigned char *)bdata(scan->in); 125 | scan->haystack = found + scan->nlen; 126 | scan->hlen -= found_at - scan->nlen; 127 | } 128 | else 129 | { 130 | StringScanner_reset(scan); 131 | found_at = -1; 132 | } 133 | 134 | return found_at; 135 | } 136 | 137 | void StringScanner_destroy(StringScanner *scan) 138 | { 139 | if(scan) free(scan); 140 | } 141 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/string_algos.h: -------------------------------------------------------------------------------- 1 | #ifndef string_algos_h 2 | #define string_algos_h 3 | 4 | #include 5 | #include 6 | 7 | typedef struct StringScanner 8 | { 9 | bstring in; 10 | const unsigned char *haystack; 11 | ssize_t hlen; 12 | const unsigned char *needle; 13 | ssize_t nlen; 14 | size_t skip_chars[UCHAR_MAX + 1]; 15 | } StringScanner; 16 | 17 | int String_find(bstring in, bstring what); 18 | 19 | StringScanner *StringScanner_create(bstring in); 20 | 21 | int StringScanner_scan(StringScanner *scan, bstring tofind); 22 | 23 | void StringScanner_destroy(StringScanner *scan); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/tstree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | static inline TSTree *TSTree_insert_base(TSTree *root, TSTree *node, 8 | const char *key, size_t len, void *value) 9 | { 10 | if(node == NULL) 11 | { 12 | node = (TSTree *)calloc(1, sizeof(TSTree)); 13 | 14 | if(root == NULL) 15 | { 16 | root = node; 17 | } 18 | 19 | node->splitchar = *key; 20 | } 21 | 22 | if(*key < node->splitchar) 23 | { 24 | node->low = TSTree_insert_base(root, node->low, key, len, value); 25 | } 26 | else if(*key == node->splitchar) 27 | { 28 | if(len > 1) 29 | { 30 | node->equal = TSTree_insert_base(root, node->equal, key + 1, len - 1, value); 31 | } 32 | else 33 | { 34 | assert(node->value == NULL && "Duplicate insert to tst."); 35 | node->value = value; 36 | } 37 | } 38 | else 39 | { 40 | node->high = TSTree_insert_base(root, node->high, key, len, value); 41 | } 42 | 43 | return node; 44 | } 45 | 46 | TSTree *TSTree_insert(TSTree *node, const char *key, size_t len, void *value) 47 | { 48 | return TSTree_insert_base(node, node, key, len, value); 49 | } 50 | 51 | void *TSTree_search(TSTree *root, const char *key, size_t len) 52 | { 53 | TSTree *node = root; 54 | size_t i = 0; 55 | 56 | while(i < len && node) 57 | { 58 | if(key[i] < node->splitchar) 59 | { 60 | node = node->low; 61 | } 62 | else if(key[i] == node->splitchar) 63 | { 64 | i++; 65 | if(i < len) node = node->equal; 66 | } 67 | else 68 | { 69 | node = node->high; 70 | } 71 | } 72 | 73 | if(node) 74 | { 75 | return node->value; 76 | } 77 | else 78 | { 79 | return NULL; 80 | } 81 | } 82 | 83 | void *TSTree_search_prefix(TSTree *root, const char *key, size_t len) 84 | { 85 | if(len == 0) return NULL; 86 | 87 | TSTree *node = root; 88 | TSTree *last = NULL; 89 | size_t i = 0; 90 | 91 | while(i < len && node) 92 | { 93 | if(key[i] splitchar) 94 | { 95 | node = node->low; 96 | } 97 | else if(key[i] == node->splitchar) 98 | { 99 | i++; 100 | if(i < len) 101 | { 102 | if(node->value) last = node; 103 | node = node->equal; 104 | } 105 | } 106 | else 107 | { 108 | node = node->high; 109 | } 110 | } 111 | 112 | node = node ? node : last; 113 | 114 | while(node && !node->value) 115 | { 116 | node = node->equal; 117 | } 118 | 119 | return node ? node->value : NULL; 120 | } 121 | 122 | void TSTree_traverse(TSTree *node, TSTree_traverse_cb cb, void *data) 123 | { 124 | if(!node) return; 125 | 126 | if(node->low) TSTree_traverse(node->low, cb, data); 127 | 128 | if(node->equal) TSTree_traverse(node->equal, cb, data); 129 | 130 | if(node->high) TSTree_traverse(node->high, cb, data); 131 | 132 | if(node->value) cb(node->value, data); 133 | } 134 | 135 | void TSTree_destroy(TSTree *node) 136 | { 137 | if(node == NULL) return; 138 | 139 | if(node->low) TSTree_destroy(node->low); 140 | 141 | if(node->equal) TSTree_destroy(node->equal); 142 | 143 | if(node->high) TSTree_destroy(node->high); 144 | 145 | free(node); 146 | } 147 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/src/lcthw/tstree.h: -------------------------------------------------------------------------------- 1 | #ifndef _lcthw_TSTree_h 2 | #define _lcthw_TSTree_h 3 | 4 | #include 5 | #include 6 | 7 | typedef struct TSTree 8 | { 9 | char splitchar; 10 | struct TSTree *low; 11 | struct TSTree *equal; 12 | struct TSTree *high; 13 | void *value; 14 | } TSTree; 15 | 16 | void *TSTree_search(TSTree *root, const char *key, size_t len); 17 | 18 | void *TSTree_search_prefix(TSTree *root, const char *key, size_t len); 19 | 20 | typedef void (*TSTree_traverse_cb)(void *value, void *data); 21 | 22 | TSTree *TSTree_insert(TSTree *node, const char *key, size_t len, void *value); 23 | 24 | void TSTree_traverse(TSTree *node, TSTree_traverse_cb cb, void *data); 25 | 26 | void TSTree_destroy(TSTree *root); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/darray_algos_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | 4 | int testcmp(char **a, char **b) 5 | { 6 | return strcmp(*a, *b); 7 | } 8 | 9 | DArray *create_words() 10 | { 11 | DArray *result = DArray_create(0, 5); 12 | char *words[] = {"asfdasfd", "werwar", "13234", "asfdasfd", "oioj"}; 13 | int i = 0; 14 | 15 | for(i = 0; i < 5; i++) 16 | { 17 | DArray_push(result, words[i]); 18 | } 19 | 20 | return result; 21 | } 22 | 23 | int is_sorted(DArray *array) 24 | { 25 | int i = 0; 26 | for(i = 0; i < DArray_count(array) - 1; i++) 27 | { 28 | if(strcmp(DArray_get(array, i), DArray_get(array, i+1)) > 0) 29 | { 30 | return 0; 31 | } 32 | } 33 | 34 | return 1; 35 | } 36 | 37 | char *run_sort_test(int (*func)(DArray *, DArray_compare), const char *name) 38 | { 39 | DArray *words = create_words(); 40 | mu_assert(!is_sorted(words), "Words should start not sorted."); 41 | 42 | debug("---Testing %s sorting algorithm", name); 43 | int rc = func(words, (DArray_compare)testcmp); 44 | mu_assert(rc == 0, "sort failed."); 45 | mu_assert(is_sorted(words), "didn't sort it."); 46 | 47 | DArray_destroy(words); 48 | 49 | return NULL; 50 | } 51 | 52 | char *test_qsort() 53 | { 54 | return run_sort_test(DArray_qsort, "qsort"); 55 | } 56 | 57 | char *test_heapsort() 58 | { 59 | return run_sort_test(DArray_heapsort, "heapsort"); 60 | } 61 | 62 | char *test_mergesort() 63 | { 64 | return run_sort_test(DArray_mergesort, "mergesort"); 65 | } 66 | 67 | char *all_tests() 68 | { 69 | mu_suite_start(); 70 | 71 | mu_run_test(test_qsort); 72 | mu_run_test(test_heapsort); 73 | mu_run_test(test_mergesort); 74 | 75 | return NULL; 76 | } 77 | 78 | RUN_TESTS(all_tests); 79 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/darray_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | 4 | static DArray *array = NULL; 5 | static int *val1 = NULL; 6 | static int *val2 = NULL; 7 | 8 | char *test_create() 9 | { 10 | array = DArray_create(sizeof(int), 100); 11 | mu_assert(array != NULL, "DArray create failed."); 12 | mu_assert(array->contents != NULL, "contents are wrong in darray."); 13 | mu_assert(array->end == 0, "end isn't at the right spot."); 14 | mu_assert(array->element_size == sizeof(int), "element size is wrong."); 15 | mu_assert(array->max == 100, "wrong max length on initial size."); 16 | 17 | return NULL; 18 | } 19 | 20 | char *test_destroy() 21 | { 22 | DArray_destroy(array); 23 | 24 | return NULL; 25 | } 26 | 27 | char *test_new() 28 | { 29 | val1 = DArray_new(array); 30 | mu_assert(val1 != NULL, "fail to make a new element."); 31 | 32 | val2 = DArray_new(array); 33 | mu_assert(val2 != NULL, "fail to make a new element."); 34 | 35 | return NULL; 36 | } 37 | 38 | char *test_set() 39 | { 40 | DArray_set(array, 0, val1); 41 | DArray_set(array, 1, val2); 42 | 43 | return NULL; 44 | } 45 | 46 | char *test_get() 47 | { 48 | mu_assert(DArray_get(array, 0) == val1, "Wrong first value."); 49 | mu_assert(DArray_get(array, 1) == val2, "Wrong second value."); 50 | 51 | return NULL; 52 | } 53 | 54 | char *test_remove() 55 | { 56 | int *val_check = DArray_remove(array, 0); 57 | mu_assert(val_check != NULL, "should not get NULL."); 58 | mu_assert(*val_check == *val1, "should get the first value."); 59 | mu_assert(DArray_get(array, 0) == NULL, "should be gone."); 60 | DArray_free(val_check); 61 | 62 | 63 | val_check = DArray_remove(array, 1); 64 | mu_assert(val_check != NULL, "should not get NULL."); 65 | mu_assert(*val_check == *val2, "should get the second value."); 66 | mu_assert(DArray_get(array, 1) == NULL, "should be gone."); 67 | DArray_free(val_check); 68 | 69 | return NULL; 70 | } 71 | 72 | char *test_expand_contract() 73 | { 74 | int old_max = array->max; 75 | DArray_expand(array); 76 | mu_assert((unsigned int)array->max == array->expand_rate + old_max, "Wrong size after expand."); 77 | 78 | DArray_contract(array); 79 | mu_assert((unsigned int)array->max == array->expand_rate + 1, "should stay at the expand rate at least."); 80 | 81 | DArray_contract(array); 82 | mu_assert((unsigned int)array->max == array->expand_rate + 1, "should stay at the expand rate at least."); 83 | 84 | return NULL; 85 | } 86 | 87 | char *test_push_pop() 88 | { 89 | int i = 0; 90 | for(i = 0; i < 1000; ++i) 91 | { 92 | int *val = DArray_new(array); 93 | *val = i * 333; 94 | DArray_push(array, val); 95 | } 96 | 97 | mu_assert(array->max == 1201, "Wrong max size."); 98 | 99 | for(i = 999; i>= 0; i--) 100 | { 101 | int *val = DArray_pop(array); 102 | mu_assert(val != NULL, "should not get a NULL."); 103 | mu_assert(*val == i * 333, "Wrong value."); 104 | DArray_free(val); 105 | } 106 | return NULL; 107 | } 108 | 109 | char *all_tests() 110 | { 111 | mu_suite_start(); 112 | 113 | mu_run_test(test_create); 114 | mu_run_test(test_new); 115 | mu_run_test(test_set); 116 | mu_run_test(test_get); 117 | mu_run_test(test_remove); 118 | mu_run_test(test_expand_contract); 119 | mu_run_test(test_push_pop); 120 | 121 | return NULL; 122 | } 123 | 124 | RUN_TESTS(all_tests); 125 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/dbg.h: -------------------------------------------------------------------------------- 1 | #ifndef _dbg_h 2 | #define _dbg_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define debug(M, ...) 10 | #else 11 | #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 17 | 18 | #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 21 | 22 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 23 | 24 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 25 | 26 | #define check_mem(A) check((A), "Out of memory.") 27 | 28 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/hash.txt: -------------------------------------------------------------------------------- 1 | FNV A32 DJB 2 | 1027 1013 991 3 | 950 1025 969 4 | 1031 917 1031 5 | 981 1046 944 6 | 1036 1007 985 7 | 959 996 969 8 | 1036 1040 1059 9 | 1007 993 1046 10 | 990 1003 994 11 | 1049 1042 1003 12 | 958 976 956 13 | 1003 1023 1073 14 | 1000 999 1026 15 | 992 1017 1047 16 | 968 986 930 17 | 1092 1017 1018 18 | 1005 1023 1028 19 | 992 943 1022 20 | 995 1052 958 21 | 1030 964 1007 22 | 1012 1009 977 23 | 1069 1013 1006 24 | 990 1000 1011 25 | 990 1086 1024 26 | 1008 991 1006 27 | 993 1042 940 28 | 974 995 992 29 | 1021 982 950 30 | 1063 1030 1037 31 | 1000 1021 999 32 | 993 982 989 33 | 969 1027 968 34 | 1016 950 982 35 | 983 1066 959 36 | 1006 985 995 37 | 1002 963 1064 38 | 975 965 1063 39 | 1002 931 1013 40 | 960 982 982 41 | 976 996 1014 42 | 1029 1010 1014 43 | 1009 1027 1014 44 | 976 1012 1002 45 | 1012 982 1026 46 | 965 969 1023 47 | 1010 1060 1016 48 | 962 944 1017 49 | 1026 992 967 50 | 1012 1025 968 51 | 963 978 1056 52 | 1030 957 982 53 | 1000 942 1026 54 | 1025 1013 995 55 | 1035 973 1020 56 | 1014 987 1060 57 | 993 977 998 58 | 990 965 951 59 | 1012 981 1025 60 | 1019 992 1051 61 | 1004 1022 1018 62 | 1004 996 968 63 | 1028 980 1010 64 | 996 1017 939 65 | 1004 982 935 66 | 965 998 1002 67 | 998 1002 1030 68 | 998 995 985 69 | 969 1024 1007 70 | 914 1015 1023 71 | 1006 965 1008 72 | 1012 966 970 73 | 1010 950 1003 74 | 985 1000 1015 75 | 981 961 1034 76 | 995 1065 1038 77 | 999 1016 994 78 | 1015 979 988 79 | 1038 939 964 80 | 993 1008 977 81 | 994 1029 1033 82 | 966 1042 1036 83 | 987 1010 1020 84 | 1013 995 1018 85 | 987 1082 1020 86 | 1038 992 928 87 | 999 1045 962 88 | 989 1013 1050 89 | 1062 970 993 90 | 1030 1033 973 91 | 990 1009 980 92 | 940 1004 940 93 | 1036 1004 954 94 | 949 985 993 95 | 994 1004 1020 96 | 995 995 1003 97 | 958 992 1013 98 | 985 937 983 99 | 1044 1065 1009 100 | 987 1020 950 101 | 958 1010 976 102 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/hashmap_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | #include 5 | 6 | Hashmap *map = NULL; 7 | static int traverse_called = 0; 8 | struct tagbstring test1 = bsStatic("test data 1"); 9 | struct tagbstring test2 = bsStatic("test data 2"); 10 | struct tagbstring test3 = bsStatic("test data 3"); 11 | struct tagbstring expect1 = bsStatic("THE VALUE 1"); 12 | struct tagbstring expect2 = bsStatic("THE VALUE 2"); 13 | struct tagbstring expect3 = bsStatic("THE VALUE 3"); 14 | 15 | static int traverse_good_cb(HashmapNode *node) 16 | { 17 | debug("KEY %s", bdata((bstring)node->key)); 18 | traverse_called++; 19 | return 0; 20 | } 21 | 22 | static int traverse_fail_cb(HashmapNode *node) 23 | { 24 | debug("KEY %s", bdata((bstring)node->key)); 25 | traverse_called++; 26 | 27 | if(traverse_called == 2) 28 | { 29 | return 1; 30 | } 31 | else 32 | { 33 | return 0; 34 | } 35 | } 36 | 37 | char *test_create() 38 | { 39 | map = Hashmap_create(NULL, NULL); 40 | mu_assert(map != NULL, "Failed to create map"); 41 | 42 | return NULL; 43 | } 44 | 45 | char *test_destroy() 46 | { 47 | Hashmap_destroy(map); 48 | 49 | return NULL; 50 | } 51 | 52 | char *test_get_set() 53 | { 54 | int rc = Hashmap_set(map, &test1, &expect1); 55 | mu_assert(rc == 0, "Failed to set &test1"); 56 | bstring result = Hashmap_get(map, &test1); 57 | mu_assert(result == &expect1, "Wrong value for test1"); 58 | 59 | rc = Hashmap_set(map, &test2, &expect2); 60 | mu_assert(rc == 0, "Failed to set &test2"); 61 | result = Hashmap_get(map, &test2); 62 | mu_assert(result == &expect2, "Wrong value for test2"); 63 | 64 | rc = Hashmap_set(map, &test3, &expect3); 65 | mu_assert(rc == 0, "Failed to set &test3"); 66 | result = Hashmap_get(map, &test3); 67 | mu_assert(result == &expect3, "Wrong value for test3"); 68 | 69 | return NULL; 70 | } 71 | 72 | char *test_traverse() 73 | { 74 | int rc = Hashmap_traverse(map, traverse_good_cb); 75 | mu_assert(rc == 0, "Failed to traverse"); 76 | mu_assert(traverse_called == 3, "Wrong count traverse"); 77 | 78 | traverse_called = 0; 79 | rc = Hashmap_traverse(map, traverse_fail_cb); 80 | mu_assert(rc == 1, "Failed to traverse"); 81 | mu_assert(traverse_called == 2, "Wrong count traverse for fail"); 82 | 83 | return NULL; 84 | } 85 | 86 | char *test_delete() 87 | { 88 | bstring delete = (bstring)Hashmap_delete(map, &test1); 89 | mu_assert(delete != NULL, "Got NULL on delete"); 90 | mu_assert(delete == &expect1, "Should got test1"); 91 | bstring result = Hashmap_get(map, &test1); 92 | mu_assert(result == NULL, "Should delete"); 93 | 94 | delete = (bstring)Hashmap_delete(map, &test2); 95 | mu_assert(delete != NULL, "Got NULL on delete"); 96 | mu_assert(delete == &expect2, "Should got test2"); 97 | result = Hashmap_get(map, &test2); 98 | mu_assert(result == NULL, "Should delete"); 99 | 100 | delete = (bstring)Hashmap_delete(map, &test3); 101 | mu_assert(delete != NULL, "Got NULL on delete"); 102 | mu_assert(delete == &expect3, "Should got test2"); 103 | result = Hashmap_get(map, &test3); 104 | mu_assert(result == NULL, "Should delete"); 105 | 106 | return NULL; 107 | } 108 | 109 | char *all_tests() 110 | { 111 | mu_suite_start(); 112 | 113 | mu_run_test(test_create); 114 | mu_run_test(test_get_set); 115 | mu_run_test(test_traverse); 116 | mu_run_test(test_delete); 117 | mu_run_test(test_destroy); 118 | 119 | return NULL; 120 | } 121 | 122 | RUN_TESTS(all_tests); 123 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/list_algos_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | #include 5 | 6 | char *value[] = {"XXXX", "1234", "abcd", "xjvef", "NDSS"}; 7 | #define NUM_VALUES 5 8 | 9 | List *create_words() 10 | { 11 | int i = 0; 12 | List *words = List_create(); 13 | 14 | for(i = 0; i < NUM_VALUES; ++i) 15 | { 16 | List_push(words, value[i]); 17 | } 18 | 19 | return words; 20 | } 21 | 22 | int is_sorted(List *words) 23 | { 24 | LIST_FOREACH(words, first, next, cur) 25 | { 26 | if(cur->next && strcmp(cur->value, cur->next->value) > 0) 27 | { 28 | debug("%s %s", (char *)cur->value, (char *)cur->next->value); 29 | return 0; 30 | } 31 | } 32 | 33 | return 1; 34 | } 35 | 36 | char *test_bubble_sort() 37 | { 38 | List *words = create_words(); 39 | 40 | int rc = List_bubble_sort(words, (List_compare)strcmp); 41 | mu_assert(rc == 0, "Bubble sort failed."); 42 | mu_assert(is_sorted(words), "Words are not sorted after bubble sort."); 43 | 44 | rc = List_bubble_sort(words, (List_compare)strcmp); 45 | mu_assert(rc == 0, "Bubble sort of already sort failed."); 46 | mu_assert(is_sorted(words), "Words are not sorted after bubble sort of already sort."); 47 | 48 | List_destroy(words); 49 | 50 | words = List_create(words); 51 | rc = List_bubble_sort(words, (List_compare)strcmp); 52 | mu_assert(rc == 0, "Bubble sort of empty failed."); 53 | mu_assert(is_sorted(words), "Words are not sorted after bubble sort of empty."); 54 | 55 | List_destroy(words); 56 | 57 | return NULL; 58 | 59 | } 60 | 61 | char *test_merge_sort() 62 | { 63 | List *words = create_words(); 64 | 65 | List *res = List_merge_sort(words, (List_compare)strcmp); 66 | mu_assert(is_sorted(res), "Words are not sorted after merge sort."); 67 | 68 | List *res2 = List_merge_sort(res, (List_compare)strcmp); 69 | mu_assert(is_sorted(res2), "Should still be sorted after merge sort."); 70 | List_destroy(res2); 71 | List_destroy(res); 72 | 73 | List_destroy(words); 74 | return NULL; 75 | } 76 | 77 | char *all_tests() 78 | { 79 | mu_suite_start(); 80 | 81 | mu_run_test(test_bubble_sort); 82 | mu_run_test(test_merge_sort); 83 | 84 | return NULL; 85 | } 86 | 87 | RUN_TESTS(all_tests); 88 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/list_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | 5 | static List *list = NULL; 6 | char *test1 = "test1 data"; 7 | char *test2 = "test2 data"; 8 | char *test3 = "test3 data"; 9 | 10 | char *test_create() 11 | { 12 | list = List_create(); 13 | mu_assert(list != NULL, "Failed to create list."); 14 | 15 | return NULL; 16 | } 17 | 18 | char *test_destroy() 19 | { 20 | List_clear_destroy(list); 21 | 22 | return NULL; 23 | } 24 | 25 | char *test_push_pop() 26 | { 27 | List_push(list, test1); 28 | mu_assert(List_last(list) == test1, "Wrongg last value."); 29 | 30 | List_push(list, test2); 31 | mu_assert(List_last(list) == test2, "Wrong last value."); 32 | 33 | List_push(list, test3); 34 | mu_assert(List_last(list) == test3, "Wrong last value."); 35 | mu_assert(List_count(list) == 3, "Wrong count on push."); 36 | 37 | char *val = List_pop(list); 38 | mu_assert(val == test3, "Wrong value on pop."); 39 | 40 | val = List_pop(list); 41 | mu_assert(val == test2, "Wrong value on pop."); 42 | 43 | val = List_pop(list); 44 | mu_assert(val == test1, "Wrong value on pop."); 45 | mu_assert(List_count(list) == 0, "Wrong count after pop."); 46 | 47 | return NULL; 48 | } 49 | 50 | char *test_unshift() 51 | { 52 | List_unshift(list, test1); 53 | mu_assert(List_first(list) == test1, "Wrong first value."); 54 | 55 | List_unshift(list, test2); 56 | mu_assert(List_first(list) == test2, "Wrong first value."); 57 | 58 | List_unshift(list, test3); 59 | mu_assert(List_first(list) == test3, "Wrong first value."); 60 | mu_assert(List_count(list) == 3, "Wrong count on unshift."); 61 | 62 | return NULL; 63 | } 64 | 65 | char *test_remove() 66 | { 67 | char *val = List_remove(list, list->first->next); 68 | mu_assert(val == test2, "Wrong removed element."); 69 | mu_assert(List_count(list) == 2, "Wrong count after remove."); 70 | mu_assert(List_first(list) == test3, "Wrong first after remmove."); 71 | mu_assert(List_last(list) == test1, "Wrong last after remove."); 72 | 73 | return NULL; 74 | } 75 | 76 | char *test_shift() 77 | { 78 | mu_assert(List_count(list) != 0, "Wrong count before shift."); 79 | 80 | char *val = List_shift(list); 81 | mu_assert(val == test3, "Wrong value on shift."); 82 | 83 | val = List_shift(list); 84 | mu_assert(val == test1, "Wrong value on shift."); 85 | mu_assert(List_count(list) == 0, "Wrong count after shift."); 86 | 87 | return NULL; 88 | } 89 | 90 | char *all_tests() 91 | { 92 | mu_suite_start(); 93 | 94 | mu_run_test(test_create); 95 | mu_run_test(test_push_pop); 96 | mu_run_test(test_unshift); 97 | mu_run_test(test_remove); 98 | mu_run_test(test_shift); 99 | mu_run_test(test_destroy); 100 | 101 | return NULL; 102 | } 103 | 104 | RUN_TESTS(all_tests); 105 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/minunit.h: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #ifndef _minunit_h 3 | #define _minunit_h 4 | 5 | #include 6 | #include 7 | #include "dbg.h" 8 | 9 | #define mu_suite_start() char *message = NULL 10 | 11 | #define mu_assert(test, message) if (!(test)) {log_err(message); return message;} 12 | #define mu_run_test(test) debug("\n--------%s", ""#test); \ 13 | message = test(); tests_run++; if (message) return message; 14 | 15 | #define RUN_TESTS(name) int main(int argc, char *argv[]) \ 16 | {\ 17 | argc = 1;\ 18 | debug("------RUNNING: %s", argv[0]);\ 19 | printf("------\nRUNNING: %s\n", argv[0]);\ 20 | char *result = name();\ 21 | if (result != 0) \ 22 | {\ 23 | printf("FAILED: %s\n", result);\ 24 | }\ 25 | else\ 26 | {\ 27 | printf("ALL TESTS PASSED\n");\ 28 | }\ 29 | printf("Tests run: %d\n", tests_run);\ 30 | exit(result != 0);\ 31 | } 32 | 33 | int tests_run; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/queue_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | 5 | static Queue *queue = NULL; 6 | char *tests[] = {"test1 data", "test2 data", "test3 data"}; 7 | #define NUM_TESTS 3 8 | 9 | char *test_create() 10 | { 11 | queue = Queue_create(); 12 | mu_assert(queue != NULL, "Failed to create queue."); 13 | 14 | return NULL; 15 | } 16 | 17 | char *test_destroy() 18 | { 19 | mu_assert(queue != NULL, "Failed to make queue #2."); 20 | Queue_destroy(queue); 21 | 22 | return NULL; 23 | } 24 | 25 | char *test_send_recv() 26 | { 27 | int i = 0; 28 | for(i = 0; i < NUM_TESTS; i++) 29 | { 30 | Queue_send(queue, tests[i]); 31 | mu_assert(Queue_peek(queue) == tests[i], "Wrong next value."); 32 | } 33 | 34 | mu_assert(Queue_count(queue) == NUM_TESTS, "Wrong count on send."); 35 | 36 | QUEUE_FOREACH(queue, cur) 37 | { 38 | debug("VAL: %s", (char *)cur->value); 39 | } 40 | 41 | for(i = 0; i < NUM_TESTS; i++) 42 | { 43 | char *val = Queue_recv(queue); 44 | mu_assert(val == tests[i], "Wrong value on recv."); 45 | } 46 | 47 | mu_assert(Queue_count(queue) == 0, "Wrong count after recv."); 48 | 49 | return NULL; 50 | } 51 | 52 | char *all_tests() 53 | { 54 | mu_suite_start(); 55 | 56 | mu_run_test(test_create); 57 | mu_run_test(test_send_recv); 58 | mu_run_test(test_destroy); 59 | 60 | return NULL; 61 | } 62 | 63 | RUN_TESTS(all_tests); 64 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/radixmap_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | 5 | static int make_random(RadixMap *map) 6 | { 7 | size_t i = 0; 8 | 9 | for(i = 0; i < map->max - 1; i++) 10 | { 11 | uint32_t key = (uint32_t)(rand() | (rand() << 16)); 12 | check(RadixMap_add(map, key, i) == 0, "Failed to add key %u.", key); 13 | } 14 | 15 | return i; 16 | 17 | error: 18 | return 0; 19 | } 20 | 21 | static int check_order(RadixMap *map) 22 | { 23 | RMElement d1, d2; 24 | unsigned int i = 0; 25 | 26 | for(i = 0; map->end > 0 && i < map->end - 1; i++) 27 | { 28 | d1 = map->contents[i]; 29 | d2 = map->contents[i+1]; 30 | 31 | if(d1.data.key > d2.data.key) 32 | { 33 | debug("FAIL: i=%u, key=%u, value=%u, equals max? %d\n", i, d1.data.key, d1.data.value, d2.data.key == UINT32_MAX); 34 | return 0; 35 | } 36 | } 37 | 38 | return 1; 39 | } 40 | 41 | static int test_search(RadixMap *map) 42 | { 43 | unsigned i = 0; 44 | RMElement *d = NULL; 45 | RMElement *found = NULL; 46 | 47 | for(i = map->end / 2; i < map->end; i++) 48 | { 49 | d = &map->contents[i]; 50 | found = RadixMap_find(map, d->data.key); 51 | check(found != NULL, "Didn't find %u at %u", d->data.key, i); 52 | check(found->data.key == d->data.key, "Got the wrong result: %p:%u looking for %u at %u", found, found->data.key, d->data.key, i); 53 | } 54 | 55 | return 1; 56 | error: 57 | return 0; 58 | } 59 | 60 | static char *test_operation() 61 | { 62 | size_t N = 200; 63 | 64 | RadixMap *map = RadixMap_create(N); 65 | mu_assert(map != NULL, "Failed to make the map."); 66 | mu_assert(make_random(map), "Didn't make a random fake radix map."); 67 | 68 | RadixMap_sort(map); 69 | mu_assert(check_order(map), "Failed to properly sort the RadixMap."); 70 | 71 | mu_assert(test_search(map), "Failed the search test."); 72 | mu_assert(check_order(map), "RadixMap didn't stay sorted after search."); 73 | 74 | while(map->end > 0) 75 | { 76 | RMElement *el = RadixMap_find(map, map->contents[map->end / 2].data.key); 77 | mu_assert(el != NULL, "Should get a result."); 78 | 79 | size_t old_end = map->end; 80 | 81 | mu_assert(RadixMap_delete(map, el) == 0, "Didn't delete it."); 82 | mu_assert(old_end - 1 == map->end, "Wrong size after delete."); 83 | 84 | mu_assert(check_order(map), "RadixMap didn't stay sorted after delete."); 85 | } 86 | 87 | RadixMap_destroy(map); 88 | 89 | return NULL; 90 | } 91 | 92 | char *all_tests() 93 | { 94 | mu_suite_start(); 95 | srand(time(NULL)); 96 | 97 | mu_run_test(test_operation); 98 | 99 | return NULL; 100 | } 101 | 102 | RUN_TESTS(all_tests); 103 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/ringbuffer_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | 5 | static RingBuffer *buffer = NULL; 6 | 7 | char *tests[] = {"test1 data", "test2 data", "test3 data"}; 8 | 9 | #define BUFFER_LENGTH 100 10 | #define NUM_TESTS 3 11 | 12 | char *test_create() 13 | { 14 | buffer = RingBuffer_create(BUFFER_LENGTH); 15 | mu_assert(buffer != NULL, "Failed to create ringbuffer."); 16 | 17 | return NULL; 18 | } 19 | 20 | char *test_read_write() 21 | { 22 | int i = 0; 23 | int wr_data_cnt = 0; 24 | for(i = 0; i < NUM_TESTS; i++) 25 | { 26 | int res = RingBuffer_write(buffer, tests[i], strlen(tests[i])); 27 | mu_assert(res >= 0, "Failed to write."); 28 | wr_data_cnt += strlen(tests[i]); 29 | mu_assert(!RingBuffer_empty(buffer), "Should not be empty."); 30 | mu_assert(RingBuffer_available_data(buffer) == wr_data_cnt, "Write size wrong."); 31 | } 32 | 33 | for(i = 0; i < NUM_TESTS; i++) 34 | { 35 | mu_assert(!RingBuffer_empty(buffer), "Should not be empty."); 36 | int cur_size = strlen(tests[i]); 37 | char *read_target = calloc(1, cur_size); 38 | int res = RingBuffer_read(buffer, read_target, cur_size); 39 | mu_assert(res >= 0, "Failed to read."); 40 | int j = 0; 41 | for(j = 0; j < cur_size; j++) 42 | { 43 | mu_assert(tests[i][j] == read_target[j], "Wrong read result."); 44 | } 45 | } 46 | 47 | mu_assert(RingBuffer_empty(buffer), "Should be empty."); 48 | 49 | return NULL; 50 | } 51 | 52 | char *test_destroy() 53 | { 54 | mu_assert(buffer != NULL, "Failed to make ringbuffer #2."); 55 | RingBuffer_destroy(buffer); 56 | 57 | return NULL; 58 | } 59 | 60 | 61 | char *all_tests() 62 | { 63 | mu_suite_start(); 64 | 65 | mu_run_test(test_create); 66 | mu_run_test(test_read_write); 67 | mu_run_test(test_destroy); 68 | 69 | return NULL; 70 | } 71 | 72 | RUN_TESTS(all_tests); 73 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/runtests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Running unit test:" 4 | 5 | for i in tests/*_tests 6 | do 7 | if test -f $i 8 | then 9 | if $VALGRIND ./$i 2>> tests/tests.log 10 | then 11 | echo $i PASS 12 | else 13 | echo "ERROR in test $i: here's tests/tests.log" 14 | echo "---" 15 | tail tests/tests.log 16 | exit 1 17 | fi 18 | fi 19 | done 20 | 21 | echo "" 22 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/stack_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | 5 | static Stack *stack = NULL; 6 | char *tests[] = {"test1 data", "test2 data", "test3 data"}; 7 | #define NUM_TESTS 3 8 | 9 | char *test_create() 10 | { 11 | stack = Stack_create(); 12 | mu_assert(stack != NULL, "Failed to create stack."); 13 | 14 | return NULL; 15 | } 16 | 17 | char *test_destroy() 18 | { 19 | mu_assert(stack != NULL, "Failed to make stack #2."); 20 | Stack_destroy(stack); 21 | 22 | return NULL; 23 | } 24 | 25 | char *test_push_pop() 26 | { 27 | int i = 0; 28 | for(i = 0; i < NUM_TESTS; i++) 29 | { 30 | Stack_push(stack, tests[i]); 31 | mu_assert(Stack_peek(stack) == tests[i], "Wrong next value."); 32 | } 33 | 34 | mu_assert(Stack_count(stack) == NUM_TESTS, "Wrong count on push."); 35 | 36 | STACK_FOREACH(stack, cur) 37 | { 38 | debug("VAL: %s", (char *)cur->value); 39 | } 40 | 41 | for(i = NUM_TESTS - 1; i >= 0; i--) 42 | { 43 | char *val = Stack_pop(stack); 44 | mu_assert(val == tests[i], "Wrong value on pop."); 45 | } 46 | 47 | mu_assert(Stack_count(stack) == 0, "Wrong count after pop."); 48 | 49 | return NULL; 50 | } 51 | 52 | char *all_tests() 53 | { 54 | mu_suite_start(); 55 | 56 | mu_run_test(test_create); 57 | mu_run_test(test_push_pop); 58 | mu_run_test(test_destroy); 59 | 60 | return NULL; 61 | } 62 | 63 | RUN_TESTS(all_tests); 64 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/stats_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | 5 | const int NUM_SAMPLES = 10; 6 | double samples[] = { 7 | 6.1061334, 9.6783204, 1.2747090, 8.2395131, 0.3333483, 8 | 6.9755066, 1.0626275, 7.6587523, 4.9382973, 9.5788115 9 | }; 10 | 11 | Stats expect = 12 | { 13 | .sumsq = 425.1641, 14 | .sum = 55.84602, 15 | .min = 0.333, 16 | .max = 9.678, 17 | .n = 10, 18 | }; 19 | 20 | double expect_mean = 5.584602; 21 | double expect_stddev = 3.547868; 22 | 23 | #define EQ(X, Y, N) (round((X) * pow(10, N)) == round((Y) * pow(10, N))) 24 | 25 | char *test_operations() 26 | { 27 | int i = 0; 28 | Stats *st = Stats_create(); 29 | mu_assert(st != NULL, "Failed to create stats"); 30 | 31 | for(i = 0; i < NUM_SAMPLES; i++) 32 | { 33 | Stats_sample(st, samples[i]); 34 | } 35 | 36 | Stats_dump(st); 37 | 38 | mu_assert(EQ(st->sumsq, expect.sumsq, 3), "sumsq not valid."); 39 | mu_assert(EQ(st->sum, expect.sum, 3), "sum not valid."); 40 | mu_assert(EQ(st->n, expect.n, 3), "n not valid."); 41 | mu_assert(EQ(st->max, expect.max, 3), "max not valid."); 42 | mu_assert(EQ(st->min, expect.min, 3), "min not valid."); 43 | mu_assert(EQ(expect_mean, Stats_mean(st), 3), "mean not valid."); 44 | mu_assert(EQ(expect_stddev, Stats_stddev(st), 3), "stddev not valid."); 45 | 46 | return NULL; 47 | } 48 | 49 | char *test_recreate() 50 | { 51 | Stats *st = Stats_recreate(expect.sum, expect.sumsq, expect.n, expect.min, expect.max); 52 | 53 | mu_assert(st->sum == expect.sum, "sum not equal."); 54 | mu_assert(st->sumsq == expect.sumsq, "sumsq not equal."); 55 | mu_assert(st->n == expect.n, "n not equal."); 56 | mu_assert(st->min == expect.min, "min not equal."); 57 | mu_assert(st->max == expect.max, "max not equal."); 58 | mu_assert(EQ(expect_mean, Stats_mean(st), 3), "mean not valid."); 59 | mu_assert(EQ(expect_stddev, Stats_stddev(st), 3), "stddev not valid."); 60 | 61 | return NULL; 62 | } 63 | 64 | char *all_tests() 65 | { 66 | mu_suite_start(); 67 | 68 | mu_run_test(test_operations); 69 | mu_run_test(test_recreate); 70 | 71 | return NULL; 72 | } 73 | 74 | RUN_TESTS(all_tests); 75 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/string_algos_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | #include 5 | 6 | struct tagbstring IN_STR = bsStatic("I have ALPHA beta ALPHA and oranges ALPHA"); 7 | struct tagbstring ALPHA = bsStatic("ALPHA"); 8 | const int TEST_TIME = 1; 9 | 10 | char *test_find_and_scan() 11 | { 12 | StringScanner *scan = StringScanner_create(&IN_STR); 13 | mu_assert(scan != NULL, "Failed to create scanner."); 14 | 15 | int find_i = String_find(&IN_STR, &ALPHA); 16 | mu_assert(find_i > 0, "Failed to find 'ALPHA' in test string."); 17 | 18 | int scan_i = StringScanner_scan(scan, &ALPHA); 19 | mu_assert(scan_i > 0, "Failed to find 'ALPHA' with scan."); 20 | mu_assert(scan_i == find_i, "find and scan don't match."); 21 | 22 | scan_i = StringScanner_scan(scan, &ALPHA); 23 | mu_assert(scan_i > find_i, "Should find another ALPHA with scan."); 24 | 25 | scan_i = StringScanner_scan(scan, &ALPHA); 26 | mu_assert(scan_i > find_i, "Should find another ALPHA with scan."); 27 | 28 | mu_assert(StringScanner_scan(scan, &ALPHA) == -1, "Shouldn't find it."); 29 | 30 | StringScanner_destroy(scan); 31 | 32 | return NULL; 33 | } 34 | 35 | char *test_binstr_performance() 36 | { 37 | int i = 0; 38 | int found_at = 0; 39 | unsigned long find_count = 0; 40 | time_t elapsed = 0; 41 | time_t start = time(NULL); 42 | 43 | do 44 | { 45 | for(i = 0; i < 1000; i++) 46 | { 47 | found_at = binstr(&IN_STR, 0, &ALPHA); 48 | mu_assert(found_at != BSTR_ERR, "Failed to find!"); 49 | find_count++; 50 | } 51 | 52 | elapsed = time(NULL) - start; 53 | } while(elapsed < TEST_TIME); 54 | 55 | debug("BINSTR COUNT: %lu, END TIME: %d, OPS: %f", 56 | find_count, (int)elapsed, (double)find_count / elapsed); 57 | 58 | return NULL; 59 | } 60 | 61 | char *test_find_performance() 62 | { 63 | int i = 0; 64 | int found_at = 0; 65 | unsigned long find_count = 0; 66 | time_t elapsed = 0; 67 | time_t start = time(NULL); 68 | 69 | do 70 | { 71 | for(i = 0; i < 1000; i++) 72 | { 73 | found_at = String_find(&IN_STR, &ALPHA); 74 | find_count++; 75 | } 76 | elapsed = time(NULL) - start; 77 | } while(elapsed < TEST_TIME); 78 | 79 | debug("FIND COUNT: %lu, END TIME: %d, OPS: %f", 80 | find_count, (int)elapsed, (double)find_count / elapsed); 81 | 82 | return NULL; 83 | } 84 | 85 | char *test_scan_performance() 86 | { 87 | int i = 0; 88 | int found_at = 0; 89 | unsigned long find_count = 0; 90 | time_t elapsed = 0; 91 | StringScanner *scan = StringScanner_create(&IN_STR); 92 | time_t start = time(NULL); 93 | 94 | do 95 | { 96 | for(i = 0; i < 1000; i++) 97 | { 98 | found_at = 0; 99 | 100 | do 101 | { 102 | found_at = StringScanner_scan(scan, &ALPHA); 103 | find_count++; 104 | } while(found_at != -1); 105 | } 106 | elapsed = time(NULL) - start; 107 | } while(elapsed < TEST_TIME); 108 | 109 | debug("SCAN COUNT: %lu, END TIME: %d, OPS: %f", 110 | find_count, (int)elapsed, (double)find_count / elapsed); 111 | 112 | return NULL; 113 | } 114 | 115 | char *all_tests() 116 | { 117 | mu_suite_start(); 118 | 119 | mu_run_test(test_find_and_scan); 120 | #if 1 121 | mu_run_test(test_binstr_performance); 122 | mu_run_test(test_find_performance); 123 | mu_run_test(test_scan_performance); 124 | #endif 125 | 126 | return NULL; 127 | } 128 | 129 | RUN_TESTS(all_tests); 130 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/tests/tstree_tests.c: -------------------------------------------------------------------------------- 1 | #include "minunit.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | TSTree *node = NULL; 8 | char *valueA = "VALUEA"; 9 | char *valueB = "VALUEB"; 10 | char *value2 = "VALUE2"; 11 | char *value4 = "VALUE4"; 12 | char *reverse = "VALUER"; 13 | int traverse_count = 0; 14 | 15 | struct tagbstring test1 = bsStatic("TEST"); 16 | struct tagbstring test2 = bsStatic("TEST2"); 17 | struct tagbstring test3 = bsStatic("TSET"); 18 | struct tagbstring test4 = bsStatic("T"); 19 | 20 | char *test_insert() 21 | { 22 | node = TSTree_insert(node, bdata(&test1), blength(&test1), valueA); 23 | mu_assert(node != NULL, "Failed to insert into tst."); 24 | 25 | node = TSTree_insert(node, bdata(&test2), blength(&test2), valueB); 26 | mu_assert(node != NULL, "Failed to insert into tst with second name."); 27 | 28 | node = TSTree_insert(node, bdata(&test3), blength(&test3), reverse); 29 | mu_assert(node != NULL, "Failed to insert into tst with reverse name."); 30 | 31 | node = TSTree_insert(node, bdata(&test4), blength(&test4), value4); 32 | mu_assert(node != NULL, "Failed to insert into tst with fourth name."); 33 | 34 | return NULL; 35 | } 36 | 37 | char *test_search_exact() 38 | { 39 | // tst returns the last one inserted. 40 | void *res = TSTree_search(node, bdata(&test1), blength(&test1)); 41 | debug("result: %p, expected: %p", res, reverse); 42 | mu_assert(res == valueA, "Got the wrong value back, should get A not B."); 43 | 44 | // tst does not find if not exact. 45 | res = TSTree_search(node, "TESTO", strlen("TESTO")); 46 | mu_assert(res == NULL, "Should not find anything."); 47 | 48 | return NULL; 49 | } 50 | 51 | char *test_search_prefix() 52 | { 53 | void *res = TSTree_search_prefix(node, bdata(&test1), blength(&test1)); 54 | debug("result: %p, expected: %p", res, valueA); 55 | mu_assert(res == valueA, "Got wrong valueA by prefix."); 56 | 57 | res = TSTree_search_prefix(node, bdata(&test1), 1); 58 | debug("result: %p, expected: %p", res, valueA); 59 | mu_assert(res == value4, "Got wrong value4 for prefix of 1."); 60 | 61 | res = TSTree_search_prefix(node, "TE", strlen("TE")); 62 | mu_assert(res != NULL, "Should find short prefix"); 63 | 64 | res = TSTree_search_prefix(node, "TE--", strlen("TE--")); 65 | mu_assert(res != NULL, "Should find for partial prefix."); 66 | 67 | return NULL; 68 | } 69 | 70 | void TSTree_traverse_test_cb(void *value, void *data) 71 | { 72 | assert(value != NULL && "Should not get NULL value."); 73 | assert(data == valueA && "Expecting valueA as the data."); 74 | traverse_count++; 75 | } 76 | 77 | char *test_traverse() 78 | { 79 | traverse_count = 0; 80 | TSTree_traverse(node, TSTree_traverse_test_cb, valueA); 81 | debug("traverse_count is %d", traverse_count); 82 | mu_assert(traverse_count == 4, "Didn't find 4 keys."); 83 | 84 | return NULL; 85 | } 86 | 87 | char *test_destroy() 88 | { 89 | TSTree_destroy(node); 90 | 91 | return NULL; 92 | } 93 | 94 | char *all_tests() 95 | { 96 | mu_suite_start(); 97 | 98 | mu_run_test(test_insert); 99 | mu_run_test(test_search_exact); 100 | mu_run_test(test_search_prefix); 101 | mu_run_test(test_traverse); 102 | mu_run_test(test_destroy); 103 | 104 | return NULL; 105 | } 106 | 107 | RUN_TESTS(all_tests); 108 | -------------------------------------------------------------------------------- /learncthehardway/liblcthw/urls.txt: -------------------------------------------------------------------------------- 1 | / MainApp 2 | /hello Hello 3 | /hello/ Hello 4 | /signup Signup 5 | /logout Logout 6 | /album/ Album 7 | -------------------------------------------------------------------------------- /learncthehardway/object.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "object.h" 6 | 7 | void Object_destroy(void *self) 8 | { 9 | Object *obj = self; 10 | if (obj) 11 | { 12 | if (obj->description) 13 | { 14 | free(obj->description); 15 | } 16 | free(obj); 17 | } 18 | } 19 | 20 | void Object_describe(void *self) 21 | { 22 | Object *obj = self; 23 | printf("%s.\n", obj->description); 24 | } 25 | 26 | int Object_init(void *self) 27 | { 28 | return 1; 29 | } 30 | 31 | void *Object_move(void *self, Direction direction) 32 | { 33 | printf("You can't go that direction.\n"); 34 | return NULL; 35 | } 36 | 37 | int Object_attack(void *self, int damage) 38 | { 39 | printf("You can't attack that.\n"); 40 | return 0; 41 | } 42 | 43 | void *Object_new(size_t size, Object proto, char *description) 44 | { 45 | if (!proto.init) proto.init = Object_init; 46 | if (!proto.describe) proto.describe = Object_describe; 47 | if (!proto.destroy) proto.destroy = Object_destroy; 48 | if (!proto.attack) proto.attack = Object_attack; 49 | if (!proto.move) proto.move = Object_move; 50 | 51 | Object *e1 = calloc(1, size); 52 | *e1 = proto; 53 | 54 | e1->description = strdup(description); 55 | 56 | if (!e1->init(e1)) 57 | { 58 | e1->destroy(e1); 59 | return NULL; 60 | } 61 | else 62 | { 63 | return e1; 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /learncthehardway/object.h: -------------------------------------------------------------------------------- 1 | #ifndef _object_h 2 | #define _object_h 3 | 4 | typedef enum 5 | { 6 | NORTH, SOUTH, EAST, WEST 7 | }Direction; 8 | 9 | typedef struct 10 | { 11 | char *description; 12 | int (*init)(void *self); 13 | void (*describe)(void *self); 14 | void (*destroy)(void *self); 15 | void *(*move)(void *self, Direction direction); 16 | int (*attack)(void *self, int damage); 17 | }Object; 18 | 19 | int Object_init(void *self); 20 | void Object_describe(void *self); 21 | void Object_destroy(void *self); 22 | void *Object_move(void *self, Direction direction); 23 | int Object_attack(void *self, int damage); 24 | void *Object_new(size_t size, Object proto, char *description); 25 | 26 | #define NEW(T, N) Object_new(sizeof(T), T##Proto, N) 27 | #define _(N) proto.N 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /protobuf/proto/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yubo1911/saber/aba4efee1afa10ef582f705fbd1d4d2a4829c413/protobuf/proto/__init__.py -------------------------------------------------------------------------------- /protobuf/proto/addressbook.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | package tutorial; 3 | 4 | message Person { 5 | required string name = 1; 6 | required int32 id = 2; 7 | optional string email = 3; 8 | 9 | enum PhoneType { 10 | MOBILE = 0; 11 | HOME = 1; 12 | WORK = 2; 13 | } 14 | 15 | message PhoneNumber { 16 | required string number = 1; 17 | optional PhoneType type = 2 [default = HOME]; 18 | } 19 | 20 | repeated PhoneNumber phone = 4; 21 | } 22 | 23 | message AddressBook { 24 | repeated Person person = 1; 25 | } 26 | -------------------------------------------------------------------------------- /protobuf/serialized.txt: -------------------------------------------------------------------------------- 1 | 2 | + 3 | yuboyubo1911@163.com" 4 | 13345678901 5 | ) 6 | usher usher@163.com" 7 | 13345078901 -------------------------------------------------------------------------------- /protobuf/test_addressbook.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from proto import addressbook_pb2 4 | 5 | addressbook = addressbook_pb2.AddressBook() 6 | 7 | person = addressbook.person.add() 8 | person.id = 1 9 | person.name = "yubo" 10 | person.email = "yubo1911@163.com" 11 | phone = person.phone.add() 12 | phone.number = "13345678901" 13 | phone.type = addressbook_pb2.Person.HOME 14 | 15 | person2 = addressbook.person.add() 16 | person2.id = 2 17 | person2.name = "usher" 18 | person2.email = "usher@163.com" 19 | phone2 = person2.phone.add() 20 | phone2.number = "13345078901" 21 | phone2.type = addressbook_pb2.Person.HOME 22 | 23 | with open("serialized.txt", "wb") as f: 24 | f.write(addressbook.SerializeToString()) 25 | 26 | addressbook2 = addressbook_pb2.AddressBook() 27 | with open("serialized.txt", "rb") as f: 28 | addressbook2.ParseFromString(f.read()) 29 | 30 | print(addressbook2.person[0].name) 31 | -------------------------------------------------------------------------------- /py-refresh/py_records.txt: -------------------------------------------------------------------------------- 1 | >>> import test_refresh as tr 2 | 1.0 3 | >>> import test_refresh as tr 4 | >>> # edit version=2.0 5 | >>> import test_refresh as tr 6 | >>> tr.version 7 | 1.0 8 | >>> del sys.modules['test_refresh'] 9 | >>> import test_refresh as tr 10 | 2.0 11 | >>> tr.version 12 | 2.0 13 | # edit version=3.0 14 | >>> del sys.modules['test_refresh'] 15 | >>> tr = __import__('test_refresh') 16 | 3.0 17 | >>> tr.version 18 | 3.0 19 | #edit version = 4.0 20 | >>> reload(tr) 21 | 4.0 22 | 23 | >>> tr.version 24 | 4.0 25 | 26 | >>> a = tr.RefreshClass() 27 | >>> a.value 28 | 1 29 | >>> a.print_info() 30 | RefreshClass value: 1 ver1.0 31 | 32 | # edit print_info ver2.0 33 | >>> reload(tr) 34 | 4.0 35 | 36 | >>> a.value 37 | 1 38 | >>> a.print_info() 39 | RefreshClass value: 1 ver1.0 40 | 41 | >>> b = tr.RefreshClass() 42 | >>> b.value 43 | 2 44 | >>> b.print_info() 45 | RefreshClass value: 2 ver2.0 46 | 47 | >>> a.print_info 48 | > 49 | >>> b.print_info 50 | > 51 | >>> tr.RefreshClass.print_info 52 | 53 | 54 | >>> a.__class__ = tr.RefreshClass 55 | >>> a.value 56 | 1 57 | >>> a.print_info() 58 | RefreshClass value: 1 ver2.0 59 | 60 | >>> reload(tr) 61 | 4.0 62 | 63 | >>> a.print_info.im_func 64 | 65 | >>> c = tr.RefreshClass() 66 | >>> c.print_info() 67 | RefreshClass value: 3 ver3.0 68 | >>> c.print_info.im_func 69 | 70 | >>> a.__class__ = tr.RefreshClass 71 | >>> a.print_info.im_func 72 | 73 | >>> a.print_info() 74 | RefreshClass value: 1 ver3.0 75 | >>> 76 | 77 | -------------------------------------------------------------------------------- /py-refresh/py_trigger.txt: -------------------------------------------------------------------------------- 1 | kill -SIGUSR1 pid 2 | -------------------------------------------------------------------------------- /py-refresh/refresh_class.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | class RefreshClass(object): 5 | def __init__(self): 6 | self.value = 1 7 | 8 | def print_info(self): 9 | print('RefreshClass value: {} ver2.0'.format(self.value)) 10 | -------------------------------------------------------------------------------- /py-refresh/test_refresh.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import print_function 3 | 4 | import time 5 | import signal 6 | 7 | import refresh_class 8 | 9 | rc = refresh_class.RefreshClass() 10 | 11 | 12 | def handl_refresh(signum, frame): 13 | reload(refresh_class) 14 | rc.__class__ = refresh_class.RefreshClass 15 | 16 | 17 | signal.signal(signal.SIGUSR1, handl_refresh) 18 | while True: 19 | time.sleep(5) 20 | rc.print_info() 21 | -------------------------------------------------------------------------------- /pylibtravel/docopt/example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo './py-grep . "(\w)+@(\w)+((\.\w+)+)" --ignorepath ./test_path1' 3 | ./py-grep . "(\w)+@(\w)+((\.\w+)+)" --ignorepath ./test_path1 4 | echo '====================' 5 | echo './py-grep . "(\w)+@(\w)+((\.\w+)+)" --ignorepath test_path1' 6 | ./py-grep . "(\w)+@(\w)+((\.\w+)+)" --ignorepath test_path1 7 | -------------------------------------------------------------------------------- /pylibtravel/docopt/py-grep: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Usage: 5 | py-grep [-i] [--ignorepath ...] 6 | py-grep (-h | --help) 7 | 8 | Options: 9 | -h --help Show this screen 10 | -i Ignore case 11 | --ignore_paths Ignored directories 12 | """ 13 | import os 14 | import re 15 | from docopt import docopt 16 | 17 | 18 | def py_grep(search_path, pattern, ignore_paths=None): 19 | ignore_paths = ignore_paths if ignore_paths else [] 20 | ignore_paths = [os.path.abspath(p) for p in ignore_paths] 21 | for parent, dirnames, filenames in os.walk(search_path): 22 | abs_parent = os.path.abspath(parent) 23 | is_ignore = False 24 | for ig_path in ignore_paths: 25 | if abs_parent.startswith(ig_path): 26 | is_ignore = True 27 | break 28 | if is_ignore: 29 | continue 30 | for fn in filenames: 31 | fn = os.path.join(parent, fn) 32 | with open(fn, 'r') as fobj: 33 | for n, line in enumerate(fobj): 34 | if pattern.search(line): 35 | print fn, n+1, ':', line.strip() 36 | return 37 | 38 | def main(): 39 | args = docopt(__doc__, version="py-grep") 40 | 41 | if args['-i']: 42 | pattern = re.compile(args[''], re.IGNORECASE) 43 | else: 44 | pattern = re.compile(args['']) 45 | 46 | kwargs = { 47 | 'search_path': args[''], 48 | 'pattern': pattern, 49 | 'ignore_paths': args[''], 50 | } 51 | py_grep(**kwargs) 52 | return 53 | 54 | if __name__ == "__main__": 55 | main() 56 | -------------------------------------------------------------------------------- /pylibtravel/docopt/test_file1: -------------------------------------------------------------------------------- 1 | I am a programmer. 2 | My email is yubo1911@163.com. 3 | I am 27 years old. 4 | I have another email: usher@gmail.com 5 | -------------------------------------------------------------------------------- /pylibtravel/docopt/test_path1/inner_path/test_file4: -------------------------------------------------------------------------------- 1 | I am a programmer. 2 | My email is yubo1911@163.com. 3 | I am 27 years old. 4 | I have another email: usher@gmail.com 5 | -------------------------------------------------------------------------------- /pylibtravel/docopt/test_path1/test_file2: -------------------------------------------------------------------------------- 1 | I am a programmer. 2 | My email is yubo1911@163.com. 3 | I am 27 years old. 4 | I have another email: usher@gmail.com 5 | -------------------------------------------------------------------------------- /pylibtravel/docopt/test_path2/test_file3: -------------------------------------------------------------------------------- 1 | I am a programmer. 2 | My email is yubo1911@163.com. 3 | I am 27 years old. 4 | I have another email: usher@gmail.com 5 | -------------------------------------------------------------------------------- /pylibtravel/grpc/echo_client.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import print_function 3 | import grpc 4 | import echo_server_pb2 5 | import sys 6 | 7 | 8 | if sys.version_info.major == 3: 9 | raw_input = input 10 | else: 11 | raw_input = raw_input 12 | 13 | 14 | def run(): 15 | channel = grpc.insecure_channel('localhost:50015') 16 | stub = echo_server_pb2.EchoServerStub(channel) 17 | while True: 18 | msg = raw_input('you say:') 19 | reply = stub.Echo(echo_server_pb2.EchoRequest(msg=msg)) 20 | print(reply.msg) 21 | pass 22 | 23 | if __name__ == "__main__": 24 | run() 25 | -------------------------------------------------------------------------------- /pylibtravel/grpc/echo_server.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package echo_server; 4 | 5 | service EchoServer 6 | { 7 | rpc Echo (EchoRequest) returns (EchoReply) {} 8 | } 9 | 10 | message EchoRequest 11 | { 12 | string msg = 1; 13 | } 14 | 15 | message EchoReply 16 | { 17 | string msg = 1; 18 | } 19 | -------------------------------------------------------------------------------- /pylibtravel/grpc/echo_server.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from concurrent import futures 3 | import grpc 4 | import time 5 | import echo_server_pb2 6 | 7 | 8 | class EchoServer(echo_server_pb2.EchoServerServicer): 9 | def Echo(self, request, context): 10 | return echo_server_pb2.EchoReply(msg='echo:%s' % request.msg) 11 | 12 | 13 | def serve(): 14 | server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) 15 | echo_server_pb2.add_EchoServerServicer_to_server(EchoServer(), server) 16 | server.add_insecure_port('[::]:50015') 17 | server.start() 18 | try: 19 | while True: 20 | time.sleep(60*60) 21 | except KeyboardInterrupt: 22 | server.stop(0) 23 | 24 | if __name__ == "__main__": 25 | serve() 26 | -------------------------------------------------------------------------------- /pylibtravel/grpc/run_codegen.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from grpc.tools import protoc 4 | 5 | protoc.main( 6 | ( 7 | '', 8 | '-I.', 9 | '--python_out=.', 10 | '--grpc_python_out=.', 11 | './echo_server.proto', 12 | ) 13 | ) 14 | -------------------------------------------------------------------------------- /pylibtravel/mmap/del_rule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | import mmap 4 | from docopt import docopt 5 | import logging 6 | import re 7 | 8 | logging.basicConfig() 9 | logger = logging.getLogger() 10 | logger.setLevel(logging.INFO) 11 | 12 | fmt = '\(CSV_2_DIR\)/(\S+\.csv)' 13 | pattern = re.compile(fmt, re.U) 14 | 15 | 16 | def del_rule(filename, rule): 17 | csv_files = [] 18 | with open(filename, 'r+') as f: 19 | mm = mmap.mmap(f.fileno(), 0) 20 | start_pos = end_pos = 0 21 | line = mm.readline() 22 | force_delete = False 23 | while line: 24 | if force_delete: 25 | start_pos = mm.tell() - len(line) 26 | end_pos = mm.tell() 27 | mm[start_pos: end_pos] = ' '*(end_pos-start_pos) 28 | force_delete = False 29 | logger.info('force delete...') 30 | 31 | elif rule in line: 32 | start_pos = mm.tell() - len(line) 33 | end_pos = mm.tell() 34 | split_pos = line.find(':') 35 | start_pos += split_pos + 1 36 | logger.debug('{} {}'.format(start_pos, end_pos)) 37 | mm[start_pos: end_pos] = ' '*(end_pos-start_pos-1) + '\n' 38 | force_delete = True 39 | logger.info('delete {}'.format(rule)) 40 | 41 | sm = pattern.search(line) 42 | if sm: 43 | csv_files.append(sm.group(1)) 44 | line = mm.readline() 45 | 46 | mm.close() 47 | 48 | return csv_files 49 | 50 | 51 | if __name__ == "__main__": 52 | doc = """Usage: 53 | del_rule.py 54 | del_rule.py (-h | --help) 55 | 56 | Options: 57 | -h --help Show this screen 58 | """ 59 | args = docopt(doc, version="del_rule ver1.0") 60 | csv_files = del_rule(args[''], args['']) 61 | for fn in csv_files: 62 | logger.info('found csv files: {}'.format(fn)) 63 | -------------------------------------------------------------------------------- /pylibtravel/mmap/test.conf: -------------------------------------------------------------------------------- 1 | d_sb_xiuwei.txt: $(CSV_2_DIR)/幻化吸收修为限制.csv $(CSV2PY_DIR)/sb_xiuwei.py 2 | | $(CSV2PY) sb_xiuwei $< $@ 3 | 4 | d_item_shop_ad.txt: 5 | 6 | d_sphere_cq_box.txt: 7 | 8 | d_sphere_cq_npc.txt: 9 | 10 | d_sch_rebuild_event.txt: 11 | 12 | d_sch_degree_event.txt: $(CSV_2_DIR)/进度事件对应表.csv $(CSV2PY_DIR)/sch_degree_event.py 13 | | $(CSV2PY) sch_degree_event $< $@ 14 | 15 | d_sch_degree_contrib.txt: $(CSV_2_DIR)/进度贡献对应表.csv $(CSV2PY_DIR)/sch_degree_contrib.py 16 | | $(CSV2PY) sch_degree_contrib $< $@ 17 | 18 | d_online_guaji_rule.txt: $(CSV_2_DIR)/在线经验技能点声望奖励表.csv $(CSV2PY_DIR)/online_guaji_rule.py 19 | | $(CSV2PY) online_guaji_rule $< $@ 20 | 21 | d_online_pick_npc.txt: $(CSV_2_DIR)/提交物品抽奖.csv $(CSV2PY_DIR)/online_pick_npc.py 22 | | $(CSV2PY) online_pick_npc $< $@ 23 | -------------------------------------------------------------------------------- /pylibtravel/mmap/test.conf.bak: -------------------------------------------------------------------------------- 1 | d_sb_xiuwei.txt: $(CSV_2_DIR)/幻化吸收修为限制.csv $(CSV2PY_DIR)/sb_xiuwei.py 2 | | $(CSV2PY) sb_xiuwei $< $@ 3 | 4 | d_item_shop_ad.txt: 5 | 6 | d_sphere_cq_box.txt: $(CSV_2_DIR)/副本环形任务box表.csv $(CSV2PY_DIR)/sphere_cq_entity.py 7 | | $(CSV2PY) sphere_cq_entity $< $@ 8 | 9 | d_sphere_cq_npc.txt: $(CSV_2_DIR)/副本环形任务npc表.csv $(CSV2PY_DIR)/sphere_cq_entity.py 10 | | $(CSV2PY) sphere_cq_entity $< $@ 11 | 12 | d_sch_rebuild_event.txt: 13 | 14 | d_sch_degree_event.txt: $(CSV_2_DIR)/进度事件对应表.csv $(CSV2PY_DIR)/sch_degree_event.py 15 | | $(CSV2PY) sch_degree_event $< $@ 16 | 17 | d_sch_degree_contrib.txt: $(CSV_2_DIR)/进度贡献对应表.csv $(CSV2PY_DIR)/sch_degree_contrib.py 18 | | $(CSV2PY) sch_degree_contrib $< $@ 19 | 20 | d_online_guaji_rule.txt: $(CSV_2_DIR)/在线经验技能点声望奖励表.csv $(CSV2PY_DIR)/online_guaji_rule.py 21 | | $(CSV2PY) online_guaji_rule $< $@ 22 | 23 | d_online_pick_npc.txt: $(CSV_2_DIR)/提交物品抽奖.csv $(CSV2PY_DIR)/online_pick_npc.py 24 | | $(CSV2PY) online_pick_npc $< $@ 25 | -------------------------------------------------------------------------------- /pylibtravel/mmap/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./del_rule.py sphere_cq_entity.py test.conf 3 | -------------------------------------------------------------------------------- /redis-py/redis_friends.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import web 4 | import time 5 | import redis 6 | 7 | r = redis.StrictRedis() 8 | 9 | urls = ( 10 | '/', 'visit', 11 | '/online', 'online' 12 | ) 13 | 14 | app = web.application(urls, globals()) 15 | 16 | 17 | def time_to_key(current_time): 18 | return 'active.users:' + time.strftime('%M', time.localtime(current_time)) 19 | 20 | 21 | def keys_in_last_10_minutes(): 22 | now = time.time() 23 | result = [] 24 | for i in range(10): 25 | result.append(time_to_key(now - i * 60)) 26 | return result 27 | 28 | 29 | class visit: 30 | def GET(self): 31 | user_id = web.ctx.env['HTTP_USER_AGENT'] 32 | current_key = time_to_key(time.time()) 33 | pipe = r.pipeline() 34 | pipe.sadd(current_key, user_id) 35 | pipe.expire(current_key, 10 * 60) 36 | pipe.execute() 37 | 38 | return 'User:\t' + user_id + '\r\nKey:\t' + current_key 39 | 40 | 41 | class online: 42 | def GET(self): 43 | online_users = r.sunion(keys_in_last_10_minutes()) 44 | result = '' 45 | for user in online_users: 46 | result += 'User agent:' + user + '\r\n' 47 | return result 48 | 49 | 50 | if __name__ == "__main__": 51 | app.run() 52 | -------------------------------------------------------------------------------- /redis-py/test_redis.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import redis 3 | 4 | r = redis.StrictRedis(host='127.0.0.1', port=6379, db=0) 5 | r.set('foo', 'bar') 6 | print r.get('foo') 7 | 8 | r.hmset('dict', {'name': 'Bob'}) 9 | people = r.hgetall('dict') 10 | print people 11 | 12 | pipe = r.pipeline() 13 | pipe.set('foo', 'bar') 14 | pipe.get('foo') 15 | result = pipe.execute() 16 | print result 17 | -------------------------------------------------------------------------------- /roi/LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yubo1911/saber/aba4efee1afa10ef582f705fbd1d4d2a4829c413/roi/LICENSE -------------------------------------------------------------------------------- /roi/Makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | CPPFLAGS=-g -O2 -Wall -Wextra -Isrc -rdynamic -std=c++11 -DNDEBUG $(OPTFLAGS) 3 | LDLIBS=-ldl -luv $(OPTLIBS) 4 | PREFIX?=/usr/local 5 | 6 | SOURCES=$(wildcard src/olist.cpp src/proto.cpp) 7 | OBJECTS=$(patsubst %.cpp,%.o,$(SOURCES)) 8 | 9 | TEST_SRC=$(wildcard tests/*_tests.cpp) 10 | TESTS=$(patsubst %.cpp,%,$(TEST_SRC)) 11 | 12 | SERVER_SRC=$(wildcard src/gserver.cpp) 13 | SERVER=$(patsubst %.cpp,%,$(SERVER_SRC)) 14 | 15 | CLIENT_SRC=$(wildcard src/gclient.cpp) 16 | CLIENT=$(patsubst %.cpp,%,$(CLIENT_SRC)) 17 | 18 | TARGET=build/libroi.a 19 | SO_TARGET=$(patsubst %.a,%.so,$(TARGET)) 20 | 21 | all: $(TARGET) $(SO_TARGET) server client tests 22 | 23 | dev: CFLAGS=-g -Wall -Isrc -Wall -Wextra $(OPTFLAGS) 24 | dev: all 25 | 26 | $(TARGET): CPPFLAGS += -fPIC 27 | $(TARGET): build $(OBJECTS) 28 | ar rcs $@ $(OBJECTS) 29 | ranlib $@ 30 | 31 | $(SO_TARGET): $(TARGET) $(OBJECTS) 32 | $(CC) -shared -o $@ $(OBJECTS) 33 | 34 | build: 35 | @mkdir -p build 36 | @mkdir -p bin 37 | 38 | .PHONY: tests 39 | tests: LDLIBS += $(TARGET) 40 | tests: $(TESTS) 41 | sh ./tests/runtests.sh 42 | 43 | .PHONY: server 44 | server: LDLIBS += $(TARGET) 45 | server: $(SERVER) 46 | 47 | .PHONY: client 48 | client: LDLIBS += $(TARGET) 49 | client: $(CLIENT) 50 | 51 | valgrind: 52 | VALGRIND="valgrind --log-file=/tmp/valgrind-%p.log" $(MAKE) 53 | 54 | clean: 55 | rm -rf build $(OBJECTS) $(TESTS) $(SERVER) $(CLIENT) 56 | rm -f tests/tests.log 57 | find . -name "*.gc*" -exec rm {} \; 58 | rm -rf `find . -name "*.dSYM" -print` 59 | 60 | install: all 61 | install -d $(DESTDIR)/$(PREFIX)/lib/ 62 | install $(TARGET) $(DESTDIR)/$(PREFIX)/lib/ 63 | 64 | BADFUNC='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)' 65 | check: 66 | @echo Files with potentially dangerous functions. 67 | @egrep $(BADFUNC) $(SOURCES) || true 68 | -------------------------------------------------------------------------------- /roi/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yubo1911/saber/aba4efee1afa10ef582f705fbd1d4d2a4829c413/roi/README.md -------------------------------------------------------------------------------- /roi/src/dbg.h: -------------------------------------------------------------------------------- 1 | #ifndef _dbg_h 2 | #define _dbg_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define debug(M, ...) 10 | #else 11 | #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 17 | 18 | #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 21 | 22 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 23 | 24 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 25 | 26 | #define check_mem(A) check((A), "Out of memory.") 27 | 28 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /roi/src/entity.h: -------------------------------------------------------------------------------- 1 | #ifndef _entity_h 2 | #define _entity_h 3 | 4 | #include 5 | #include 6 | #include "olist.h" 7 | 8 | typedef struct Entity 9 | { 10 | uv_stream_t *client; 11 | unsigned int id; 12 | char *repr; 13 | std::set *roi_entities; 14 | } Entity; 15 | 16 | typedef struct ClientEntity 17 | { 18 | unsigned int id; 19 | double pos[COORD_NUM]; 20 | uv_stream_t *server; 21 | } ClientEntity; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /roi/src/olist.h: -------------------------------------------------------------------------------- 1 | #ifndef olist_h 2 | #define olist_h 3 | 4 | #include 5 | #include 6 | 7 | struct OListNode; 8 | #define MAX_ROI_NUM 30 9 | 10 | #define COORD_NUM 2 11 | #define COORD_X 0 12 | #define COORD_Y 1 13 | 14 | typedef struct OListNode 15 | { 16 | struct OListNode *next[COORD_NUM]; 17 | struct OListNode *prev[COORD_NUM]; 18 | double pos[COORD_NUM]; 19 | void *value; 20 | } OListNode; 21 | 22 | typedef struct OList 23 | { 24 | int count; 25 | OListNode *first[COORD_NUM]; 26 | OListNode *last[COORD_NUM]; 27 | } OList; 28 | 29 | OList *OList_create(); 30 | void OList_destroy(OList *list); 31 | void OList_clear(OList *list); 32 | void OList_clear_destroy(OList *list); 33 | 34 | #define OList_count(A) ((A)->count) 35 | #define OList_first(A, N) ((A)->first[N] != NULL ? (A)->first[N] : NULL) 36 | #define OList_last(A, N) ((A)->last[N] != NULL ? (A)->last[N] : NULL) 37 | 38 | void OList_insert(OList *list, OListNode *node); 39 | void *OList_remove(OList *list, OListNode *node); 40 | void OList_remove_without_free(OList *list, OListNode *node, int removex, int removey); 41 | void OList_roi(OList *list, OListNode *node, double rangex, double rangey, std::set &roi); 42 | int OList_out_range(OListNode *from, OListNode *to, double rangex, double rangey, int *stopx, int *stopy); 43 | int OList_has_add_to_roi(std::set &roi, OListNode* node); 44 | void OList_tranvers(OList *list); 45 | void OList_move(OList *list, OListNode *node, double deltax, double deltay); 46 | OListNode *OList_find_place(OList *list, OListNode *node, int xy, double delta); 47 | 48 | //void OList_push(List *list, void *value); 49 | //void *OList_pop(List *list); 50 | 51 | //void List_unshift(List *list, void *value); 52 | //void *List_shift(List *list); 53 | 54 | #define LIST_FOREACH(L, S, M, V) OListNode *_node = NULL;\ 55 | OListNode *V = NULL;\ 56 | for(V = _node = L->S; _node != NULL; V = _node = _node->M) 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /roi/src/proto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "proto.h" 6 | 7 | std::map* > cache_msg; 8 | void get_cmd_from_cache_msg(char *data, unsigned int &len, uv_stream_t *client); 9 | 10 | void push_data_to_cache_msg(char *data, int nread, uv_stream_t *client) 11 | { 12 | if(cache_msg.count(client) <= 0) 13 | { 14 | cache_msg[client] = new std::deque(); 15 | } 16 | 17 | for(int i = 0; i < nread; i++) 18 | { 19 | cache_msg[client]->push_back(data[i]); 20 | } 21 | } 22 | 23 | void get_one_cmd_from_cache_msg(char *data, unsigned int &len, uv_stream_t **client) 24 | { 25 | for(auto it = cache_msg.begin(); it != cache_msg.end(); it++) 26 | { 27 | get_cmd_from_cache_msg(data, len, it->first); 28 | if(len > 0) 29 | { 30 | *client = it->first; 31 | return; 32 | } 33 | } 34 | } 35 | 36 | void get_cmd_from_cache_msg(char *data, unsigned int &len, uv_stream_t *client) 37 | { 38 | if(cache_msg.count(client) <= 0) 39 | { 40 | len = 0; 41 | return; 42 | } 43 | if(cache_msg[client]->size() < 5) 44 | { 45 | len = 0; 46 | return; 47 | } 48 | if(cache_msg[client]->at(0) != (char)0xff) 49 | { 50 | std::cerr<<"Wrong msg format"<at(i); 57 | } 58 | unsigned int ulen = *((unsigned int *)clen); 59 | if(cache_msg[client]->size() < ulen) 60 | { 61 | len = 0; 62 | return; 63 | } 64 | len = ulen - 5; 65 | for(size_t i = 0; i < ulen; i++) 66 | { 67 | if(i < 5) 68 | { 69 | cache_msg[client]->pop_front(); 70 | continue; 71 | } 72 | data[i - 5] = cache_msg[client]->front(); 73 | cache_msg[client]->pop_front(); 74 | } 75 | return; 76 | } 77 | -------------------------------------------------------------------------------- /roi/src/proto.h: -------------------------------------------------------------------------------- 1 | #ifndef _proto_h 2 | #define _proto_h 3 | #include 4 | 5 | #define CMD_NEW 0x01 // CMD | X | Y 6 | #define CMD_MV 0x02 // CMD | ID | DX | DY 7 | #define CMD_GONE 0x03 // CMD | ID 8 | #define CMD_SC_ROI_ADD 0x04 // CMD | ID | NUM | TGT_ID | X | Y | TGT_ID | X | Y | ... 9 | #define CMD_SC_ROI_RM 0x05 // CMD | ID | NUM | TGT_ID | X | Y | TGT_ID | X | Y | ... 10 | #define CMD_SC_NEW 0x06 // CMD | ID | X | Y 11 | #define CMD_SC_ROI_MV 0x07 // CMD | ID | NUM | TGT_ID | X | Y | TGT_ID | X | Y | ... 12 | 13 | #define PROTO_START 0xff // 0xff | len | CMD_DATA 14 | 15 | void push_data_to_cache_msg(char *data, int nread, uv_stream_t *client); 16 | void get_one_cmd_from_cache_msg(char *data, unsigned int &len, uv_stream_t **client); 17 | #endif 18 | -------------------------------------------------------------------------------- /roi/tests/dbg.h: -------------------------------------------------------------------------------- 1 | #ifndef _dbg_h 2 | #define _dbg_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef NDEBUG 9 | #define debug(M, ...) 10 | #else 11 | #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 12 | #endif 13 | 14 | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 15 | 16 | #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 17 | 18 | #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 19 | 20 | #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d: errno: %s)" M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 21 | 22 | #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 23 | 24 | #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } 25 | 26 | #define check_mem(A) check((A), "Out of memory.") 27 | 28 | #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /roi/tests/minunit.h: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #ifndef _minunit_h 3 | #define _minunit_h 4 | 5 | #include 6 | #include 7 | #include "dbg.h" 8 | 9 | #define mu_suite_start() const char *message = NULL 10 | 11 | #define mu_assert(test, message) if (!(test)) {log_err(message); return message;} 12 | #define mu_run_test(test) debug("\n--------%s", ""#test); \ 13 | message = test(); tests_run++; if (message) return message; 14 | 15 | #define RUN_TESTS(name) int main(int argc, char *argv[]) \ 16 | {\ 17 | argc = 1;\ 18 | debug("------RUNNING: %s", argv[0]);\ 19 | printf("------\nRUNNING: %s\n", argv[0]);\ 20 | const char *result = name();\ 21 | if (result != 0) \ 22 | {\ 23 | printf("FAILED: %s\n", result);\ 24 | }\ 25 | else\ 26 | {\ 27 | printf("ALL TESTS PASSED\n");\ 28 | }\ 29 | printf("Tests run: %d\n", tests_run);\ 30 | exit(result != 0);\ 31 | } 32 | 33 | int tests_run; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /roi/tests/runtests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Running unit test:" 4 | 5 | for i in tests/*_tests 6 | do 7 | if test -f $i 8 | then 9 | if $VALGRIND ./$i 2>> tests/tests.log 10 | then 11 | echo $i PASS 12 | else 13 | echo "ERROR in test $i: here's tests/tests.log" 14 | echo "---" 15 | tail tests/tests.log 16 | exit 1 17 | fi 18 | fi 19 | done 20 | 21 | echo "" 22 | -------------------------------------------------------------------------------- /shared_memory/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | g++ test_boost_shared_memory.cc -pthread -lrt --std=c++11 -o test 3 | -------------------------------------------------------------------------------- /shared_memory/test_boost_shared_memory.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(void) 8 | { 9 | using namespace boost::interprocess; 10 | 11 | shared_memory_object::remove("MyMemory"); 12 | 13 | managed_shared_memory segment(create_only, "MyMemory", 65535); 14 | std::string name; 15 | for(int i=0; i<100; ++i) 16 | { 17 | char cname[16]; 18 | snprintf(cname, 16, "child%d", i); 19 | name = cname; 20 | segment.construct(cname)(name); 21 | } 22 | pid_t fpid; 23 | fpid = fork(); 24 | if(fpid < 0) 25 | { 26 | printf("error in fork..."); 27 | } 28 | else if(fpid == 0) 29 | { 30 | // child 31 | managed_shared_memory segment(open_only, "MyMemory"); 32 | for(int i=0; i<100; ++i) 33 | { 34 | char cname[16]; 35 | snprintf(cname, 16, "child%d", i); 36 | std::string *name = segment.find(cname).first; 37 | printf("child found in shared memory %s\n", name->c_str()); 38 | } 39 | shared_memory_object::remove("MyMemory"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ssh/get_mysql_dump.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import paramiko 3 | import time 4 | import os 5 | 6 | def ssh_mysql_dump(ip, port, db_name, tbl_name, dump_name, t1, t2): 7 | try: 8 | ssh = paramiko.SSHClient() 9 | ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 10 | ssh.connect(ip, port, 'username', 'PASSWORD', timeout=5) 11 | 12 | mysqldump_cmd = 'mysqldump -uroot %s %s -w "t_when > from_unixtime(%d) and t_when < from_unixtime(%d)" > %s' % (db_name, tbl_name, t1, t2, dump_name) 13 | print mysqldump_cmd 14 | ok = ssh_exec_cmd_helper(ssh, mysqldump_cmd, ip) 15 | if not ok: 16 | return 17 | ssh.close() 18 | except Exception, e: 19 | print ip, 'ssh_mysql_dump Error', e 20 | 21 | username = 'username' 22 | privatekey = os.path.expanduser('~/.ssh/id_rsa') 23 | mykey = paramiko.RSAKey.from_private_key_file(privatekey, password='PASSWORD') 24 | transport = paramiko.Transport((ip, port)) 25 | transport.connect(username=username, pkey=mykey) 26 | 27 | sftp = paramiko.SFTPClient.from_transport(transport) 28 | sftp.get('/home/yourname/%s' % dump_name, '/home/yourname/download/mysqldump-to-csv/%s' % dump_name) 29 | sftp.close() 30 | transport.close() 31 | 32 | 33 | def mysqldump_to_csv(dump_name, csv_name): 34 | try: 35 | mysqldump_to_csv_cmd = 'cd ~/download/mysqldump-to-csv/ && python mysqldump_to_csv.py %s > %s' % (dump_name, csv_name) 36 | os.system(mysqldump_to_csv_cmd) 37 | except Exception, e: 38 | print 'mysqldump_to_csv Error', e 39 | 40 | 41 | def ssh_exec_cmd_helper(ssh, cmd, ip): 42 | stdin, stdout, stderr = ssh.exec_command(cmd) 43 | errors = stderr.readlines() 44 | if errors: 45 | print ip, cmd, errors 46 | return False 47 | 48 | return True 49 | 50 | if __name__ == "__main__": 51 | ip = 'your.remote.ip.addr' 52 | port = 22 53 | db_name = 'your_db_name' 54 | tbl_name = 'your_tbl_name' 55 | dump_name = 'dumpname.db' 56 | csv_name = 'csvname.csv' 57 | t2 = int(time.time()) 58 | t1 = t2 - 86400 * 30 59 | print 'ssh mysqldump...' 60 | ssh_mysql_dump(ip, port, db_name, tbl_name, dump_name, t1, t2) 61 | print 'mysqldump to csv...' 62 | mysqldump_to_csv(dump_name, csv_name) 63 | print 'done!' 64 | 65 | 66 | --------------------------------------------------------------------------------