├── .clang-format ├── .gitignore ├── LICENSE ├── README.md ├── c ├── epoll │ ├── README.md │ ├── epoll_two_layered │ │ ├── README.md │ │ └── main.c │ ├── tcp-client-server │ │ ├── Makefile │ │ └── main.c │ ├── tcp-client-server1 │ │ ├── Makefile │ │ ├── client.c │ │ └── server.c │ ├── tcp-server │ │ ├── Makefile │ │ └── main.c │ └── tcp │ │ ├── Makefile │ │ ├── common.c │ │ ├── common.h │ │ ├── epoll-client.c │ │ └── epoll-server.c ├── glib │ ├── README.md │ ├── datetime │ │ └── main.c │ ├── giochannel │ │ ├── cat_file.c │ │ ├── cp_file.c │ │ └── giochannel_main_loop.c │ ├── main_event_loop │ │ ├── CMakeLists.txt │ │ └── main.c │ ├── socket │ │ └── tcp │ │ │ ├── tcp_client.c │ │ │ └── tcp_server.c │ ├── source │ │ └── main.c │ ├── testing │ │ ├── README.md │ │ └── simple.c │ ├── timeout │ │ ├── custom_ctx.c │ │ └── default_ctx.c │ └── version │ │ └── main.c ├── iov │ ├── README.md │ ├── file_readv.c │ ├── file_writev.c │ └── writev.c ├── jansson │ ├── README.md │ └── github_commits.c ├── jsmn │ ├── jsondump │ │ ├── CMakeLists.txt │ │ ├── jsmn.h │ │ ├── main.c │ │ └── start_build.sh │ └── simple │ │ ├── CMakeLists.txt │ │ ├── jsmn.h │ │ ├── main.c │ │ └── start_build.sh ├── kernel │ ├── docker_mount_namespace.c │ ├── ipc_namespace.c │ ├── mount_namespace.c │ ├── pid_namespace.c │ ├── simple_clone.c │ ├── user_namespace.c │ └── uts_namespace.c ├── lib-implement │ └── memcpy.c ├── lldb │ └── main.c ├── nginx │ └── rbtree │ │ ├── rbtree.c │ │ ├── rbtree.h │ │ └── rbtree_test.c ├── protobuf-c │ ├── README.md │ ├── genpb.sh │ ├── mpb │ │ ├── amessage.pb-c.c │ │ └── amessage.pb-c.h │ ├── proto │ │ └── amessage.proto │ ├── receiver.c │ └── sender.c ├── script │ └── script.c ├── select │ └── main.c ├── socket │ ├── README.md │ ├── gethostbyname │ │ ├── CMakeLists.txt │ │ └── main.c │ ├── rawtcp │ │ ├── CMakeLists.txt │ │ └── main.c │ ├── tcpclient │ │ ├── CMakeLists.txt │ │ └── main.c │ ├── tcpserver │ │ ├── CMakeLists.txt │ │ └── main.c │ ├── tcpserver_pthread │ │ ├── CMakeLists.txt │ │ └── main.c │ ├── udpclient │ │ ├── CMakeLists.txt │ │ └── main.c │ └── udpechoserver │ │ ├── CMakeLists.txt │ │ └── main.c ├── split │ ├── main.c │ ├── strsplit.c │ └── strsplit.h ├── tcmalloc │ └── memory_error_notcmalloc.cpp ├── trim │ ├── main.c │ ├── trim.c │ └── trim.h └── uuid │ └── uuid_generate.c ├── cpp ├── array │ ├── contain.cc │ └── interaction.cc ├── boost │ ├── README.md │ ├── bimap │ │ ├── README.md │ │ ├── basic │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── student │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── tag │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ └── unconstrained-set-of │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ ├── container │ │ ├── list_emplace │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── move_container │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ └── vector_move_container │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ ├── multi_index │ │ ├── README.md │ │ ├── basic │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── const_mem_fun │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── multiple_sorts │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── project │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── simple │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ ├── tag │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ │ └── word_count │ │ │ ├── CMakeLists.txt │ │ │ └── main.cpp │ └── program_options │ │ ├── README.md │ │ └── first.cpp ├── cast │ └── reinterpret_cast.cc ├── cgen │ └── cppclass │ │ └── cpplib │ │ ├── main.c │ │ ├── main.cc │ │ ├── my_class.cc │ │ ├── my_class.h │ │ ├── my_wrapper.cc │ │ └── my_wrapper.h ├── class │ └── virtual.cpp ├── const │ └── variable.cc ├── constexpr │ └── main.cpp ├── cpprestsdk │ ├── CMakeLists.txt │ └── bing_request.cc ├── endian │ └── is_little_endian.cpp ├── exception │ ├── new_exception.cc │ └── try_catch_throw.cc ├── gengetopt │ ├── Makefile │ ├── README.md │ ├── app │ ├── cmdline.c │ ├── cmdline.ggo │ ├── cmdline.h │ └── main.cpp ├── gperf │ ├── Makefile │ ├── README.md │ ├── command_line.cpp │ ├── command_line_options.gperf │ └── command_options.h ├── hash │ ├── hash.cpp │ ├── hash.h │ ├── khash.h │ └── main.cpp ├── homework │ ├── assignment2.pdf │ ├── sun_hw1_q1.cpp │ └── sun_hw1_q2.cpp ├── metadata │ ├── hash.cpp │ ├── hash.h │ ├── khash.h │ ├── main.cpp │ ├── meta.txt │ ├── strsplit.cpp │ ├── strsplit.h │ ├── substr.cpp │ ├── substr.h │ ├── trim.cpp │ └── trim.h ├── rand │ ├── CMakeLists.txt │ ├── README.md │ ├── main.cpp │ └── rand.hpp ├── spdlog │ ├── basic.cc │ └── example.cc ├── stl │ └── copy │ │ └── example.cpp ├── swig │ ├── cmake-python-swig-rpath-example │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── src │ │ │ ├── CMakeLists.txt │ │ │ ├── stats.cc │ │ │ ├── stats.hh │ │ │ └── stats.i │ │ └── test │ │ │ └── test.py │ └── tutorial │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── example.c │ │ ├── example.i │ │ ├── example.py │ │ ├── example.pyc │ │ └── example_wrap.c ├── tuple │ └── tie.cpp └── vector │ ├── erase.cpp │ ├── erase_remove.cc │ ├── mem.cc │ └── push_unique.cc └── format.sh /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | TabWidth: 4 3 | IndentWidth: 4 4 | UseTab: ForIndentation 5 | SpacesBeforeTrailingComments: 1 6 | AlignTrailingComments: true 7 | AllowShortFunctionsOnASingleLine: false 8 | AllowShortIfStatementsOnASingleLine: false 9 | AllowShortLoopsOnASingleLine: false 10 | ColumnLimit: 79 11 | MaxEmptyLinesToKeep: 2 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | .idea/ 34 | 35 | # build 36 | jsmn/simple/build/ 37 | jsmn/jsondump/build/ 38 | settings.json 39 | /.vscode 40 | _builds/ 41 | build/ 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Bob Liu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # learning-c-cpp 2 | 3 | Codes while learning C and Cpp. 4 | -------------------------------------------------------------------------------- /c/epoll/README.md: -------------------------------------------------------------------------------- 1 | ## Tutorials 2 | * -------------------------------------------------------------------------------- /c/epoll/epoll_two_layered/README.md: -------------------------------------------------------------------------------- 1 | # epoll two layered scheme 2 | 3 | epoll(4) says that epoll descriptors can be added to other epoll sets. 4 | Maybe, a cascaded scheme can be implemented where each active priority level gets an epoll set for its fds, and the master epoll set contains epoll descriptors for the levels. A blocking epoll_wait is called on the master epoll descriptor, then the triggered level sets are processed with non-blocking epoll_wait accordingly to their priority. This will have acceptable performance when few priority levels are in effect, which was Oven's concern. Bizarre priority schemes will still work, too, at the cost of extra non-blocking system calls. When there is only one effective priority, the cascade can be bypassed altogether. 5 | 6 | Here's a small test that demonstrates how epoll works in the proposed two-layered scheme. To put it short: an epoll over other epoll descriptors reports "read" events on those epolls that got any events to retrieve. 7 | 8 | ## Refs 9 | * -------------------------------------------------------------------------------- /c/epoll/epoll_two_layered/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define TEST_TIMEOUT (0) 6 | 7 | static void print_events(const struct epoll_event *evts, int event_count) { 8 | int i; 9 | for (i = 0; i < event_count; i++) { 10 | printf("Event %d: %s, events=0x%x\n", i, 11 | (const char *)evts[i].data.ptr, evts[i].events); 12 | } 13 | } 14 | 15 | int main() { 16 | struct epoll_event evt; 17 | struct epoll_event retrieved_evts[3]; 18 | int thepipe[2]; 19 | int epfd_master; 20 | int epfd_slave; 21 | int event_count; 22 | 23 | epfd_slave = epoll_create1(0); 24 | if (epfd_slave < 0) { 25 | perror("Slave epoll_create failed"); 26 | return 1; 27 | } 28 | 29 | epfd_master = epoll_create1(0); 30 | if (epfd_master < 0) { 31 | perror("Master epoll_create failed"); 32 | return 1; 33 | } 34 | 35 | evt.events = EPOLLIN | EPOLLOUT; 36 | evt.data.ptr = "slave epoll"; 37 | if (epoll_ctl(epfd_master, EPOLL_CTL_ADD, epfd_slave, &evt) != 0) { 38 | perror("Master EPOLL_CTL_ADD failed"); 39 | return 1; 40 | } 41 | 42 | printf("Querying epoll events on master (empty set)..."); 43 | event_count = epoll_wait(epfd_master, retrieved_evts, 3, TEST_TIMEOUT); 44 | if (event_count >= 0) { 45 | printf(" got %d\n", event_count); 46 | print_events(retrieved_evts, event_count); 47 | } else { 48 | perror(" failed"); 49 | } 50 | 51 | if (pipe(thepipe) != 0) { 52 | perror("pipe failed"); 53 | return 1; 54 | } 55 | 56 | evt.events = EPOLLIN; 57 | evt.data.ptr = "pipe reading end"; 58 | if (epoll_ctl(epfd_slave, EPOLL_CTL_ADD, thepipe[0], &evt) != 0) { 59 | perror("Slave EPOLL_CTL_ADD for reading end failed"); 60 | return 1; 61 | } 62 | 63 | evt.events = EPOLLOUT; 64 | evt.data.ptr = "pipe writing end"; 65 | if (epoll_ctl(epfd_slave, EPOLL_CTL_ADD, thepipe[1], &evt) != 0) { 66 | perror("Slave EPOLL_CTL_ADD for writing end failed"); 67 | return 1; 68 | } 69 | 70 | printf("Querying epoll events on master (writer only)..."); 71 | event_count = epoll_wait(epfd_master, retrieved_evts, 3, TEST_TIMEOUT); 72 | if (event_count >= 0) { 73 | printf(" got %d\n", event_count); 74 | print_events(retrieved_evts, event_count); 75 | } else { 76 | perror(" failed"); 77 | } 78 | 79 | printf("Querying epoll events on slave (writer only)..."); 80 | event_count = epoll_wait(epfd_slave, retrieved_evts, 3, TEST_TIMEOUT); 81 | if (event_count >= 0) { 82 | printf(" got %d\n", event_count); 83 | print_events(retrieved_evts, event_count); 84 | } else { 85 | perror(" failed"); 86 | } 87 | 88 | if (write(thepipe[1], "hello", 5) < 0) { 89 | perror("write to the pipe failed"); 90 | } 91 | 92 | printf("Querying epoll events on master (read available)..."); 93 | event_count = epoll_wait(epfd_master, retrieved_evts, 3, TEST_TIMEOUT); 94 | if (event_count >= 0) { 95 | printf(" got %d\n", event_count); 96 | print_events(retrieved_evts, event_count); 97 | } else { 98 | perror(" failed"); 99 | } 100 | 101 | printf("Querying epoll events on slave (read available)..."); 102 | event_count = epoll_wait(epfd_slave, retrieved_evts, 3, TEST_TIMEOUT); 103 | if (event_count >= 0) { 104 | printf(" got %d\n", event_count); 105 | print_events(retrieved_evts, event_count); 106 | } else { 107 | perror(" failed"); 108 | } 109 | 110 | close(epfd_master); 111 | close(epfd_slave); 112 | close(thepipe[1]); 113 | close(thepipe[0]); 114 | 115 | return 0; 116 | } -------------------------------------------------------------------------------- /c/epoll/tcp-client-server/Makefile: -------------------------------------------------------------------------------- 1 | IDIR= 2 | CC=gcc 3 | CFLAGS= 4 | 5 | ODIR=./ 6 | LDIR= 7 | 8 | LIBS= 9 | 10 | _DEPS= 11 | DEPS=$(patsubst %,$(IDIR)/%,$(_DEPS)) 12 | 13 | _OBJ=main.o 14 | OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ)) 15 | 16 | $(ODIR)/%.o: %.c $(DEPS) 17 | $(CC) -c -o $@ $< $(CFLAGS) 18 | 19 | main: $(OBJ) 20 | gcc -o $@ $^ $(CFLAGS) $(LIBS) 21 | 22 | .PHONY: clean 23 | 24 | clean: 25 | rm -f $(ODIR)/*.o *.~ core $(INCDIR)/*~ -------------------------------------------------------------------------------- /c/epoll/tcp-client-server/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Attention: 3 | * To keep things simple, do not handle 4 | * socket/bind/listen/.../epoll_create/epoll_wait API error 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define DEFAULT_PORT (8088) 19 | #define MAX_CONN (16) 20 | #define MAX_EVENTS (32) 21 | #define BUF_SIZE (16) 22 | #define MAX_LINE (256) 23 | 24 | void server_run(); 25 | void client_run(); 26 | 27 | int main(int argc, char *argv[]) { 28 | int opt; 29 | char role = 's'; 30 | while ((opt = getopt(argc, argv, "cs")) != -1) { 31 | switch (opt) { 32 | case 'c': 33 | role = 'c'; 34 | break; 35 | case 's': 36 | break; 37 | default: 38 | printf("usage: %s [-cs]\n", argv[0]); 39 | exit(1); 40 | } 41 | } 42 | if (role == 's') { 43 | server_run(); 44 | } else { 45 | client_run(); 46 | } 47 | return 0; 48 | } 49 | 50 | /* 51 | * register events of fd to epfd 52 | */ 53 | static void epoll_ctl_add(int epfd, int fd, uint32_t events) { 54 | struct epoll_event ev; 55 | ev.events = events; 56 | ev.data.fd = fd; 57 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) { 58 | perror("epoll_ctl()\n"); 59 | exit(1); 60 | } 61 | } 62 | 63 | static void set_sockaddr(struct sockaddr_in *addr) { 64 | bzero((char *)addr, sizeof(struct sockaddr_in)); 65 | addr->sin_family = AF_INET; 66 | addr->sin_addr.s_addr = INADDR_ANY; 67 | addr->sin_port = htons(DEFAULT_PORT); 68 | } 69 | 70 | static int setnonblocking(int sockfd) { 71 | if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0) | O_NONBLOCK) == -1) { 72 | return -1; 73 | } 74 | return 0; 75 | } 76 | 77 | /* 78 | * epoll echo server 79 | */ 80 | void server_run() { 81 | int i; 82 | int n; 83 | int epfd; 84 | int nfds; 85 | int listen_sock; 86 | int conn_sock; 87 | int socklen; 88 | char buf[BUF_SIZE]; 89 | struct sockaddr_in srv_addr; 90 | struct sockaddr_in cli_addr; 91 | struct epoll_event events[MAX_EVENTS]; 92 | 93 | listen_sock = socket(AF_INET, SOCK_STREAM, 0); 94 | 95 | set_sockaddr(&srv_addr); 96 | bind(listen_sock, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); 97 | 98 | setnonblocking(listen_sock); 99 | listen(listen_sock, MAX_CONN); 100 | 101 | epfd = epoll_create(1); 102 | epoll_ctl_add(epfd, listen_sock, EPOLLIN | EPOLLOUT | EPOLLET); 103 | 104 | socklen = sizeof(cli_addr); 105 | for (;;) { 106 | nfds = epoll_wait(epfd, events, MAX_EVENTS, -1); 107 | for (i = 0; i < nfds; i++) { 108 | if (events[i].data.fd == listen_sock) { 109 | /* handle new connection */ 110 | conn_sock = accept(listen_sock, (struct sockaddr *)&cli_addr, 111 | &socklen); 112 | 113 | inet_ntop(AF_INET, (char *)&(cli_addr.sin_addr), buf, 114 | sizeof(cli_addr)); 115 | printf("[+] connected with %s:%d\n", buf, 116 | ntohs(cli_addr.sin_port)); 117 | 118 | setnonblocking(conn_sock); 119 | epoll_ctl_add(epfd, conn_sock, 120 | EPOLLIN | EPOLLET | EPOLLRDHUP | EPOLLHUP); 121 | } else if (events[i].events & EPOLLIN) { 122 | /* handle EPOLLIN event */ 123 | for (;;) { 124 | bzero(buf, sizeof(buf)); 125 | n = read(events[i].data.fd, buf, sizeof(buf)); 126 | if (n <= 0 /* || errno == EAGAIN */) { 127 | break; 128 | } else { 129 | printf("[+] data: %s\n", buf); 130 | write(events[i].data.fd, buf, strlen(buf)); 131 | } 132 | } 133 | } else { 134 | printf("[+] unexpected\n"); 135 | } 136 | /* check if the connection is closing */ 137 | if (events[i].events & (EPOLLRDHUP | EPOLLHUP)) { 138 | printf("[+] connection closed\n"); 139 | epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL); 140 | close(events[i].data.fd); 141 | continue; 142 | } 143 | } 144 | } 145 | } 146 | 147 | /* 148 | * test clinet 149 | */ 150 | void client_run() { 151 | int n; 152 | int c; 153 | int sockfd; 154 | char buf[MAX_LINE]; 155 | struct sockaddr_in srv_addr; 156 | 157 | sockfd = socket(AF_INET, SOCK_STREAM, 0); 158 | 159 | set_sockaddr(&srv_addr); 160 | 161 | if (connect(sockfd, (struct sockaddr *)&srv_addr, sizeof(srv_addr)) < 0) { 162 | perror("connect()"); 163 | exit(1); 164 | } 165 | 166 | for (;;) { 167 | printf("input: "); 168 | fgets(buf, sizeof(buf), stdin); 169 | c = strlen(buf) - 1; 170 | buf[c] = '\0'; 171 | write(sockfd, buf, c + 1); 172 | 173 | bzero(buf, sizeof(buf)); 174 | while (errno != EAGAIN && (n = read(sockfd, buf, sizeof(buf))) > 0) { 175 | printf("echo: %s\n", buf); 176 | bzero(buf, sizeof(buf)); 177 | 178 | c -= n; 179 | if (c <= 0) { 180 | break; 181 | } 182 | } 183 | } 184 | close(sockfd); 185 | } -------------------------------------------------------------------------------- /c/epoll/tcp-client-server1/Makefile: -------------------------------------------------------------------------------- 1 | SRC_SVR = server.c 2 | SRC_CLT = client.c 3 | CFLAG = -std=c99 4 | CFLAG += -D_GNU_SOURCE 5 | 6 | all: epoll_svr epoll_clt 7 | 8 | epoll_svr: server.c 9 | gcc $(CFLAG) -Wall -o $@ $(SRC_SVR) 10 | 11 | epoll_clt: client.c 12 | gcc $(CFLAG) -Wall -o $@ $(SRC_CLT) 13 | 14 | clean: 15 | rm -f epoll_svr epoll_clt 16 | 17 | -------------------------------------------------------------------------------- /c/epoll/tcp-client-server1/client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int sock_connect(char *ip, char *port) { 12 | int res; 13 | int skfd; 14 | struct addrinfo hints, *result, *rp; 15 | 16 | memset(&hints, 0, sizeof(struct addrinfo)); 17 | hints.ai_canonname = NULL; 18 | hints.ai_addr = NULL; 19 | hints.ai_next = NULL; 20 | hints.ai_family = AF_UNSPEC; 21 | hints.ai_socktype = SOCK_STREAM; 22 | hints.ai_protocol = 0; 23 | hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; 24 | res = getaddrinfo(ip, port, &hints, &result); 25 | if (res != 0) { 26 | fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(res)); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | for (rp = result; rp != NULL; rp = rp->ai_next) { 31 | skfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); 32 | if (skfd == -1) { 33 | continue; 34 | } 35 | if (connect(skfd, rp->ai_addr, rp->ai_addrlen) != -1) { 36 | break; 37 | } 38 | close(skfd); 39 | } 40 | 41 | if (rp == NULL) { 42 | printf("Could not connect to %s!\n", ip); 43 | return -1; 44 | } 45 | 46 | freeaddrinfo(result); 47 | 48 | return skfd; 49 | } 50 | 51 | int main(int argc, char **argv) { 52 | int skfd, slen, rlen; 53 | char buf[128] = {0}; 54 | char hostnm[64] = {0}; 55 | time_t tm; 56 | 57 | if (argc != 3) { 58 | printf("Usage: ./epoll_clt [IP address] [Port number]\n"); 59 | exit(EXIT_FAILURE); 60 | } 61 | 62 | skfd = sock_connect(argv[1], argv[2]); 63 | if (skfd == -1) { 64 | exit(EXIT_FAILURE); 65 | } 66 | 67 | if (gethostname(hostnm, sizeof(hostnm) - 1) == -1) { 68 | perror("get_host_name"); 69 | exit(-1); 70 | } 71 | 72 | do { 73 | sleep(1); 74 | // send 75 | time(&tm); 76 | snprintf(buf, sizeof(buf), "From client %s %s", hostnm, ctime(&tm)); 77 | // flag == 0: message don't wait 78 | slen = send(skfd, buf, strlen(buf), 0); 79 | if (slen != strlen(buf)) { 80 | printf("Send msg failed! slen (%d)\n", slen); 81 | break; 82 | } 83 | 84 | // recv 85 | memset(buf, 0, sizeof(buf)); 86 | // flag == 0: message don't wait 87 | rlen = recv(skfd, buf, sizeof(buf), 0); 88 | if (rlen == -1) { 89 | printf("Recv message failed !\n"); 90 | break; 91 | } else if (rlen == 0) { 92 | printf("Recv nothing!\n"); 93 | break; 94 | } else { 95 | printf("Recv : %s\n", buf); 96 | } 97 | } while (1); 98 | 99 | close(skfd); 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /c/epoll/tcp-server/Makefile: -------------------------------------------------------------------------------- 1 | IDIR= 2 | CC=gcc 3 | CFLAGS= 4 | 5 | ODIR=./ 6 | LDIR= 7 | 8 | LIBS= 9 | 10 | _DEPS= 11 | DEPS=$(patsubst %,$(IDIR)/%,$(_DEPS)) 12 | 13 | _OBJ=main.o 14 | OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ)) 15 | 16 | $(ODIR)/%.o: %.c $(DEPS) 17 | $(CC) -c -o $@ $< $(CFLAGS) 18 | 19 | main: $(OBJ) 20 | gcc -o $@ $^ $(CFLAGS) $(LIBS) 21 | 22 | .PHONY: clean 23 | 24 | clean: 25 | rm -f $(ODIR)/*.o *.~ core $(INCDIR)/*~ -------------------------------------------------------------------------------- /c/epoll/tcp/Makefile: -------------------------------------------------------------------------------- 1 | objects = epoll-server.o common.o 2 | 3 | compile : epoll-server epoll-client 4 | 5 | epoll-server : $(objects) 6 | cc -o epoll-server $(objects) 7 | 8 | epoll-server.o : common.h 9 | cc -c epoll-server.c 10 | 11 | epoll-client : epoll-client.o common.o 12 | cc -o epoll-client epoll-client.o common.o 13 | 14 | epoll-client.o : common.h 15 | cc -c epoll-client.c 16 | 17 | common.o : common.h 18 | cc -c common.c 19 | 20 | .PHONY : clean cleanall 21 | 22 | clean : 23 | -rm *.o 24 | 25 | cleanall : 26 | -rm *.o epoll-server epoll-client 27 | -------------------------------------------------------------------------------- /c/epoll/tcp/common.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void pr_exit(char *err) { 7 | perror(err); 8 | exit(0); 9 | } 10 | 11 | void setnonblocking(int fd) { 12 | int opts; 13 | if ((opts = fcntl(fd, F_GETFL)) < 0) { 14 | pr_exit("fcntl F_GETFL"); 15 | } 16 | opts = opts | O_NONBLOCK; 17 | if (fcntl(fd, F_SETFL, opts) < 0) { 18 | pr_exit("fcntl F_SETFL"); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /c/epoll/tcp/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define PORT (8012) 4 | #define MAXLINE (1024) 5 | 6 | void pr_exit(char *); 7 | void setnonblocking(int fd); 8 | -------------------------------------------------------------------------------- /c/epoll/tcp/epoll-client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "common.h" 11 | 12 | #define IPADDRESS "127.0.0.1" 13 | 14 | int main(int argc, char *argv[]) { 15 | int n; 16 | int connfd; 17 | char buffer[MAXLINE]; 18 | struct sockaddr_in servaddr; 19 | bzero(&servaddr, sizeof(servaddr)); 20 | 21 | if ((connfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 22 | pr_exit("socket"); 23 | } 24 | servaddr.sin_family = AF_INET; 25 | servaddr.sin_port = htons(PORT); 26 | servaddr.sin_addr.s_addr = inet_addr(IPADDRESS); 27 | 28 | if (connect(connfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { 29 | pr_exit("connect"); 30 | } 31 | 32 | for (;;) { 33 | bzero(&buffer, MAXLINE); 34 | if ((n = read(1, buffer, MAXLINE)) > 0) { 35 | if (send(connfd, buffer, n, 0) == n) { 36 | printf("send message: %s", buffer); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /c/epoll/tcp/epoll-server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "common.h" 11 | 12 | #define LISTENQ (20) 13 | #define MAXEVENTS LISTENQ 14 | 15 | int main(int argc, char *argv[]) { 16 | int i, n; 17 | int listenfd, connfd, epfd, nfds; 18 | struct sockaddr_in servaddr, cliaddr; 19 | struct epoll_event ev, events[MAXEVENTS]; 20 | bzero(&servaddr, sizeof(servaddr)); 21 | 22 | if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 23 | pr_exit("socket"); 24 | } 25 | setnonblocking(listenfd); 26 | servaddr.sin_family = AF_INET; 27 | servaddr.sin_port = htons(PORT); 28 | servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 29 | 30 | if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { 31 | pr_exit("bind"); 32 | } 33 | if (listen(listenfd, LISTENQ) < 0) { 34 | pr_exit("listen"); 35 | } 36 | 37 | epfd = epoll_create(MAXEVENTS); 38 | ev.data.fd = listenfd; 39 | ev.events = EPOLLIN | EPOLLET; 40 | 41 | if (epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) { 42 | pr_exit("epoll_ctl"); 43 | } 44 | 45 | for (;;) { 46 | nfds = epoll_wait(epfd, events, MAXEVENTS, -1); 47 | for (i = 0; i < nfds; i++) { 48 | if (events[i].data.fd == listenfd) { 49 | socklen_t slen; 50 | if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, 51 | &slen)) < 0) { 52 | pr_exit("accept"); 53 | } 54 | ev.data.fd = connfd; 55 | ev.events = EPOLLIN | EPOLLET; 56 | epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev); 57 | } 58 | if (events[i].events & EPOLLIN) { 59 | char buffer[MAXLINE]; 60 | bzero(&buffer, MAXLINE); 61 | if ((n = read(events[i].data.fd, buffer, MAXLINE)) > 0) { 62 | if (buffer[n - 1] == '\n') { 63 | buffer[n - 1] = '\0'; 64 | } 65 | printf("%s\n", buffer); 66 | } 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /c/glib/README.md: -------------------------------------------------------------------------------- 1 | # glib 2 | 3 | ## build 4 | * `gcc main.c `pkg-config --cflags --libs glib-2.0` -o test` 5 | 6 | ## Docs 7 | * 8 | -------------------------------------------------------------------------------- /c/glib/datetime/main.c: -------------------------------------------------------------------------------- 1 | /*! \file main.cc 2 | * \author Akagi201 3 | * \brief glib datetime related functions 4 | * 5 | * glib datetime related functions 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | static void print_todays_date(void) { 12 | GDateTime *dt; 13 | gchar *str; 14 | 15 | dt = g_date_time_new_now_local(); 16 | str = g_date_time_format(dt, "Today is %x."); 17 | g_print("%s\n", str); 18 | 19 | g_date_time_unref(dt); 20 | g_free(str); 21 | } 22 | 23 | static void print_tomorrows_date(void) { 24 | GDateTime *dt; 25 | GDateTime *dt2; 26 | gchar *str; 27 | 28 | dt = g_date_time_new_now_local(); 29 | dt2 = g_date_time_add_days(dt, 1); 30 | str = g_date_time_format(dt2, "Tomorrow is %x."); 31 | g_print("%s\n", str); 32 | 33 | g_date_time_unref(dt); 34 | g_date_time_unref(dt2); 35 | g_free(str); 36 | } 37 | 38 | static void print_yesterdays_date(void) { 39 | GDateTime *dt; 40 | GDateTime *dt2; 41 | gchar *str; 42 | 43 | dt = g_date_time_new_now_local(); 44 | dt2 = g_date_time_add_days(dt, -1); 45 | str = g_date_time_format(dt, "Yesterday was %x."); 46 | g_print("%s\n", str); 47 | 48 | g_date_time_unref(dt); 49 | g_date_time_unref(dt2); 50 | g_free(str); 51 | } 52 | 53 | static void print_current_timezone(void) { 54 | GDateTime *dt; 55 | 56 | dt = g_date_time_new_now_local(); 57 | g_print("The current timezone is %s.\n", 58 | g_date_time_get_timezone_abbreviation(dt)); 59 | g_date_time_unref(dt); 60 | } 61 | 62 | gint main(gint argc, gchar *argv[]) { 63 | print_todays_date(); 64 | print_tomorrows_date(); 65 | print_yesterdays_date(); 66 | print_current_timezone(); 67 | 68 | return 0; 69 | } -------------------------------------------------------------------------------- /c/glib/giochannel/cat_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | GIOChannel *channel = NULL; 6 | gchar buf[100]; 7 | gsize bytes_read; 8 | FILE *fp = NULL; 9 | 10 | if (argc != 2) { 11 | g_print("usage:cat \n"); 12 | g_print("Press any key to exit\n"); 13 | getchar(); 14 | return 1; 15 | } 16 | 17 | fp = fopen(argv[1], "r"); 18 | 19 | if (!fp) { 20 | g_print("Unable to open the file %s\n", argv[1]); 21 | return 1; 22 | } 23 | 24 | channel = g_io_channel_unix_new(fileno(fp)); 25 | 26 | do { 27 | g_io_channel_read_chars(channel, buf, 100, &bytes_read, NULL); 28 | g_print("%s", buf); 29 | 30 | } while (bytes_read > 0); 31 | 32 | g_io_channel_shutdown(channel, TRUE, NULL); 33 | 34 | fclose(fp); 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /c/glib/giochannel/cp_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | GIOChannel *in_channel = NULL, *out_channel = NULL; 6 | gchar buf[100] = {}; 7 | gsize bytes_read, bytes_written; 8 | GError *error = NULL; 9 | 10 | if (argc != 3) { 11 | g_print("usage: \n"); 12 | g_print("Press any key to exit\n"); 13 | getchar(); 14 | return 1; 15 | } 16 | 17 | in_channel = g_io_channel_new_file(argv[1], "r", &error); 18 | 19 | if (!in_channel) { 20 | g_print("Unable to open the file %s to read\n", argv[1]); 21 | g_print("Press any key to exit\n"); 22 | getchar(); 23 | return 1; 24 | } 25 | 26 | out_channel = g_io_channel_new_file(argv[2], "w", &error); 27 | 28 | if (!out_channel) { 29 | g_print("Unable to open the file %s to write\n", argv[2]); 30 | g_print("Press any key to exit\n"); 31 | getchar(); 32 | return 1; 33 | } 34 | 35 | do { 36 | g_io_channel_read_chars(in_channel, buf, 100, &bytes_read, &error); 37 | if (error) { 38 | g_print("Error while reading file %s\n", argv[1]); 39 | g_print("Press any key to exit\n"); 40 | getchar(); 41 | return 1; 42 | } 43 | 44 | g_io_channel_write_chars(out_channel, buf, bytes_read, &bytes_written, 45 | &error); 46 | if (error) { 47 | g_print("Error while writing file %s\n", argv[2]); 48 | g_print("Press any key to exit\n"); 49 | getchar(); 50 | return 1; 51 | } 52 | } while (bytes_read > 0); 53 | 54 | g_io_channel_shutdown(in_channel, TRUE, &error); 55 | if (error) { 56 | g_print("Error has occured\n"); 57 | g_print("Press any key to exit\n"); 58 | getchar(); 59 | return 1; 60 | } 61 | 62 | g_io_channel_shutdown(out_channel, TRUE, &error); 63 | if (error) { 64 | g_print("Error has occured\n"); 65 | g_print("Press any key to exit\n"); 66 | getchar(); 67 | return 1; 68 | } 69 | 70 | g_print("File copied successfully...\n"); 71 | getchar(); 72 | 73 | return 0; 74 | } -------------------------------------------------------------------------------- /c/glib/giochannel/giochannel_main_loop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int fd[2]; 6 | 7 | void *thread_function(void *data) { 8 | // call sleep so that the main loop source is not ready immediately 9 | sleep(10); 10 | 11 | write(fd[1], "GIOChannel main loop example", 29); 12 | return NULL; 13 | } 14 | 15 | gboolean my_callback(GIOChannel *source, GIOCondition condition, 16 | gpointer data) { 17 | char buf[100] = {}; 18 | 19 | read(fd[0], buf, sizeof(buf)); 20 | g_print("%s", buf); 21 | 22 | getchar(); 23 | 24 | g_main_loop_quit((GMainLoop *)data); 25 | 26 | return FALSE; 27 | } 28 | 29 | int main() { 30 | GMainLoop *loop = NULL; 31 | GIOChannel *channel = NULL; 32 | 33 | pipe(fd); 34 | 35 | channel = g_io_channel_unix_new(fd[0]); 36 | 37 | g_thread_new("pipe_read", thread_function, NULL); 38 | 39 | loop = g_main_loop_new(NULL, FALSE); 40 | g_io_add_watch(channel, G_IO_IN | G_IO_HUP | G_IO_ERR, 41 | (GIOFunc)my_callback, loop); 42 | g_main_loop_run(loop); 43 | 44 | g_io_channel_shutdown(channel, TRUE, NULL); 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /c/glib/main_event_loop/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | set (CMAKE_VERBOSE_MAKEFILE 1) 4 | 5 | project (main_event_loop C) 6 | 7 | set (CMAKE_BUILD_TYPE Debug) 8 | 9 | set (CMAKE_C_FLAGS "-Wall -Werror") 10 | 11 | set (TARGET_EXE_NAME main_event_loop) 12 | set (SRCS 13 | main.c 14 | ) 15 | 16 | execute_process ( 17 | COMMAND pkg-config --cflags glib-2.0 18 | OUTPUT_VARIABLE GLIB_CFLAGS 19 | OUTPUT_STRIP_TRAILING_WHITESPACE 20 | ) 21 | message ("GLIB_CFLAGS:" ${GLIB_CFLAGS}) 22 | 23 | execute_process ( 24 | COMMAND pkg-config --libs glib-2.0 25 | OUTPUT_VARIABLE GLIB_LIBS 26 | OUTPUT_STRIP_TRAILING_WHITESPACE 27 | ) 28 | message ("GLIB_LIBS:" ${GLIB_LIBS}) 29 | 30 | set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GLIB_CFLAGS}") 31 | include_directories () 32 | link_directories () 33 | 34 | set (LIBS 35 | ${GLIB_LIBS} 36 | ) 37 | 38 | add_executable (${TARGET_EXE_NAME} ${SRCS}) 39 | target_link_libraries (${TARGET_EXE_NAME} ${LIBS}) 40 | -------------------------------------------------------------------------------- /c/glib/main_event_loop/main.c: -------------------------------------------------------------------------------- 1 | /*! \file main.cc 2 | * \author Akagi201 3 | * \brief glib main event loop related functions 4 | * 5 | * glib main event loop related functions 6 | */ 7 | 8 | #include 9 | 10 | gboolean callback(gpointer data) { 11 | static guint16 i = 0; 12 | g_print("Iter=%" G_GUINT16_FORMAT "\n", i++); 13 | if (i % 5 == 0) { 14 | g_print("try to stop loop1:%p\n", data); 15 | g_main_loop_quit((GMainLoop*)data); 16 | } 17 | return TRUE; 18 | } 19 | 20 | /* 21 | * http://stackoverflow.com/questions/26410585/add-callback-for-separate-g-main-loop 22 | */ 23 | int main() { 24 | GMainContext* con1 = NULL; 25 | GMainContext* con2 = NULL; 26 | GMainLoop* loop1 = NULL; 27 | GMainLoop* loop2 = NULL; 28 | GSource* source1 = NULL; 29 | 30 | con1 = g_main_context_new(); 31 | con2 = g_main_context_new(); 32 | 33 | loop1 = g_main_loop_new(con1, FALSE); 34 | loop2 = g_main_loop_new(con2, FALSE); 35 | 36 | source1 = g_timeout_source_new_seconds(1); 37 | g_source_set_callback(source1, callback, loop1, NULL); 38 | g_source_attach(source1, con1); 39 | 40 | // We don't need the GMainContext anymore—the loop has an internal 41 | // reference so we'll drop ours. 42 | g_main_context_unref(con1); 43 | con1 = NULL; 44 | 45 | // Ditto for the GSource 46 | g_source_unref(source1); 47 | source1 = NULL; 48 | 49 | g_main_context_unref(con2); 50 | con2 = NULL; 51 | 52 | g_print("run loop1\n"); 53 | g_main_loop_run(loop1); 54 | // Use g_main_loop_unref, not g_free 55 | g_main_loop_unref(loop1); 56 | loop1 = NULL; 57 | 58 | g_print("run loop2\n"); 59 | // Note that there is no longer a callback attached here, so it will 60 | // run forever. 61 | g_main_loop_run(loop2); 62 | g_main_loop_unref(loop2); 63 | loop2 = NULL; 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /c/glib/socket/tcp/tcp_client.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) { 5 | GError *error = NULL; 6 | 7 | /* create a new connection */ 8 | GSocketConnection *connection = NULL; 9 | GSocketClient *client = g_socket_client_new(); 10 | 11 | /* connect to the host */ 12 | connection = g_socket_client_connect_to_host( 13 | client, (gchar *)"localhost", 8327, /* your port goes here */ 14 | NULL, &error); 15 | 16 | /* don't forget to check for errors */ 17 | if (error != NULL) { 18 | g_error("connect failed, %s", error->message); 19 | } else { 20 | g_print("Connection successful!\n"); 21 | } 22 | 23 | /* use the connection */ 24 | GInputStream *istream = 25 | g_io_stream_get_input_stream(G_IO_STREAM(connection)); 26 | GOutputStream *ostream = 27 | g_io_stream_get_output_stream(G_IO_STREAM(connection)); 28 | g_output_stream_write(ostream, 29 | "Hello server!", /* your message goes here */ 30 | 13, /* length of your message */ 31 | NULL, &error); 32 | /* don't forget to check for errors */ 33 | if (error != NULL) { 34 | g_error("stream write failed, %s", error->message); 35 | } 36 | return 0; 37 | } -------------------------------------------------------------------------------- /c/glib/socket/tcp/tcp_server.c: -------------------------------------------------------------------------------- 1 | // refs: 2 | // https://stackoverflow.com/questions/9513327/gio-socket-server-client-example 3 | 4 | #include 5 | #include 6 | 7 | #define BLOCK_SIZE (1024) 8 | #define PORT (8327) 9 | 10 | struct ConnData { 11 | GSocketConnection *connection; 12 | char message[BLOCK_SIZE]; 13 | }; 14 | 15 | void message_ready(GObject *source_object, GAsyncResult *res, 16 | gpointer user_data) { 17 | GInputStream *istream = G_INPUT_STREAM(source_object); 18 | GError *error = NULL; 19 | struct ConnData *data = user_data; 20 | int count; 21 | 22 | count = g_input_stream_read_finish(istream, res, &error); 23 | 24 | if (count == -1) { 25 | g_error("Error when receiving message"); 26 | if (error != NULL) { 27 | g_error("%s", error->message); 28 | g_clear_error(&error); 29 | } 30 | } 31 | 32 | g_message("Message was: %s", data->message); 33 | g_object_unref(G_SOCKET_CONNECTION(data->connection)); 34 | g_free(data); 35 | } 36 | 37 | /* this function will get called everytime a client attempts to connect */ 38 | static gboolean incoming_callback(GSocketService *service, 39 | GSocketConnection *connection, 40 | GObject *source_object, gpointer user_data) { 41 | g_message("Received Connection from client!"); 42 | GInputStream *istream = 43 | g_io_stream_get_input_stream(G_IO_STREAM(connection)); 44 | struct ConnData *data = g_new(struct ConnData, 1); 45 | data->connection = g_object_ref(connection); 46 | g_input_stream_read_async(istream, data->message, sizeof(data->message), 47 | G_PRIORITY_DEFAULT, NULL, message_ready, data); 48 | return FALSE; 49 | } 50 | 51 | int main(int argc, char **argv) { 52 | GError *error = NULL; 53 | GSocketService *service = NULL; 54 | gboolean ret = FALSE; 55 | 56 | /* create the new socketservice */ 57 | service = g_socket_service_new(); 58 | 59 | ret = g_socket_listener_add_inet_port(G_SOCKET_LISTENER(service), PORT, 60 | NULL, &error); 61 | 62 | /* don't forget to check for errors */ 63 | if (error != NULL) { 64 | g_error("listen port failed, %s", error->message); 65 | g_clear_error(&error); 66 | return -1; 67 | } 68 | 69 | /* listen to the 'incoming' signal */ 70 | g_signal_connect(service, "incoming", G_CALLBACK(incoming_callback), NULL); 71 | 72 | /* start the socket service */ 73 | g_socket_service_start(service); 74 | 75 | /* enter mainloop */ 76 | g_print("Waiting for client!\n"); 77 | GMainLoop *loop = g_main_loop_new(NULL, FALSE); 78 | g_main_loop_run(loop); 79 | g_socket_service_stop(service); 80 | return 0; 81 | } -------------------------------------------------------------------------------- /c/glib/source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | gboolean callback(gpointer data) { 4 | static int i = 0; 5 | i++; 6 | g_print("timeout_callback called %d times\n", i); 7 | if (10 == i) { 8 | g_main_loop_quit((GMainLoop *)data); 9 | return FALSE; 10 | } 11 | 12 | return TRUE; 13 | } 14 | 15 | gboolean prepare(GSource *source, gint *timeout_) { 16 | *timeout_ = -1; 17 | return TRUE; 18 | } 19 | 20 | gboolean check(GSource *source) { 21 | return TRUE; 22 | } 23 | 24 | gboolean dispatch(GSource *source, GSourceFunc callback, gpointer user_data) { 25 | return callback(user_data); 26 | } 27 | 28 | int main() { 29 | GMainLoop *loop = NULL; 30 | GMainContext *context = NULL; 31 | GSource *source = NULL; 32 | int id; 33 | 34 | // create a variable of type GSourceFuncs 35 | GSourceFuncs SourceFuncs = {prepare, check, dispatch, NULL}; 36 | 37 | // create a new source 38 | source = g_source_new(&SourceFuncs, sizeof(GSource)); 39 | 40 | // create a context 41 | context = g_main_context_new(); 42 | 43 | // attach source to context 44 | id = g_source_attach(source, context); 45 | 46 | // create a main loop with context 47 | loop = g_main_loop_new(context, FALSE); 48 | 49 | // set the callback for this source 50 | g_source_set_callback(source, callback, loop, NULL); 51 | 52 | g_main_loop_run(loop); 53 | g_main_loop_unref(loop); 54 | 55 | return 0; 56 | } -------------------------------------------------------------------------------- /c/glib/testing/README.md: -------------------------------------------------------------------------------- 1 | # testing 2 | 3 | ## Refs 4 | * 5 | * 6 | -------------------------------------------------------------------------------- /c/glib/testing/simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void computationTest(void) { 4 | // a suitable test 5 | g_assert(g_bit_storage(1) == 1); 6 | // a test with verbose error message 7 | g_assert_cmpint(g_bit_storage(1), ==, 1); 8 | } 9 | 10 | int main(int argc, char** argv) { 11 | g_test_init(&argc, &argv, NULL); 12 | g_test_add_func("/package_name/unit", computationTest); 13 | return g_test_run(); 14 | } -------------------------------------------------------------------------------- /c/glib/timeout/custom_ctx.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | gboolean timeout_callback(gpointer data) { 4 | static int i = 0; 5 | 6 | i++; 7 | g_print("timeout_callback called %d times\n", i); 8 | 9 | if (10 == i) { 10 | g_main_loop_quit((GMainLoop *)data); 11 | return FALSE; 12 | } 13 | 14 | return TRUE; 15 | } 16 | 17 | int main() { 18 | GMainLoop *loop = NULL; 19 | GMainContext *context = NULL; 20 | GSource *source = NULL; 21 | int id; 22 | 23 | // create a new time-out source 24 | source = g_timeout_source_new(1000); 25 | 26 | // create a context 27 | context = g_main_context_new(); 28 | 29 | // attach source to context 30 | id = g_source_attach(source, context); 31 | 32 | // create a main loop with context 33 | loop = g_main_loop_new(context, FALSE); 34 | 35 | // set the callback for this source 36 | g_source_set_callback(source, timeout_callback, loop, NULL); 37 | 38 | g_main_loop_run(loop); 39 | g_main_loop_unref(loop); 40 | 41 | return 0; 42 | } -------------------------------------------------------------------------------- /c/glib/timeout/default_ctx.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | gboolean timeout_callback(gpointer data) { 4 | static int i = 0; 5 | 6 | i++; 7 | g_print("timeout_callback called %d times\n", i); 8 | if (10 == i) { 9 | g_main_loop_quit((GMainLoop *)data); 10 | return FALSE; 11 | } 12 | 13 | return TRUE; 14 | } 15 | 16 | int main() { 17 | GMainLoop *loop = NULL; 18 | 19 | // use default context 20 | loop = g_main_loop_new(NULL, FALSE); 21 | 22 | // add source to default context 23 | g_timeout_add(1000, timeout_callback, loop); 24 | 25 | g_main_loop_run(loop); 26 | g_main_loop_unref(loop); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /c/glib/version/main.c: -------------------------------------------------------------------------------- 1 | /*! \file main.cc 2 | * \author Akagi201 3 | * \brief glib version related functions 4 | * 5 | * glib version related functions 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | int main() { 12 | const gchar *result = NULL; 13 | result = glib_check_version(1, 0, 0); 14 | printf("runtime glib check version result: %s\n", result); 15 | 16 | int static_check = 0; 17 | static_check = GLIB_CHECK_VERSION(1, 0, 0); 18 | printf("static glib check version result: %d\n", static_check); 19 | 20 | printf("runtime glib version: %u.%u.%u\n", glib_major_version, 21 | glib_minor_version, glib_micro_version); 22 | 23 | printf("static glib version: %u.%u.%u\n", GLIB_MAJOR_VERSION, 24 | GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /c/iov/README.md: -------------------------------------------------------------------------------- 1 | 平时里用的 read()/write() 是线性 I/O 读写函数. 所谓线性, 就是一段缓冲区可以被连续的读写, 而即将介绍的 readv()/writev() 称为向量 I/O 读写函数, 也可以叫做"分散/聚集""(Scatter/gather) I/O 函数. 这两个函数可以一次性对多个不连续的缓冲区进行读写, 支持这种特性的一个关键结构是: 2 | 3 | ``` 4 | struct iovec { 5 | void *iov_base; // Starting address 6 | size_t iov_len; // Number of bytes to transfer 7 | } 8 | ``` 9 | 10 | 它定义在 `` 头文件中, `readv()` 和 `writev()` 的原型为: 11 | 12 | ``` 13 | #include 14 | ssize_t readv(int fd, const struct iovec *iov, int iovcnt); 15 | ssize_t writev(int fd, const struct iovec *iov, int iovcnt); 16 | ``` 17 | 18 | ## 函数有 3 个参数 19 | * 第 1 个参数 fd 是一个文件描述符, 如果是 readv(), 则是从 fd 中读取内容存储到缓冲中; 如果是 writev(), 则是将缓冲中的内容写到fd中. 20 | * 第 2 个参数 iov 是上面所提到的 struct iovec 结构指针. 这个结构有两个成员, 其中, iov_base 表示某个缓冲区的起始地址, iov_len 表示该段缓冲区的长度. 读写多个缓冲区就是由该结构来连结的. 21 | * 第 3 个参数 iovcnt 表示多少个缓冲区. 22 | 23 | ## 向量I/O的读写的特点有 24 | * 读入缓冲区的内容要依次填满缓冲区, 即先填满 iov[0], 接着是 iov[1], 然后是 iov[2] ... ...直到 iov[n-1]. 25 | * 如果直接输出 iov[k], 那么它会连续输出 iov[k], iov[k-1], ... ...iov[1], iov[0]. 26 | 27 | 所以, 根据第 2 条, 在上面的 readv() 中输出 iov[2] 时, 看上去逆序得到 www.groad.net. 28 | 29 | 此外, 向量 I/O 的一个特性是可以原子性读写, 不会被其它的进程所干扰, 并且它的性能比线性 I/O 要高一些, 因为不必要调用多次系统调用. 30 | -------------------------------------------------------------------------------- /c/iov/file_readv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | char foo[4]; 10 | char bar[5]; 11 | char baz[4]; 12 | 13 | struct iovec iov[3]; 14 | ssize_t nr; 15 | int fd, i; 16 | 17 | fd = open("groad.txt", O_RDONLY); 18 | if (fd == -1) { 19 | perror("open"); 20 | return 1; 21 | } 22 | 23 | /* set up our iovec structures */ 24 | iov[0].iov_base = foo; 25 | iov[0].iov_len = sizeof(foo); 26 | iov[1].iov_base = bar; 27 | iov[1].iov_len = sizeof(bar); 28 | iov[2].iov_base = baz; 29 | iov[2].iov_len = sizeof(baz); 30 | 31 | /* read into the structures with a single call */ 32 | nr = readv(fd, iov, 3); 33 | if (nr == -1) { 34 | perror("readv"); 35 | return 1; 36 | } 37 | 38 | for (i = 0; i < 3; i++) { 39 | printf("%s", (char *) iov[i].iov_base); 40 | printf("\n"); 41 | } 42 | 43 | if (close(fd)) { 44 | perror("close"); 45 | return 1; 46 | } 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /c/iov/file_writev.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | struct iovec iov[3]; 10 | ssize_t nr; 11 | int fd, i; 12 | 13 | char *buf[] = {".net", "groad", "www."}; 14 | 15 | fd = open("groad.txt", O_WRONLY | O_CREAT | O_TRUNC, 0755); 16 | if (fd == -1) { 17 | perror("open"); 18 | return 1; 19 | } 20 | 21 | /* fill out three iovec structures */ 22 | for (i = 0; i < 3; i++) { 23 | iov[i].iov_base = buf[i]; 24 | iov[i].iov_len = strlen(buf[i]); 25 | printf("%d : %d\n", i, iov[i].iov_len); 26 | } 27 | 28 | /* write a single call, write them all out */ 29 | nr = writev(fd, iov, 3); 30 | if (nr == -1) { 31 | perror("writev"); 32 | return 1; 33 | } 34 | printf("wrote %d bytes\n", nr); 35 | 36 | if (close(fd)) { 37 | perror("close"); 38 | return 1; 39 | } 40 | 41 | return 0; 42 | } -------------------------------------------------------------------------------- /c/iov/writev.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * File : writev.c 3 | * Author : Saurabh Gupta 4 | * Desc : writev example c 5 | * Source : http://www.ccplusplus.com/2011/07/socket.html 6 | * Created : 10:37 PM Saturday, February 18, 2012 7 | *************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | int main(int argc, char **argv) { 16 | static char part2[] = "THIS IS FROM WRITEV : http://www.ccplusplus.com/"; 17 | static char part3[] = "]\n"; 18 | static char part1[] = "["; 19 | struct iovec iov[3]; 20 | 21 | iov[0].iov_base = part1; 22 | iov[0].iov_len = strlen(part1); 23 | 24 | iov[1].iov_base = part2; 25 | iov[1].iov_len = strlen(part2); 26 | 27 | iov[2].iov_base = part3; 28 | iov[2].iov_len = strlen(part3); 29 | 30 | writev(1, iov, 3); 31 | 32 | return 0; 33 | } 34 | /* 35 | * 36 | * 37 | [sgupta@rhel6x86 passing-creential-over-network]$ gcc writev.c -o writev 38 | [sgupta@rhel6x86 passing-creential-over-network]$ ./writev 39 | [THIS IS FROM WRITEV : http://www.ccplusplus.com/] 40 | [sgupta@rhel6x86 passing-creential-over-network]$ 41 | */ 42 | -------------------------------------------------------------------------------- /c/jansson/README.md: -------------------------------------------------------------------------------- 1 | # Jansson tutorial 2 | 3 | ## Build 4 | * `gcc -c github_commits github_commits.c -ljansson -lcurl` 5 | 6 | ## Run 7 | * `github_commits USER REPOSITORY` 8 | -------------------------------------------------------------------------------- /c/jansson/github_commits.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #define BUFFER_SIZE (256 * 1024) /* 256 KB */ 8 | 9 | #define URL_FORMAT "https://api.github.com/repos/%s/%s/commits" 10 | #define URL_SIZE (256) 11 | 12 | /* Return the offset of the first newline in text or the length of 13 | text if there's no newline */ 14 | static int newline_offset(const char *text) { 15 | const char *newline = strchr(text, '\n'); 16 | if (!newline) { 17 | return strlen(text); 18 | } else { 19 | return (int) (newline - text); 20 | } 21 | } 22 | 23 | struct write_result { 24 | char *data; 25 | int pos; 26 | }; 27 | 28 | static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream) { 29 | struct write_result *result = (struct write_result *) stream; 30 | 31 | if (result->pos + size * nmemb >= BUFFER_SIZE - 1) { 32 | fprintf(stderr, "error: too small buffer\n"); 33 | return 0; 34 | } 35 | 36 | memcpy(result->data + result->pos, ptr, size * nmemb); 37 | result->pos += size * nmemb; 38 | 39 | return size * nmemb; 40 | } 41 | 42 | static char *request(const char *url) { 43 | CURL *curl = NULL; 44 | CURLcode status; 45 | struct curl_slist *headers = NULL; 46 | char *data = NULL; 47 | long code; 48 | 49 | curl_global_init(CURL_GLOBAL_ALL); 50 | curl = curl_easy_init(); 51 | if (!curl) { 52 | goto error; 53 | } 54 | 55 | data = malloc(BUFFER_SIZE); 56 | if (!data) { 57 | goto error; 58 | } 59 | 60 | struct write_result write_result = { 61 | .data = data, 62 | .pos = 0 63 | }; 64 | 65 | curl_easy_setopt(curl, CURLOPT_URL, url); 66 | 67 | /* GitHub commits API v3 requires a User-Agent header */ 68 | headers = curl_slist_append(headers, "User-Agent: Jansson-Tutorial"); 69 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 70 | 71 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response); 72 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result); 73 | 74 | status = curl_easy_perform(curl); 75 | if (status != 0) { 76 | fprintf(stderr, "error: unable to request data from %s:\n", url); 77 | fprintf(stderr, "%s\n", curl_easy_strerror(status)); 78 | goto error; 79 | } 80 | 81 | curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); 82 | if (code != 200) { 83 | fprintf(stderr, "error: server responded with code %ld\n", code); 84 | goto error; 85 | } 86 | 87 | curl_easy_cleanup(curl); 88 | curl_slist_free_all(headers); 89 | curl_global_cleanup(); 90 | 91 | /* zero-terminate the result */ 92 | data[write_result.pos] = '\0'; 93 | 94 | return data; 95 | 96 | error: 97 | if (data) { 98 | free(data); 99 | } 100 | if (curl) { 101 | curl_easy_cleanup(curl); 102 | } 103 | if (headers) { 104 | curl_slist_free_all(headers); 105 | } 106 | curl_global_cleanup(); 107 | return NULL; 108 | } 109 | 110 | int main(int argc, char *argv[]) { 111 | size_t i; 112 | char *text; 113 | char url[URL_SIZE]; 114 | 115 | json_t *root; 116 | json_error_t error; 117 | 118 | if (argc != 3) { 119 | fprintf(stderr, "usage: %s USER REPOSITORY\n\n", argv[0]); 120 | fprintf(stderr, "List commits at USER's REPOSITORY.\n\n"); 121 | return 2; 122 | } 123 | 124 | snprintf(url, URL_SIZE, URL_FORMAT, argv[1], argv[2]); 125 | 126 | printf("Query url: %s\n", url); 127 | 128 | text = request(url); 129 | if (!text) { 130 | return 1; 131 | } 132 | 133 | root = json_loads(text, 0, &error); 134 | free(text); 135 | 136 | if (!root) { 137 | fprintf(stderr, "error: on line %d: %s\n", error.line, error.text); 138 | return 1; 139 | } 140 | 141 | if (!json_is_array(root)) { 142 | fprintf(stderr, "error: root is not an array\n"); 143 | json_decref(root); 144 | return 1; 145 | } 146 | 147 | for (i = 0; i < json_array_size(root); i++) { 148 | json_t *data, *sha, *commit, *message; 149 | const char *message_text; 150 | 151 | data = json_array_get(root, i); 152 | if (!json_is_object(data)) { 153 | fprintf(stderr, "error: commit data %d is not an object\n", (int) (i + 1)); 154 | json_decref(root); 155 | return 1; 156 | } 157 | 158 | sha = json_object_get(data, "sha"); 159 | if (!json_is_string(sha)) { 160 | fprintf(stderr, "error: commit %d: sha is not a string\n", (int) (i + 1)); 161 | return 1; 162 | } 163 | 164 | commit = json_object_get(data, "commit"); 165 | if (!json_is_object(commit)) { 166 | fprintf(stderr, "error: commit %d: commit is not an object\n", (int) (i + 1)); 167 | json_decref(root); 168 | return 1; 169 | } 170 | 171 | message = json_object_get(commit, "message"); 172 | if (!json_is_string(message)) { 173 | fprintf(stderr, "error: commit %d: message is not a string\n", (int) (i + 1)); 174 | json_decref(root); 175 | return 1; 176 | } 177 | 178 | message_text = json_string_value(message); 179 | printf("%.8s %.*s\n", 180 | json_string_value(sha), 181 | newline_offset(message_text), 182 | message_text); 183 | } 184 | 185 | json_decref(root); 186 | return 0; 187 | } 188 | -------------------------------------------------------------------------------- /c/jsmn/jsondump/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.4) 2 | 3 | set(TARGET_NAME jsondump_jsmn) 4 | 5 | project(${TARGET_NAME}) 6 | 7 | set(SOURCE_FILES main.c) 8 | 9 | include_directories("/usr/local/include") 10 | 11 | link_directories("." "/usr/local/lib") 12 | 13 | add_executable(${TARGET_NAME} ${SOURCE_FILES}) 14 | 15 | target_link_libraries(${TARGET_NAME} "libjsmn.a") 16 | -------------------------------------------------------------------------------- /c/jsmn/jsondump/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** 11 | * JSON type identifier. Basic types are: 12 | * o Object 13 | * o Array 14 | * o String 15 | * o Other primitive: number, boolean (true/false) or null 16 | */ 17 | typedef enum { 18 | JSMN_UNDEFINED = 0, 19 | JSMN_OBJECT = 1, 20 | JSMN_ARRAY = 2, 21 | JSMN_STRING = 3, 22 | JSMN_PRIMITIVE = 4 23 | } jsmntype_t; 24 | 25 | enum jsmnerr { 26 | /* Not enough tokens were provided */ 27 | JSMN_ERROR_NOMEM = -1, 28 | /* Invalid character inside JSON string */ 29 | JSMN_ERROR_INVAL = -2, 30 | /* The string is not a full JSON packet, more bytes expected */ 31 | JSMN_ERROR_PART = -3 32 | }; 33 | 34 | /** 35 | * JSON token description. 36 | * @param type type (object, array, string etc.) 37 | * @param start start position in JSON data string 38 | * @param end end position in JSON data string 39 | */ 40 | typedef struct { 41 | jsmntype_t type; 42 | int start; 43 | int end; 44 | int size; 45 | #ifdef JSMN_PARENT_LINKS 46 | int parent; 47 | #endif 48 | } jsmntok_t; 49 | 50 | /** 51 | * JSON parser. Contains an array of token blocks available. Also stores 52 | * the string being parsed now and current position in that string 53 | */ 54 | typedef struct { 55 | unsigned int pos; /* offset in the JSON string */ 56 | unsigned int toknext; /* next token to allocate */ 57 | int toksuper; /* superior token node, e.g parent object or array */ 58 | } jsmn_parser; 59 | 60 | /** 61 | * Create JSON parser over an array of tokens 62 | */ 63 | void jsmn_init(jsmn_parser *parser); 64 | 65 | /** 66 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 67 | * a single JSON object. 68 | */ 69 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 70 | jsmntok_t *tokens, unsigned int num_tokens); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* __JSMN_H_ */ 77 | -------------------------------------------------------------------------------- /c/jsmn/jsondump/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "jsmn.h" 7 | 8 | /* Function realloc_it() is a wrapper function for standart realloc() 9 | * with one difference - it frees old memory pointer in case of realloc 10 | * failure. Thus, DO NOT use old data pointer in anyway after call to 11 | * realloc_it(). If your code has some kind of fallback algorithm if 12 | * memory can't be re-allocated - use standart realloc() instead. 13 | */ 14 | static inline void *realloc_it(void *ptrmem, size_t size) { 15 | void *p = realloc(ptrmem, size); 16 | if (!p) { 17 | free(ptrmem); 18 | fprintf(stderr, "realloc(): errno=%d\n", errno); 19 | } 20 | return p; 21 | } 22 | 23 | /* 24 | * An example of reading JSON from stdin and printing its content to stdout. 25 | * The output looks like YAML, but I'm not sure if it's really compatible. 26 | */ 27 | 28 | static int dump(const char *js, jsmntok_t *t, size_t count, int indent) { 29 | int i, j, k; 30 | if (count == 0) { 31 | return 0; 32 | } 33 | if (t->type == JSMN_PRIMITIVE) { 34 | printf("%.*s", t->end - t->start, js + t->start); 35 | return 1; 36 | } else if (t->type == JSMN_STRING) { 37 | printf("'%.*s'", t->end - t->start, js + t->start); 38 | return 1; 39 | } else if (t->type == JSMN_OBJECT) { 40 | printf("\n"); 41 | j = 0; 42 | for (i = 0; i < t->size; i++) { 43 | for (k = 0; k < indent; k++) printf(" "); 44 | j += dump(js, t + 1 + j, count - j, indent + 1); 45 | printf(": "); 46 | j += dump(js, t + 1 + j, count - j, indent + 1); 47 | printf("\n"); 48 | } 49 | return j + 1; 50 | } else if (t->type == JSMN_ARRAY) { 51 | j = 0; 52 | printf("\n"); 53 | for (i = 0; i < t->size; i++) { 54 | for (k = 0; k < indent - 1; k++) printf(" "); 55 | printf(" - "); 56 | j += dump(js, t + 1 + j, count - j, indent + 1); 57 | printf("\n"); 58 | } 59 | return j + 1; 60 | } 61 | return 0; 62 | } 63 | 64 | int main() { 65 | int r; 66 | int eof_expected = 0; 67 | char *js = NULL; 68 | size_t jslen = 0; 69 | char buf[BUFSIZ]; 70 | 71 | jsmn_parser p; 72 | jsmntok_t *tok; 73 | size_t tokcount = 2; 74 | 75 | /* Prepare parser */ 76 | jsmn_init(&p); 77 | 78 | /* Allocate some tokens as a start */ 79 | tok = malloc(sizeof(*tok) * tokcount); 80 | if (tok == NULL) { 81 | fprintf(stderr, "malloc(): errno=%d\n", errno); 82 | return 3; 83 | } 84 | 85 | for (; ;) { 86 | /* Read another chunk */ 87 | r = fread(buf, 1, sizeof(buf), stdin); 88 | if (r < 0) { 89 | fprintf(stderr, "fread(): %d, errno=%d\n", r, errno); 90 | return 1; 91 | } 92 | if (r == 0) { 93 | if (eof_expected != 0) { 94 | return 0; 95 | } else { 96 | fprintf(stderr, "fread(): unexpected EOF\n"); 97 | return 2; 98 | } 99 | } 100 | 101 | js = realloc_it(js, jslen + r + 1); 102 | if (js == NULL) { 103 | return 3; 104 | } 105 | strncpy(js + jslen, buf, r); 106 | jslen = jslen + r; 107 | 108 | again: 109 | r = jsmn_parse(&p, js, jslen, tok, tokcount); 110 | if (r < 0) { 111 | if (r == JSMN_ERROR_NOMEM) { 112 | tokcount = tokcount * 2; 113 | tok = realloc_it(tok, sizeof(*tok) * tokcount); 114 | if (tok == NULL) { 115 | return 3; 116 | } 117 | goto again; 118 | } 119 | } else { 120 | dump(js, tok, p.toknext, 0); 121 | eof_expected = 1; 122 | } 123 | } 124 | 125 | return 0; 126 | } 127 | -------------------------------------------------------------------------------- /c/jsmn/jsondump/start_build.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | 3 | if test -d build ; 4 | then rm -rf build 5 | fi 6 | mkdir build 7 | 8 | cd build 9 | # cmake .. 10 | cmake .. && make 11 | -------------------------------------------------------------------------------- /c/jsmn/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.4) 2 | 3 | set(TARGET_NAME simple_jsmn) 4 | 5 | project(${TARGET_NAME}) 6 | 7 | set(SOURCE_FILES main.c) 8 | 9 | include_directories("/usr/local/include") 10 | 11 | link_directories("." "/usr/local/lib") 12 | 13 | add_executable(${TARGET_NAME} ${SOURCE_FILES}) 14 | 15 | target_link_libraries(${TARGET_NAME} "libjsmn.a") 16 | -------------------------------------------------------------------------------- /c/jsmn/simple/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /** 11 | * JSON type identifier. Basic types are: 12 | * o Object 13 | * o Array 14 | * o String 15 | * o Other primitive: number, boolean (true/false) or null 16 | */ 17 | typedef enum { 18 | JSMN_UNDEFINED = 0, 19 | JSMN_OBJECT = 1, 20 | JSMN_ARRAY = 2, 21 | JSMN_STRING = 3, 22 | JSMN_PRIMITIVE = 4 23 | } jsmntype_t; 24 | 25 | enum jsmnerr { 26 | /* Not enough tokens were provided */ 27 | JSMN_ERROR_NOMEM = -1, 28 | /* Invalid character inside JSON string */ 29 | JSMN_ERROR_INVAL = -2, 30 | /* The string is not a full JSON packet, more bytes expected */ 31 | JSMN_ERROR_PART = -3 32 | }; 33 | 34 | /** 35 | * JSON token description. 36 | * @param type type (object, array, string etc.) 37 | * @param start start position in JSON data string 38 | * @param end end position in JSON data string 39 | */ 40 | typedef struct { 41 | jsmntype_t type; 42 | int start; 43 | int end; 44 | int size; 45 | #ifdef JSMN_PARENT_LINKS 46 | int parent; 47 | #endif 48 | } jsmntok_t; 49 | 50 | /** 51 | * JSON parser. Contains an array of token blocks available. Also stores 52 | * the string being parsed now and current position in that string 53 | */ 54 | typedef struct { 55 | unsigned int pos; /* offset in the JSON string */ 56 | unsigned int toknext; /* next token to allocate */ 57 | int toksuper; /* superior token node, e.g parent object or array */ 58 | } jsmn_parser; 59 | 60 | /** 61 | * Create JSON parser over an array of tokens 62 | */ 63 | void jsmn_init(jsmn_parser *parser); 64 | 65 | /** 66 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 67 | * a single JSON object. 68 | */ 69 | int jsmn_parse(jsmn_parser *parser, const char *js, size_t len, 70 | jsmntok_t *tokens, unsigned int num_tokens); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* __JSMN_H_ */ 77 | -------------------------------------------------------------------------------- /c/jsmn/simple/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "jsmn.h" 5 | 6 | /* 7 | * A small example of jsmn parsing when JSON structure is known and number of 8 | * tokens is predictable. 9 | */ 10 | 11 | const char *JSON_STRING = 12 | "{\"user\": \"johndoe\", \"admin\": false, \"uid\": 1000,\n " 13 | "\"groups\": [\"users\", \"wheel\", \"audio\", \"video\"]}"; 14 | 15 | static int jsoneq(const char *json, jsmntok_t *tok, const char *s) { 16 | if (tok->type == JSMN_STRING && (int) strlen(s) == tok->end - tok->start && 17 | strncmp(json + tok->start, s, tok->end - tok->start) == 0) { 18 | return 0; 19 | } 20 | return -1; 21 | } 22 | 23 | int main() { 24 | int i; 25 | int r; 26 | jsmn_parser p; 27 | jsmntok_t t[128]; /* We expect no more than 128 tokens */ 28 | 29 | jsmn_init(&p); 30 | r = jsmn_parse(&p, JSON_STRING, strlen(JSON_STRING), t, sizeof(t) / sizeof(t[0])); 31 | if (r < 0) { 32 | printf("Failed to parse JSON: %d\n", r); 33 | return 1; 34 | } 35 | 36 | /* Assume the top-level element is an object */ 37 | if (r < 1 || t[0].type != JSMN_OBJECT) { 38 | printf("Object expected\n"); 39 | return 1; 40 | } 41 | 42 | /* Loop over all keys of the root object */ 43 | for (i = 1; i < r; i++) { 44 | if (jsoneq(JSON_STRING, &t[i], "user") == 0) { 45 | /* We may use strndup() to fetch string value */ 46 | printf("- User: %.*s\n", t[i + 1].end - t[i + 1].start, 47 | JSON_STRING + t[i + 1].start); 48 | i++; 49 | } else if (jsoneq(JSON_STRING, &t[i], "admin") == 0) { 50 | /* We may additionally check if the value is either "true" or "false" */ 51 | printf("- Admin: %.*s\n", t[i + 1].end - t[i + 1].start, 52 | JSON_STRING + t[i + 1].start); 53 | i++; 54 | } else if (jsoneq(JSON_STRING, &t[i], "uid") == 0) { 55 | /* We may want to do strtol() here to get numeric value */ 56 | printf("- UID: %.*s\n", t[i + 1].end - t[i + 1].start, 57 | JSON_STRING + t[i + 1].start); 58 | i++; 59 | } else if (jsoneq(JSON_STRING, &t[i], "groups") == 0) { 60 | int j; 61 | printf("- Groups:\n"); 62 | if (t[i + 1].type != JSMN_ARRAY) { 63 | continue; /* We expect groups to be an array of strings */ 64 | } 65 | for (j = 0; j < t[i + 1].size; j++) { 66 | jsmntok_t *g = &t[i + j + 2]; 67 | printf(" * %.*s\n", g->end - g->start, JSON_STRING + g->start); 68 | } 69 | i += t[i + 1].size + 1; 70 | } else { 71 | printf("Unexpected key: %.*s\n", t[i].end - t[i].start, 72 | JSON_STRING + t[i].start); 73 | } 74 | } 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /c/jsmn/simple/start_build.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | 3 | if test -d build ; 4 | then rm -rf build 5 | fi 6 | mkdir build 7 | 8 | cd build 9 | # cmake .. 10 | cmake .. && make 11 | -------------------------------------------------------------------------------- /c/kernel/docker_mount_namespace.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 定义一个给 clone 用的栈,栈大小1M */ 11 | #define STACK_SIZE (1024 * 1024) 12 | static char container_stack[STACK_SIZE]; 13 | 14 | char *const container_args[] = { 15 | "/bin/bash", 16 | "-1", 17 | NULL 18 | }; 19 | 20 | int container_main(void *arg) { 21 | printf("Container [%5d] - inside the container!\n", getpid()); 22 | 23 | // set hostname 24 | sethostname("container", 10) 25 | 26 | // remount "/proc" to make sure the "top" and "ps" show container's information 27 | if (mount("proc", "rootfs/proc", "proc", 0, NULL) != 0) { 28 | perror("proc"); 29 | } 30 | 31 | if (mount("sysfs", "rootfs/sys", "sysfs", 0, NULL) != 0) { 32 | perror("sys"); 33 | } 34 | 35 | if (mount("none", "rootfs/tmp", "tmpfs", 0, NULL) != 0) { 36 | perror("tmp"); 37 | } 38 | 39 | if (mount("udev", "rootfs/dev", "devtmpfs", 0, NULL) != 0) { 40 | perror("dev"); 41 | } 42 | 43 | if (mount("devpts", "rootfs/dev/pts", "devpts", 0, NULL) != 0) { 44 | perror("dev/pts); 45 | } 46 | 47 | if (mount("shm", "rootfs/dev/shm", "tmpfs", 0, NULL) != 0) { 48 | perror("dev/shm"); 49 | } 50 | 51 | if (mount("tmpfs", "rootfs/run", "tmpfs", 0, NULL) != 0) { 52 | perror("run"); 53 | } 54 | 55 | /* 56 | * 模仿Docker的从外向容器里mount相关的配置文件 57 | * 你可以查看:/var/lib/docker/containers//目录, 58 | * 你会看到docker的这些文件的。 59 | */ 60 | if (mount("conf/hosts", "rootfs/etc/hosts", "none", MS_BIND, NULL) != 0 || 61 | mount("conf/hostname", "rootfs/etc/hostname", "none", MS_BIND, NULL) != 0 || 62 | mount("conf/resolv.conf", "rootfs/etc/resolv.conf", "none", MS_BIND, NULL) != 0) { 63 | perror("conf"); 64 | } 65 | 66 | /* 模仿docker run命令中的 -v --volume=[] 参数干的事 */ 67 | if (mount("/tmp/t1", "rootfs/mnt", "none", MS_BIND, NULL) != 0) { 68 | perror("mnt"); 69 | } 70 | 71 | /* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */ 72 | execv(container_args[0], container_args); 73 | perror("exec"); 74 | printf("Something's wrong!\n"); 75 | return 1; 76 | } 77 | 78 | int main() { 79 | printf("Parent [%5d] - start a container!\n", getpid()); 80 | /* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */ 81 | int container_pid = clone(container_main, container_stack + STACK_SIZE, CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID 82 | | CLONE_NEWNS | SIGCHLD, NULL); 83 | /* 等待子进程结束 */ 84 | waitpid(container_pid, NULL, 0); 85 | printf("Parent - container stopped!\n"); 86 | return 0; 87 | } -------------------------------------------------------------------------------- /c/kernel/ipc_namespace.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 定义一个给 clone 用的栈,栈大小1M */ 11 | #define STACK_SIZE (1024 * 1024) 12 | static char container_stack[STACK_SIZE]; 13 | 14 | char *const container_args[] = { 15 | "/bin/bash", 16 | NULL 17 | }; 18 | 19 | int container_main(void *arg) { 20 | printf("Container - inside the container!\n"); 21 | /* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */ 22 | execv(container_args[0], container_args); 23 | printf("Something's wrong!\n"); 24 | return 1; 25 | } 26 | 27 | int main() { 28 | printf("Parent - start a container!\n"); 29 | /* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */ 30 | int container_pid = clone(container_main, container_stack + STACK_SIZE, CLONE_NEWUTS | CLONE_NEWIPC | SIGCHLD, NULL); 31 | /* 等待子进程结束 */ 32 | waitpid(container_pid, NULL, 0); 33 | printf("Parent - container stopped!\n"); 34 | return 0; 35 | } -------------------------------------------------------------------------------- /c/kernel/mount_namespace.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 定义一个给 clone 用的栈,栈大小1M */ 11 | #define STACK_SIZE (1024 * 1024) 12 | static char container_stack[STACK_SIZE]; 13 | 14 | char *const container_args[] = { 15 | "/bin/bash", 16 | NULL 17 | }; 18 | 19 | int container_main(void *arg) { 20 | /* 查看子进程的PID,我们可以看到其输出子进程的 pid 为 1 */ 21 | printf("Container [%5d] - inside the container!\n", getpid()); 22 | sethostname("container", 10); 23 | /* 重新mount proc文件系统到 /proc下 */ 24 | system("mount -t proc proc /proc"); 25 | /* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */ 26 | execv(container_args[0], container_args); 27 | printf("Something's wrong!\n"); 28 | return 1; 29 | } 30 | 31 | int main() { 32 | printf("Parent [%5d] - start a container!\n", getpid()); 33 | /* 启用Mount Namespace - 增加CLONE_NEWNS参数 */ 34 | /* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */ 35 | /* 启动PID namespace - CLONE_NEWPID */ 36 | int container_pid = clone(container_main, container_stack + STACK_SIZE, CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | SIGCHLD, NULL); 37 | /* 等待子进程结束 */ 38 | waitpid(container_pid, NULL, 0); 39 | printf("Parent - container stopped!\n"); 40 | return 0; 41 | } -------------------------------------------------------------------------------- /c/kernel/pid_namespace.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 定义一个给 clone 用的栈,栈大小1M */ 11 | #define STACK_SIZE (1024 * 1024) 12 | static char container_stack[STACK_SIZE]; 13 | 14 | char *const container_args[] = { 15 | "/bin/bash", 16 | NULL 17 | }; 18 | 19 | int container_main(void *arg) { 20 | /* 查看子进程的PID,我们可以看到其输出子进程的 pid 为 1 */ 21 | printf("Container [%5d] - inside the container!\n", getpid()); 22 | sethostname("container", 10); 23 | /* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */ 24 | execv(container_args[0], container_args); 25 | printf("Something's wrong!\n"); 26 | return 1; 27 | } 28 | 29 | int main() { 30 | printf("Parent [%5d] - start a container!\n", getpid()); 31 | /* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */ 32 | /* 启动PID namespace - CLONE_NEWPID */ 33 | int container_pid = clone(container_main, container_stack + STACK_SIZE, CLONE_NEWUTS | CLONE_NEWPID | SIGCHLD, NULL); 34 | /* 等待子进程结束 */ 35 | waitpid(container_pid, NULL, 0); 36 | printf("Parent - container stopped!\n"); 37 | return 0; 38 | } -------------------------------------------------------------------------------- /c/kernel/simple_clone.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 定义一个给 clone 用的栈,栈大小1M */ 11 | #define STACK_SIZE (1024 * 1024) 12 | static char container_stack[STACK_SIZE]; 13 | 14 | char *const container_args[] = { 15 | "/bin/bash", 16 | NULL 17 | }; 18 | 19 | int container_main(void *arg) { 20 | printf("Container - inside the container!\n"); 21 | /* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */ 22 | execv(container_args[0], container_args); 23 | printf("Something's wrong!\n"); 24 | return 1; 25 | } 26 | 27 | int main() { 28 | printf("Parent - start a container!\n"); 29 | /* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */ 30 | int container_pid = clone(container_main, container_stack + STACK_SIZE, SIGCHLD, NULL); 31 | /* 等待子进程结束 */ 32 | waitpid(container_pid, NULL, 0); 33 | printf("Parent - container stopped!\n"); 34 | return 0; 35 | } -------------------------------------------------------------------------------- /c/kernel/user_namespace.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define STACK_SIZE (1024 * 1024) 15 | 16 | static char container_stack[STACK_SIZE]; 17 | char *const container_args[] = { 18 | "/bin/bash", 19 | NULL 20 | }; 21 | 22 | int pipefd[2]; 23 | 24 | void set_map(char *file, int inside_id, int outside_id, int len) { 25 | FILE *mapfd = fopen(file, "w"); 26 | if (NULL == mapfd) { 27 | perror("open file error"); 28 | return; 29 | } 30 | fprintf(mapfd, "%d %d %d", inside_id, outside_id, len); 31 | fclose(mapfd); 32 | } 33 | 34 | void set_uid_map(pid_t pid, int inside_id, int outside_id, int len) { 35 | char file[256]; 36 | sprintf(file, "/proc/%d/uid_map", pid); 37 | set_map(file, inside_id, outside_id, len); 38 | } 39 | 40 | void set_gid_map(pid_t pid, int inside_id, int outside_id, int len) { 41 | char file[256]; 42 | sprintf(file, "/proc/%d/gid_map", pid); 43 | set_map(file, inside_id, outside_id, len); 44 | } 45 | 46 | int container_main(void *arg) { 47 | 48 | printf("Container [%5d] - inside the container!\n", getpid()); 49 | 50 | printf("Container: eUID = %ld; eGID = %ld, UID=%ld, GID=%ld\n", 51 | (long) geteuid(), (long) getegid(), (long) getuid(), (long) getgid()); 52 | 53 | /* 等待父进程通知后再往下执行(进程间的同步) */ 54 | char ch; 55 | close(pipefd[1]); 56 | read(pipefd[0], &ch, 1); 57 | 58 | printf("Container [%5d] - setup hostname!\n", getpid()); 59 | //set hostname 60 | sethostname("container", 10); 61 | 62 | //remount "/proc" to make sure the "top" and "ps" show container's information 63 | mount("proc", "/proc", "proc", 0, NULL); 64 | 65 | execv(container_args[0], container_args); 66 | printf("Something's wrong!\n"); 67 | return 1; 68 | } 69 | 70 | int main() { 71 | const int gid = getgid(), uid = getuid(); 72 | 73 | printf("Parent: eUID = %ld; eGID = %ld, UID=%ld, GID=%ld\n", 74 | (long) geteuid(), (long) getegid(), (long) getuid(), (long) getgid()); 75 | 76 | pipe(pipefd); 77 | 78 | printf("Parent [%5d] - start a container!\n", getpid()); 79 | 80 | int container_pid = clone(container_main, container_stack + STACK_SIZE, 81 | CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUSER | SIGCHLD, NULL); 82 | 83 | 84 | printf("Parent [%5d] - Container [%5d]!\n", getpid(), container_pid); 85 | 86 | //To map the uid/gid, 87 | // we need edit the /proc/PID/uid_map (or /proc/PID/gid_map) in parent 88 | //The file format is 89 | // ID-inside-ns ID-outside-ns length 90 | //if no mapping, 91 | // the uid will be taken from /proc/sys/kernel/overflowuid 92 | // the gid will be taken from /proc/sys/kernel/overflowgid 93 | set_uid_map(container_pid, 0, uid, 1); 94 | set_gid_map(container_pid, 0, gid, 1); 95 | 96 | printf("Parent [%5d] - user/group mapping done!\n", getpid()); 97 | 98 | /* 通知子进程 */ 99 | close(pipefd[1]); 100 | 101 | waitpid(container_pid, NULL, 0); 102 | printf("Parent - container stopped!\n"); 103 | return 0; 104 | } -------------------------------------------------------------------------------- /c/kernel/uts_namespace.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 定义一个给 clone 用的栈,栈大小1M */ 11 | #define STACK_SIZE (1024 * 1024) 12 | static char container_stack[STACK_SIZE]; 13 | 14 | char *const container_args[] = { 15 | "/bin/bash", 16 | NULL 17 | }; 18 | 19 | int container_main(void *arg) { 20 | printf("Container - inside the container!\n"); 21 | sethostname("container", 10); /* 设置hostname */ 22 | /* 直接执行一个shell,以便我们观察这个进程空间里的资源是否被隔离了 */ 23 | execv(container_args[0], container_args); 24 | printf("Something's wrong!\n"); 25 | return 1; 26 | } 27 | 28 | int main() { 29 | printf("Parent - start a container!\n"); 30 | /* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */ 31 | /* 启用CLONE_NEWUTS Namespace隔离 */ 32 | int container_pid = clone(container_main, container_stack + STACK_SIZE, CLONE_NEWUTS | SIGCHLD, NULL); 33 | /* 等待子进程结束 */ 34 | waitpid(container_pid, NULL, 0); 35 | printf("Parent - container stopped!\n"); 36 | return 0; 37 | } -------------------------------------------------------------------------------- /c/lib-implement/memcpy.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akagi201/learning-c-cpp/998370e4fdd59c867f3b1e2b8840f38500c5c634/c/lib-implement/memcpy.c -------------------------------------------------------------------------------- /c/lldb/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) { 4 | char *aa = argv[1]; 5 | printf("%s\n", aa); 6 | int a = 4; 7 | int b = 6; 8 | int array[3]; 9 | array[0] = 1; 10 | array[1] = 10; 11 | array[2] = 100; 12 | int *p; 13 | p = &a; 14 | int i = 0; 15 | while (i < 6) { 16 | printf("*p = %d\n", *p); 17 | p++; 18 | i++; 19 | } 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /c/nginx/rbtree/rbtree.h: -------------------------------------------------------------------------------- 1 | /*! \file rbtree.h 2 | * \author Akagi201 3 | * \brief rbtree from nginx 4 | * 5 | */ 6 | 7 | #pragma once 8 | 9 | typedef int ngx_int_t; 10 | typedef unsigned int ngx_uint_t; 11 | typedef int ngx_flag_t; 12 | 13 | typedef ngx_uint_t ngx_rbtree_key_t; 14 | typedef ngx_int_t ngx_rbtree_key_int_t; 15 | 16 | typedef struct ngx_rbtree_node_s ngx_rbtree_node_t; 17 | 18 | struct ngx_rbtree_node_s { 19 | ngx_rbtree_key_t key; 20 | ngx_rbtree_node_t *left; 21 | ngx_rbtree_node_t *right; 22 | ngx_rbtree_node_t *parent; 23 | char color; 24 | char data; 25 | }; 26 | 27 | 28 | typedef struct ngx_rbtree_s ngx_rbtree_t; 29 | 30 | typedef void (*ngx_rbtree_insert_pt)(ngx_rbtree_node_t *root, 31 | ngx_rbtree_node_t *node, 32 | ngx_rbtree_node_t *sentinel); 33 | 34 | struct ngx_rbtree_s { 35 | ngx_rbtree_node_t *root; 36 | ngx_rbtree_node_t *sentinel; 37 | ngx_rbtree_insert_pt insert; 38 | }; 39 | 40 | 41 | #define ngx_rbtree_init(tree, s, i) \ 42 | ngx_rbtree_sentinel_init(s); \ 43 | (tree)->root = s; \ 44 | (tree)->sentinel = s; \ 45 | (tree)->insert = i 46 | 47 | 48 | void ngx_rbtree_insert(ngx_rbtree_t *tree, ngx_rbtree_node_t *node); 49 | void ngx_rbtree_delete(ngx_rbtree_t *tree, ngx_rbtree_node_t *node); 50 | void ngx_rbtree_insert_value(ngx_rbtree_node_t *root, ngx_rbtree_node_t *node, 51 | ngx_rbtree_node_t *sentinel); 52 | void ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *root, 53 | ngx_rbtree_node_t *node, 54 | ngx_rbtree_node_t *sentinel); 55 | ngx_rbtree_node_t *ngx_rbtree_next(ngx_rbtree_t *tree, 56 | ngx_rbtree_node_t *node); 57 | 58 | 59 | #define ngx_rbt_red(node) ((node)->color = 1) 60 | #define ngx_rbt_black(node) ((node)->color = 0) 61 | #define ngx_rbt_is_red(node) ((node)->color) 62 | #define ngx_rbt_is_black(node) (!ngx_rbt_is_red(node)) 63 | #define ngx_rbt_copy_color(n1, n2) ((n1)->color = (n2)->color) 64 | 65 | 66 | /* a sentinel must be black */ 67 | 68 | #define ngx_rbtree_sentinel_init(node) ngx_rbt_black(node) 69 | 70 | 71 | static inline ngx_rbtree_node_t *ngx_rbtree_min(ngx_rbtree_node_t *node, 72 | ngx_rbtree_node_t *sentinel) { 73 | while (node->left != sentinel) { 74 | node = node->left; 75 | } 76 | 77 | return node; 78 | } -------------------------------------------------------------------------------- /c/protobuf-c/README.md: -------------------------------------------------------------------------------- 1 | # protobuf-c 2 | 3 | ## Build 4 | * `./genpb.sh` 5 | * `gcc sender.c ./mpb/amessage.pb-c.c -lprotobuf-c -o sender` 6 | * `gcc receiver.c ./mpb/amessage.pb-c.c -lprotobuf-c -o receiver` 7 | 8 | ## Run 9 | * `./sender 1 2 | ./receiver` 10 | 11 | ## Refs 12 | * 13 | -------------------------------------------------------------------------------- /c/protobuf-c/genpb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd proto 4 | 5 | echo "generate protobuf C code..." 6 | 7 | protoc-c --c_out=../mpb *.proto 8 | 9 | clang-format -sort-includes -style=Google -i ../mpb/*.c ../mpb/*.h 10 | -------------------------------------------------------------------------------- /c/protobuf-c/mpb/amessage.pb-c.c: -------------------------------------------------------------------------------- 1 | /* Generated by the protocol buffer compiler. DO NOT EDIT! */ 2 | /* Generated from: amessage.proto */ 3 | 4 | /* Do not generate deprecated warnings for self */ 5 | #ifndef PROTOBUF_C__NO_DEPRECATED 6 | #define PROTOBUF_C__NO_DEPRECATED 7 | #endif 8 | 9 | #include "amessage.pb-c.h" 10 | void mpb__amessage__init(Mpb__AMessage *message) { 11 | static Mpb__AMessage init_value = MPB__AMESSAGE__INIT; 12 | *message = init_value; 13 | } 14 | size_t mpb__amessage__get_packed_size(const Mpb__AMessage *message) { 15 | assert(message->base.descriptor == &mpb__amessage__descriptor); 16 | return protobuf_c_message_get_packed_size( 17 | (const ProtobufCMessage *)(message)); 18 | } 19 | size_t mpb__amessage__pack(const Mpb__AMessage *message, uint8_t *out) { 20 | assert(message->base.descriptor == &mpb__amessage__descriptor); 21 | return protobuf_c_message_pack((const ProtobufCMessage *)message, out); 22 | } 23 | size_t mpb__amessage__pack_to_buffer(const Mpb__AMessage *message, 24 | ProtobufCBuffer *buffer) { 25 | assert(message->base.descriptor == &mpb__amessage__descriptor); 26 | return protobuf_c_message_pack_to_buffer((const ProtobufCMessage *)message, 27 | buffer); 28 | } 29 | Mpb__AMessage *mpb__amessage__unpack(ProtobufCAllocator *allocator, size_t len, 30 | const uint8_t *data) { 31 | return (Mpb__AMessage *)protobuf_c_message_unpack(&mpb__amessage__descriptor, 32 | allocator, len, data); 33 | } 34 | void mpb__amessage__free_unpacked(Mpb__AMessage *message, 35 | ProtobufCAllocator *allocator) { 36 | assert(message->base.descriptor == &mpb__amessage__descriptor); 37 | protobuf_c_message_free_unpacked((ProtobufCMessage *)message, allocator); 38 | } 39 | static const ProtobufCFieldDescriptor mpb__amessage__field_descriptors[2] = { 40 | { 41 | "a", 1, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT32, 42 | offsetof(Mpb__AMessage, has_a), offsetof(Mpb__AMessage, a), NULL, NULL, 43 | 0, /* flags */ 44 | 0, NULL, NULL /* reserved1,reserved2, etc */ 45 | }, 46 | { 47 | "b", 2, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_INT32, 48 | offsetof(Mpb__AMessage, has_b), offsetof(Mpb__AMessage, b), NULL, NULL, 49 | 0, /* flags */ 50 | 0, NULL, NULL /* reserved1,reserved2, etc */ 51 | }, 52 | }; 53 | static const unsigned mpb__amessage__field_indices_by_name[] = { 54 | 0, /* field[0] = a */ 55 | 1, /* field[1] = b */ 56 | }; 57 | static const ProtobufCIntRange mpb__amessage__number_ranges[1 + 1] = {{1, 0}, 58 | {0, 2}}; 59 | const ProtobufCMessageDescriptor mpb__amessage__descriptor = { 60 | PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, 61 | "mpb.AMessage", 62 | "AMessage", 63 | "Mpb__AMessage", 64 | "mpb", 65 | sizeof(Mpb__AMessage), 66 | 2, 67 | mpb__amessage__field_descriptors, 68 | mpb__amessage__field_indices_by_name, 69 | 1, 70 | mpb__amessage__number_ranges, 71 | (ProtobufCMessageInit)mpb__amessage__init, 72 | NULL, 73 | NULL, 74 | NULL /* reserved[123] */ 75 | }; 76 | -------------------------------------------------------------------------------- /c/protobuf-c/mpb/amessage.pb-c.h: -------------------------------------------------------------------------------- 1 | /* Generated by the protocol buffer compiler. DO NOT EDIT! */ 2 | /* Generated from: amessage.proto */ 3 | 4 | #ifndef PROTOBUF_C_amessage_2eproto__INCLUDED 5 | #define PROTOBUF_C_amessage_2eproto__INCLUDED 6 | 7 | #include 8 | 9 | PROTOBUF_C__BEGIN_DECLS 10 | 11 | #if PROTOBUF_C_VERSION_NUMBER < 1000000 12 | # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. 13 | #elif 1002001 < PROTOBUF_C_MIN_COMPILER_VERSION 14 | # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. 15 | #endif 16 | 17 | typedef struct _Mpb__AMessage Mpb__AMessage; 18 | 19 | /* --- enums --- */ 20 | 21 | /* --- messages --- */ 22 | 23 | struct _Mpb__AMessage { 24 | ProtobufCMessage base; 25 | protobuf_c_boolean has_a; 26 | int32_t a; 27 | protobuf_c_boolean has_b; 28 | int32_t b; 29 | }; 30 | #define MPB__AMESSAGE__INIT \ 31 | { \ 32 | PROTOBUF_C_MESSAGE_INIT(&mpb__amessage__descriptor) \ 33 | , 0, 0, 0, 0 \ 34 | } 35 | 36 | /* Mpb__AMessage methods */ 37 | void mpb__amessage__init(Mpb__AMessage *message); 38 | size_t mpb__amessage__get_packed_size(const Mpb__AMessage *message); 39 | size_t mpb__amessage__pack(const Mpb__AMessage *message, uint8_t *out); 40 | size_t mpb__amessage__pack_to_buffer(const Mpb__AMessage *message, 41 | ProtobufCBuffer *buffer); 42 | Mpb__AMessage *mpb__amessage__unpack(ProtobufCAllocator *allocator, size_t len, 43 | const uint8_t *data); 44 | void mpb__amessage__free_unpacked(Mpb__AMessage *message, 45 | ProtobufCAllocator *allocator); 46 | /* --- per-message closures --- */ 47 | 48 | typedef void (*Mpb__AMessage_Closure)(const Mpb__AMessage *message, 49 | void *closure_data); 50 | 51 | /* --- services --- */ 52 | 53 | /* --- descriptors --- */ 54 | 55 | extern const ProtobufCMessageDescriptor mpb__amessage__descriptor; 56 | 57 | PROTOBUF_C__END_DECLS 58 | 59 | #endif /* PROTOBUF_C_amessage_2eproto__INCLUDED */ 60 | -------------------------------------------------------------------------------- /c/protobuf-c/proto/amessage.proto: -------------------------------------------------------------------------------- 1 | // AMessage Protobuf 2 | 3 | syntax = "proto3"; 4 | package mpb; 5 | 6 | message AMessage { 7 | int32 a=1; 8 | int32 b=2; 9 | } 10 | -------------------------------------------------------------------------------- /c/protobuf-c/receiver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "mpb/amessage.pb-c.h" 4 | 5 | #define MAX_MSG_SIZE (1024) 6 | 7 | static size_t read_buffer(unsigned max_length, uint8_t *out) { 8 | size_t cur_len = 0; 9 | size_t nread; 10 | while ((nread = fread(out + cur_len, 1, max_length - cur_len, stdin)) != 0) { 11 | cur_len += nread; 12 | if (cur_len == max_length) { 13 | fprintf(stderr, "max message length exceeded\n"); 14 | exit(1); 15 | } 16 | } 17 | return cur_len; 18 | } 19 | 20 | 21 | int main(int argc, const char *argv[]) { 22 | Mpb__AMessage *msg; 23 | 24 | // Read packed message from standard-input. 25 | uint8_t buf[MAX_MSG_SIZE]; 26 | size_t msg_len = read_buffer(MAX_MSG_SIZE, buf); 27 | 28 | // Unpack the message using protobuf-c. 29 | msg = mpb__amessage__unpack(NULL, msg_len, buf); 30 | if (msg == NULL) { 31 | fprintf(stderr, "error unpacking incoming message\n"); 32 | exit(1); 33 | } 34 | 35 | // display the message's fields. 36 | printf("Received: a=%d", msg->a); // required field 37 | if (msg->has_b) { 38 | // handle optional field 39 | printf(" b=%d", msg->b); 40 | } 41 | printf("\n"); 42 | 43 | // Free the unpacked message 44 | mpb__amessage__free_unpacked(msg, NULL); 45 | return 0; 46 | } -------------------------------------------------------------------------------- /c/protobuf-c/sender.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "mpb/amessage.pb-c.h" 4 | 5 | int main(int argc, const char *argv[]) { 6 | Mpb__AMessage msg = MPB__AMESSAGE__INIT; // AMessage 7 | void *buf; // Buffer to store serialized data 8 | unsigned len; // Length of serialized data 9 | 10 | if (argc != 2 && argc != 3) { // Allow one or two integers 11 | fprintf(stderr, "usage: amessage a [b]\n"); 12 | return 1; 13 | } 14 | 15 | msg.a = atoi(argv[1]); 16 | if (argc == 3) { 17 | msg.has_b = 1; 18 | msg.b = atoi(argv[2]); 19 | } 20 | len = mpb__amessage__get_packed_size(&msg); 21 | 22 | buf = malloc(len); 23 | mpb__amessage__pack(&msg, buf); 24 | 25 | fprintf(stderr, "Writing %d serialized bytes\n", len); // See the length of message 26 | fwrite(buf, len, 1, stdout); // Write to stdout to allow direct command line piping 27 | 28 | free(buf); // Free the allocated serialized buffer 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /c/script/script.c: -------------------------------------------------------------------------------- 1 | //usr/bin/env gcc $0 "$@" && ./a.out && rm ./a.out; exit 2 | #include 3 | 4 | int main() { 5 | printf("hello world\n"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /c/select/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Handle multiple socket connections with select and fd_set on Linux 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define TRUE (1) 17 | #define FALSE (0) 18 | #define PORT (8888) 19 | 20 | int main(int argc, char *argv[]) { 21 | int opt = TRUE; 22 | int master_socket, addrlen, new_socket, client_socket[30] = {}, 23 | max_clients = 30, activity, i, valread, sd; 24 | int max_sd; 25 | struct sockaddr_in address; 26 | 27 | char buffer[1025] = {}; // data buffer of 1K 28 | 29 | // set of socket descriptors 30 | fd_set readfds; 31 | FD_ZERO(&readfds); 32 | 33 | // a message 34 | char *message = "ECHO Daemon v1.0 \r\n"; 35 | 36 | // initialise all client_socket[] to 0 so not checked 37 | for (i = 0; i < max_clients; i++) { 38 | client_socket[i] = 0; 39 | } 40 | 41 | // create a master socket 42 | if ((master_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0) { 43 | perror("socket failed"); 44 | exit(EXIT_FAILURE); 45 | } 46 | 47 | // set master socket to allow multiple connections , this is just a good 48 | // habit, it will work without this 49 | if (setsockopt(master_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, 50 | sizeof(opt)) < 0) { 51 | perror("setsockopt"); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | // type of socket created 56 | address.sin_family = AF_INET; 57 | address.sin_addr.s_addr = INADDR_ANY; 58 | address.sin_port = htons(PORT); 59 | 60 | // bind the socket to localhost port 8888 61 | if (bind(master_socket, (struct sockaddr *)&address, sizeof(address)) < 62 | 0) { 63 | perror("bind failed"); 64 | exit(EXIT_FAILURE); 65 | } 66 | printf("Listener on port %d \n", PORT); 67 | 68 | // try to specify maximum of 3 pending connections for the master socket 69 | if (listen(master_socket, 3) < 0) { 70 | perror("listen"); 71 | exit(EXIT_FAILURE); 72 | } 73 | 74 | // accept the incoming connection 75 | addrlen = sizeof(address); 76 | puts("Waiting for connections ..."); 77 | 78 | while (TRUE) { 79 | // clear the socket set 80 | FD_ZERO(&readfds); 81 | 82 | // add master socket to set 83 | FD_SET(master_socket, &readfds); 84 | max_sd = master_socket; 85 | 86 | // add child sockets to set 87 | for (i = 0; i < max_clients; i++) { 88 | // socket descriptor 89 | sd = client_socket[i]; 90 | 91 | // if valid socket descriptor then add to read list 92 | if (sd > 0) { 93 | FD_SET(sd, &readfds); 94 | } 95 | 96 | // highest file descriptor number, need it for the select function 97 | if (sd > max_sd) { 98 | max_sd = sd; 99 | } 100 | } 101 | 102 | // wait for an activity on one of the sockets , timeout is NULL , so 103 | // wait indefinitely 104 | activity = select(max_sd + 1, &readfds, NULL, NULL, NULL); 105 | 106 | if ((activity < 0) && (errno != EINTR)) { 107 | printf("select error"); 108 | } 109 | 110 | // If something happened on the master socket , then its an incoming 111 | // connection 112 | if (FD_ISSET(master_socket, &readfds)) { 113 | if ((new_socket = 114 | accept(master_socket, (struct sockaddr *)&address, 115 | (socklen_t *)&addrlen)) < 0) { 116 | perror("accept"); 117 | exit(EXIT_FAILURE); 118 | } 119 | 120 | // inform user of socket number - used in send and receive commands 121 | printf( 122 | "New connection , socket fd is %d , ip is : %s , port : %d \n", 123 | new_socket, inet_ntoa(address.sin_addr), 124 | ntohs(address.sin_port)); 125 | 126 | // send new connection greeting message 127 | if (send(new_socket, message, strlen(message), 0) != 128 | strlen(message)) { 129 | perror("send"); 130 | } 131 | 132 | puts("Welcome message sent successfully"); 133 | 134 | // add new socket to array of sockets 135 | for (i = 0; i < max_clients; i++) { 136 | // if position is empty 137 | if (client_socket[i] == 0) { 138 | client_socket[i] = new_socket; 139 | printf("Adding to list of sockets as %d\n", i); 140 | 141 | break; 142 | } 143 | } 144 | } 145 | 146 | // else its some IO operation on some other socket :) 147 | for (i = 0; i < max_clients; i++) { 148 | sd = client_socket[i]; 149 | 150 | if (FD_ISSET(sd, &readfds)) { 151 | // Check if it was for closing , and also read the incoming 152 | // message 153 | if ((valread = read(sd, buffer, 1024)) == 0) { 154 | // Somebody disconnected , get his details and print 155 | getpeername(sd, (struct sockaddr *)&address, 156 | (socklen_t *)&addrlen); 157 | printf("Host disconnected , ip %s , port %d \n", 158 | inet_ntoa(address.sin_addr), 159 | ntohs(address.sin_port)); 160 | 161 | // Close the socket and mark as 0 in list for reuse 162 | close(sd); 163 | client_socket[i] = 0; 164 | } 165 | 166 | // Echo back the message that came in 167 | else { 168 | // set the string terminating NULL byte on the end of the 169 | // data read 170 | buffer[valread] = '\0'; 171 | send(sd, buffer, strlen(buffer), 0); 172 | } 173 | } 174 | } 175 | } 176 | 177 | return 0; 178 | } -------------------------------------------------------------------------------- /c/socket/README.md: -------------------------------------------------------------------------------- 1 | ## Linux C 2 | * TCP client and server: 3 | * UDP client adn server: 4 | * raw tcp socket linux only: 5 | * -------------------------------------------------------------------------------- /c/socket/gethostbyname/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(gethostbyname) 3 | 4 | set(SOURCE_FILES main.c) 5 | add_executable(gethostbyname ${SOURCE_FILES}) 6 | -------------------------------------------------------------------------------- /c/socket/gethostbyname/main.c: -------------------------------------------------------------------------------- 1 | #include // printf 2 | #include // strcpy 3 | #include 4 | #include // hostent 5 | #include 6 | 7 | /* Description of data base entry for a single host. */ 8 | //struct hostent { 9 | // char *h_name; /* Official name of host. */ 10 | // char **h_aliases; /* Alias list. */ 11 | // int h_addrtype; /* Host address type. */ 12 | // int h_length; /* Length of address. */ 13 | // char **h_addr_list; /* List of addresses from name server. */ 14 | //}; 15 | 16 | int main(int argc, char *argv[]) { 17 | char *hostname = "www.baidu.com"; 18 | char ip[100] = {}; 19 | struct hostent *he = NULL; 20 | struct in_addr **addr_list; 21 | int i = 0; 22 | 23 | if ((he = gethostbyname(hostname)) == NULL) { 24 | // gethostbyname failed 25 | herror("gethostbyname"); 26 | return 1; 27 | } 28 | 29 | // Cast the h_addr_list to in_addr, since h_addr_list also has the ip address in long format only. 30 | addr_list = (struct in_addr **) he->h_addr_list; 31 | 32 | for (i = 0; addr_list[i] != NULL; i++) { 33 | // Return the first one; 34 | strcpy(ip, inet_ntoa(*addr_list[i])); 35 | printf("%s resolved to: %s\n", hostname, ip); 36 | } 37 | 38 | // printf("%s resolved to: %s\n", hostname, ip); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /c/socket/rawtcp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(rawtcp) 3 | 4 | set(SOURCE_FILES main.c) 5 | add_executable(rawtcp ${SOURCE_FILES}) -------------------------------------------------------------------------------- /c/socket/rawtcp/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Raw TCP packets 3 | */ 4 | #include 5 | #include //for printf 6 | #include //memset 7 | #include //for socket ofcourse 8 | #include //for exit(0); 9 | #include //For errno - the error number 10 | #include //Provides declarations for tcp header 11 | #include //Provides declarations for ip header 12 | 13 | /* 14 | 96 bit (12 bytes) pseudo header needed for tcp header checksum calculation 15 | */ 16 | struct pseudo_header { 17 | u_int32_t source_address; 18 | u_int32_t dest_address; 19 | u_int8_t placeholder; 20 | u_int8_t protocol; 21 | u_int16_t tcp_length; 22 | }; 23 | 24 | /* 25 | Generic checksum calculation function 26 | */ 27 | unsigned short csum(unsigned short *ptr, int nbytes) { 28 | register long sum; 29 | unsigned short oddbyte; 30 | register short answer; 31 | 32 | sum = 0; 33 | while (nbytes > 1) { 34 | sum += *ptr++; 35 | nbytes -= 2; 36 | } 37 | if (nbytes == 1) { 38 | oddbyte = 0; 39 | *((u_char *) &oddbyte) = *(u_char *) ptr; 40 | sum += oddbyte; 41 | } 42 | 43 | sum = (sum >> 16) + (sum & 0xffff); 44 | sum = sum + (sum >> 16); 45 | answer = (short) ~sum; 46 | 47 | return (answer); 48 | } 49 | 50 | int main(void) { 51 | //Create a raw socket 52 | int s = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); 53 | 54 | if (s == -1) { 55 | //socket creation failed, may be because of non-root privileges 56 | perror("Failed to create socket"); 57 | exit(1); 58 | } 59 | 60 | //Datagram to represent the packet 61 | char datagram[4096], source_ip[32], *data, *pseudogram; 62 | 63 | //zero out the packet buffer 64 | memset(datagram, 0, 4096); 65 | 66 | //IP header 67 | struct iphdr *iph = (struct iphdr *) datagram; 68 | 69 | //TCP header 70 | struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof(struct ip)); 71 | struct sockaddr_in sin; 72 | struct pseudo_header psh; 73 | 74 | //Data part 75 | data = datagram + sizeof(struct iphdr) + sizeof(struct tcphdr); 76 | strcpy(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 77 | 78 | //some address resolution 79 | strcpy(source_ip, "192.168.1.2"); 80 | sin.sin_family = AF_INET; 81 | sin.sin_port = htons(80); 82 | sin.sin_addr.s_addr = inet_addr("1.2.3.4"); 83 | 84 | //Fill in the IP Header 85 | iph->ihl = 5; 86 | iph->version = 4; 87 | iph->tos = 0; 88 | iph->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr) + strlen(data); 89 | iph->id = htonl (54321); //Id of this packet 90 | iph->frag_off = 0; 91 | iph->ttl = 255; 92 | iph->protocol = IPPROTO_TCP; 93 | iph->check = 0; //Set to 0 before calculating checksum 94 | iph->saddr = inet_addr(source_ip); //Spoof the source ip address 95 | iph->daddr = sin.sin_addr.s_addr; 96 | 97 | //Ip checksum 98 | iph->check = csum((unsigned short *) datagram, iph->tot_len); 99 | 100 | //TCP Header 101 | tcph->source = htons (1234); 102 | tcph->dest = htons (80); 103 | tcph->seq = 0; 104 | tcph->ack_seq = 0; 105 | tcph->doff = 5; //tcp header size 106 | tcph->fin = 0; 107 | tcph->syn = 1; 108 | tcph->rst = 0; 109 | tcph->psh = 0; 110 | tcph->ack = 0; 111 | tcph->urg = 0; 112 | tcph->window = htons (5840); /* maximum allowed window size */ 113 | tcph->check = 0; //leave checksum 0 now, filled later by pseudo header 114 | tcph->urg_ptr = 0; 115 | 116 | //Now the TCP checksum 117 | psh.source_address = inet_addr(source_ip); 118 | psh.dest_address = sin.sin_addr.s_addr; 119 | psh.placeholder = 0; 120 | psh.protocol = IPPROTO_TCP; 121 | psh.tcp_length = htons(sizeof(struct tcphdr) + strlen(data)); 122 | 123 | int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + strlen(data); 124 | pseudogram = malloc(psize); 125 | 126 | memcpy(pseudogram, (char *) &psh, sizeof(struct pseudo_header)); 127 | memcpy(pseudogram + sizeof(struct pseudo_header), tcph, sizeof(struct tcphdr) + strlen(data)); 128 | 129 | tcph->check = csum((unsigned short *) pseudogram, psize); 130 | 131 | //IP_HDRINCL to tell the kernel that headers are included in the packet 132 | int one = 1; 133 | const int *val = &one; 134 | 135 | if (setsockopt(s, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) { 136 | perror("Error setting IP_HDRINCL"); 137 | exit(0); 138 | } 139 | 140 | //loop if you want to flood :) 141 | while (1) { 142 | //Send the packet 143 | if (sendto(s, datagram, iph->tot_len, 0, (struct sockaddr *) &sin, sizeof(sin)) < 0) { 144 | perror("sendto failed"); 145 | } 146 | //Data send successfully 147 | else { 148 | printf("Packet Send. Length : %d \n", iph->tot_len); 149 | } 150 | } 151 | 152 | return 0; 153 | } 154 | 155 | //Complete -------------------------------------------------------------------------------- /c/socket/tcpclient/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(tcpclient) 3 | 4 | set(SOURCE_FILES main.c) 5 | add_executable(tcpclient ${SOURCE_FILES}) 6 | -------------------------------------------------------------------------------- /c/socket/tcpclient/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // strlen 3 | #include 4 | 5 | #include 6 | #include // inet_addr 7 | 8 | int main(int argc, char *argv[]) { 9 | int socket_desc = -1; 10 | struct sockaddr_in server; 11 | char *message = NULL; 12 | char server_reply[2000] = {}; 13 | 14 | // Create socket 15 | socket_desc = socket(AF_INET, SOCK_STREAM, 0); 16 | if (socket_desc == -1) { 17 | printf("Could not create socket\n"); 18 | } 19 | 20 | // use the address of baidu.com to connect test. 21 | server.sin_addr.s_addr = inet_addr("115.239.211.112"); 22 | server.sin_family = AF_INET; 23 | server.sin_port = htons(80); 24 | 25 | // Connect to remote server 26 | if (connect(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { 27 | printf("Connect error\n"); 28 | return 1; 29 | } 30 | 31 | printf("Connected\n"); 32 | 33 | // Send some data 34 | message = "GET / HTTP/1.1\r\n\r\n"; 35 | if (send(socket_desc, message, strlen(message), 0) < 0) { 36 | printf("Send failed.\n"); 37 | return 1; 38 | } 39 | 40 | printf("Data Send\n"); 41 | 42 | // Receive a reply from the server 43 | if (recv(socket_desc, server_reply, 2000, 0) < 0) { 44 | printf("recv failed.\n"); 45 | } 46 | 47 | printf("Reply received.\n"); 48 | puts(server_reply); 49 | 50 | close(socket_desc); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /c/socket/tcpserver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(tcpserver) 3 | 4 | set(SOURCE_FILES main.c) 5 | add_executable(tcpserver ${SOURCE_FILES}) -------------------------------------------------------------------------------- /c/socket/tcpserver/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char *argv[]) { 9 | 10 | int socket_desc = -1; 11 | int new_socket = -1; 12 | int c = 0; 13 | struct sockaddr_in server; 14 | struct sockaddr_in client; 15 | char *message = NULL; 16 | int on = 1; 17 | int ret = -1; 18 | 19 | // Create socket 20 | socket_desc = socket(AF_INET, SOCK_STREAM, 0); 21 | if (socket_desc == -1) { 22 | printf("Could not create socket.\n"); 23 | } 24 | 25 | // Prepare the sockaddr_in structure 26 | server.sin_family = AF_INET; 27 | server.sin_addr.s_addr = INADDR_ANY; 28 | server.sin_port = htons(8888); 29 | 30 | ret = setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 31 | if (ret < 0) { 32 | perror("setsockopt SO_REUSEADDR failed."); 33 | } 34 | 35 | // Bind 36 | if (bind(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) { 37 | puts("bind failed"); 38 | return 1; 39 | } 40 | 41 | puts("bind done"); 42 | 43 | // Listen 44 | listen(socket_desc, 3); 45 | 46 | // Accept and incoming connection 47 | puts("Waiting for incoming connections...."); 48 | c = sizeof(struct sockaddr_in); 49 | while ((new_socket = accept(socket_desc, (struct sockaddr *) &client, (socklen_t *) &c))) { 50 | puts("Connection accepted"); 51 | 52 | // Reply to the client 53 | message = "Hello Client, I have received your connection, but I have to go now, bye.\n"; 54 | 55 | char *client_ip = inet_ntoa(client.sin_addr); 56 | int client_port = ntohs(client.sin_port); 57 | printf("client: ip: %s, port: %d\n", client_ip, client_port); 58 | 59 | write(new_socket, message, strlen(message)); 60 | close(new_socket); 61 | new_socket = -1; 62 | } 63 | 64 | if (new_socket < 0) { 65 | perror("accept failed"); 66 | return 1; 67 | } 68 | 69 | return 0; 70 | } 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /c/socket/tcpserver_pthread/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(tcpserver_pthread) 3 | 4 | set(SOURCE_FILES main.c) 5 | add_executable(tcpserver_pthread ${SOURCE_FILES}) 6 | -------------------------------------------------------------------------------- /c/socket/tcpserver_pthread/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | * This will handle connection for each client 10 | */ 11 | void *connection_handler(void *socket_desc) { 12 | // Get the socket descriptor 13 | int sock = *(int *)socket_desc; 14 | int read_size; 15 | char *message; 16 | char client_message[2000] = {}; 17 | 18 | // Send some messages to the client 19 | message = "Greetings! I am your connection handler.\n"; 20 | write(sock, message, strlen(message)); 21 | 22 | message = "Now type something and I shall repeat what you type.\n"; 23 | write(sock, message, strlen(message)); 24 | 25 | // Receive a message from client 26 | while ((read_size = recv(sock, client_message, 2000, 0)) > 0) { 27 | // Send the message back to client 28 | write(sock, client_message, strlen(client_message)); 29 | } 30 | 31 | if (read_size == 0) { 32 | puts("Client disconnected."); 33 | fflush(stdout); 34 | } else if (read_size == -1) { 35 | perror("recv failed."); 36 | } 37 | 38 | // Free the socket pointer 39 | free(socket_desc); 40 | 41 | return 0; 42 | } 43 | 44 | int main(int argc, char *argv[]) { 45 | int socket_desc; 46 | int new_socket; 47 | int c; 48 | int *new_sock; 49 | struct sockaddr_in server; 50 | struct sockaddr_in client; 51 | char *message; 52 | int ret = -1; 53 | int on = 1; 54 | 55 | // Create socket 56 | socket_desc = socket(AF_INET, SOCK_STREAM, 0); 57 | if (socket_desc == -1) { 58 | printf("Could not create socket\n"); 59 | } 60 | 61 | // Prepare the sockaddr_in struct 62 | server.sin_family = AF_INET; 63 | server.sin_addr.s_addr = INADDR_ANY; 64 | server.sin_port = htons(8888); 65 | 66 | ret = setsockopt(socket_desc, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 67 | if (ret < 0) { 68 | perror("setsockopt SO_REUSEADDR failed."); 69 | } 70 | 71 | // Bind 72 | if (bind(socket_desc, (struct sockaddr *)&server, sizeof(server)) < 0) { 73 | puts("bind failed"); 74 | return 1; 75 | } 76 | puts("bind done"); 77 | 78 | // Listen 79 | listen(socket_desc, 3); 80 | 81 | // Accept and incoming connection 82 | puts("Waiting for incoming connections...."); 83 | c = sizeof(struct sockaddr_in); 84 | while ((new_socket = accept(socket_desc, (struct sockaddr *)&client, (socklen_t *)&c))) { 85 | puts("Connection accepted"); 86 | 87 | // Reply to the client 88 | message = "Hello Client, I have received your connection. And now I will assign a handler for you\n"; 89 | write(new_socket, message, strlen(message)); 90 | 91 | pthread_t sniffer_thread; 92 | new_sock = malloc(1); 93 | *new_sock = new_socket; 94 | 95 | if (pthread_create(&sniffer_thread, NULL, connection_handler, (void *)new_sock) < 0) { 96 | perror("Could not create thread"); 97 | return 1; 98 | } 99 | 100 | // Now join the thread, so that we don't terminate before the thread 101 | pthread_join(sniffer_thread, NULL); 102 | puts("Handler assigned"); 103 | } 104 | 105 | if (new_socket < 0) { 106 | perror("Accept failed"); 107 | return 1; 108 | } 109 | 110 | return 0; 111 | } -------------------------------------------------------------------------------- /c/socket/udpclient/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(udpclient) 3 | 4 | set(SOURCE_FILES main.c) 5 | add_executable(udpclient ${SOURCE_FILES}) -------------------------------------------------------------------------------- /c/socket/udpclient/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple udp client 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define SERVER "127.0.0.1" 13 | #define BUFLEN (512) //Max length of buffer 14 | #define PORT (8888) //The port on which to send data 15 | 16 | void die(char *s) { 17 | perror(s); 18 | exit(1); 19 | } 20 | 21 | int main(void) { 22 | struct sockaddr_in si_other; 23 | int s, i, slen = sizeof(si_other); 24 | char buf[BUFLEN]; 25 | char message[BUFLEN]; 26 | 27 | if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 28 | die("socket"); 29 | } 30 | 31 | memset((char *) &si_other, 0, sizeof(si_other)); 32 | si_other.sin_family = AF_INET; 33 | si_other.sin_port = htons(PORT); 34 | 35 | if (inet_aton(SERVER, &si_other.sin_addr) == 0) { 36 | fprintf(stderr, "inet_aton() failed\n"); 37 | exit(1); 38 | } 39 | 40 | while (1) { 41 | printf("Enter message : "); 42 | gets(message); 43 | 44 | //send the message 45 | if (sendto(s, message, strlen(message), 0, (struct sockaddr *) &si_other, slen) == -1) { 46 | die("sendto()"); 47 | } 48 | 49 | //receive a reply and print it 50 | //clear the buffer by filling null, it might have previously received data 51 | memset(buf, '\0', BUFLEN); 52 | //try to receive some data, this is a blocking call 53 | if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, (socklen_t *)&slen) == -1) { 54 | die("recvfrom()"); 55 | } 56 | 57 | puts(buf); 58 | } 59 | 60 | close(s); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /c/socket/udpechoserver/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(udpechoserver) 3 | 4 | set(SOURCE_FILES main.c) 5 | add_executable(udpechoserver ${SOURCE_FILES}) 6 | -------------------------------------------------------------------------------- /c/socket/udpechoserver/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple udp server 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define BUFLEN (512) // Max length of buffer 13 | #define PORT (8888) // The port of which to listen for incoming data 14 | 15 | void die(char *s) { 16 | perror(s); 17 | exit(1); 18 | } 19 | 20 | int main(void) { 21 | struct sockaddr_in si_me; 22 | struct sockaddr_in si_other; 23 | 24 | int s = 0; 25 | int i = 0; 26 | int slen = sizeof(si_other); 27 | int recv_len = 0; 28 | 29 | char buf[BUFLEN] = {}; 30 | 31 | // create a UDP socket 32 | if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 33 | die("socket"); 34 | } 35 | 36 | // zero out the structure 37 | memset((char *)&si_me, 0, sizeof(si_me)); 38 | 39 | si_me.sin_family = AF_INET; 40 | si_me.sin_port = htons(PORT); 41 | si_me.sin_addr.s_addr = htonl(INADDR_ANY); 42 | 43 | // bind socket to port 44 | if (bind(s, (struct sockaddr *)&si_me, sizeof(si_me)) == -1) { 45 | die("bind"); 46 | } 47 | 48 | // keep listening for data 49 | while (1) { 50 | printf("Waiting for data..."); 51 | fflush(stdout); 52 | 53 | // try to receive some data, this is a blocking call 54 | if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *)&si_other, (socklen_t *)&slen)) == -1) { 55 | die("recvfrom()"); 56 | } 57 | 58 | // print details of the client/peer and the data received 59 | printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); 60 | printf("Data: %s\n", buf); 61 | 62 | // now reply the client with the same data 63 | if (sendto(s, buf, recv_len, 0, (struct sockaddr *)&si_other, slen) == -1) { 64 | die("sendto()"); 65 | } 66 | } 67 | 68 | close(s); 69 | 70 | return 0; 71 | } -------------------------------------------------------------------------------- /c/split/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "strsplit.h" 6 | 7 | int main(void) { 8 | { 9 | char str[] = "hello\nworld"; 10 | char *parts[2] = {NULL}; 11 | size_t size = strsplit(str, parts, "\n"); 12 | assert(size); 13 | int i = 0; 14 | for (; i < size; i++) { 15 | printf("%s\n", parts[i]); 16 | } 17 | for (i = 0; i < (int) size; i++) { 18 | free(parts[i]); 19 | } 20 | } 21 | 22 | { 23 | char str[] = "0 1 2 3 4 5 6 7 8 9"; 24 | char *parts[10] = {NULL}; 25 | size_t size = strsplit(str, parts, " "); 26 | assert(size); 27 | int i = 0; 28 | 29 | for (; i < (int) size; i++) { 30 | assert(i == atoi(parts[i])); 31 | printf("%s\n", parts[i]); 32 | } 33 | 34 | for (i = 0; i < (int) size; i++) { 35 | free(parts[i]); 36 | } 37 | } 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /c/split/strsplit.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "strsplit.h" 4 | //#include "strdup/strdup.h" 5 | 6 | int strsplit(const char *str, char *parts[], const char *delimiter) { 7 | char *pch; 8 | int i = 0; 9 | char *copy = NULL, *tmp = NULL; 10 | 11 | copy = strdup(str); 12 | if (!copy) { 13 | goto bad; 14 | } 15 | 16 | pch = strtok(copy, delimiter); 17 | 18 | tmp = strdup(pch); 19 | if (!tmp) { 20 | goto bad; 21 | } 22 | 23 | parts[i++] = tmp; 24 | 25 | while (pch) { 26 | pch = strtok(NULL, delimiter); 27 | if (NULL == pch) { 28 | break; 29 | } 30 | 31 | tmp = strdup(pch); 32 | if (!tmp) { 33 | goto bad; 34 | } 35 | 36 | parts[i++] = tmp; 37 | } 38 | 39 | free(copy); 40 | return i; 41 | 42 | bad: 43 | free(copy); 44 | for (int j = 0; j < i; j++) { 45 | free(parts[j]); 46 | } 47 | return -1; 48 | } 49 | -------------------------------------------------------------------------------- /c/split/strsplit.h: -------------------------------------------------------------------------------- 1 | #ifndef STRSPLIT_H 2 | #define STRSPLIT_H 1 3 | 4 | int strsplit(const char *, char *[], const char *); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /c/tcmalloc/memory_error_notcmalloc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * g++ memory_error_notcmalloc.cpp -g -O0 -o memory_error_notcmalloc 3 | * Refs: http://blog.csdn.net/win_lin/article/details/50461709 4 | */ 5 | #include 6 | #include 7 | #include 8 | 9 | void foo(char *p) { 10 | memcpy(p, "01234567890abcdef", 16); 11 | } 12 | 13 | int main(int argc, char **argv) { 14 | char *p = new char[10]; 15 | foo(p); 16 | printf("p=%s\n", p); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /c/trim/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "trim.h" 4 | 5 | int main() { 6 | { 7 | char str[] = "\t\n hello \t\n"; 8 | printf("%s\n", trim(str)); 9 | } 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /c/trim/trim.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "trim.h" 5 | 6 | char *trim_left(char *str) { 7 | int len = strlen(str); 8 | char *cur = str; 9 | 10 | while (*cur && isspace(*cur)) { 11 | ++cur; 12 | --len; 13 | } 14 | 15 | if (str != cur) { 16 | memmove(str, cur, len + 1); 17 | } 18 | 19 | return str; 20 | } 21 | 22 | char *trim_right(char *str) { 23 | int len = strlen(str); 24 | char *cur = str + len - 1; 25 | 26 | while (cur != str && isspace(*cur)) { 27 | --cur; 28 | } 29 | cur[isspace(*cur) ? 0 : 1] = '\0'; 30 | 31 | return str; 32 | } 33 | 34 | char *trim(char *str) { 35 | trim_right(str); 36 | trim_left(str); 37 | return str; 38 | } 39 | -------------------------------------------------------------------------------- /c/trim/trim.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef TRIM_H 3 | #define TRIM_H 1 4 | 5 | char *trim(char *); 6 | 7 | char *trim_right(char *); 8 | 9 | char *trim_left(char *); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /c/uuid/uuid_generate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) { 5 | uuid_t uuid; 6 | uuid_generate(uuid); 7 | 8 | unsigned char *p = uuid; 9 | int i; 10 | for (i = 0; i < sizeof(uuid_t); i++, p++) { 11 | printf("%02x", *p); 12 | } 13 | printf("\n"); 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /cpp/array/contain.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | int array[10] = {0,1,2,3,4,5,6,7,8,9}; 7 | auto it = std::find(std::begin(array), std::end(array), 5); 8 | 9 | if (it != std::end(array)) { 10 | cout << "found at position " << distance(array, it) << endl; 11 | } else { 12 | cout << "not found" << endl; 13 | } 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /cpp/array/interaction.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int interaction_count(const vector& a1, const vector& a2) { 8 | unordered_set s1(a1.begin(), a1.end()); 9 | int count = 0; 10 | for (const int& i:a2) { 11 | if (s1.find(i) != s1.end()) { 12 | count++; 13 | } 14 | } 15 | return count; 16 | } 17 | 18 | int main() { 19 | vector a1({1,2,3}); 20 | vector a2({2,3,4}); 21 | 22 | cout << interaction_count(a1, a2) << endl; 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /cpp/boost/README.md: -------------------------------------------------------------------------------- 1 | # boost 2 | 3 | ## Github 4 | * [container](https://github.com/boostorg/container) 5 | * [container-doc](http://www.boost.org/libs/container/) 6 | 7 | ## Tutorial 8 | * [The Boost C++ Libraries](https://theboostcpplibraries.com/introduction) 9 | * [Boost Cookbook](http://apolukhin.github.io/Boost-Cookbook/) -------------------------------------------------------------------------------- /cpp/boost/bimap/README.md: -------------------------------------------------------------------------------- 1 | # bimap 2 | 3 | ## Refs 4 | * -------------------------------------------------------------------------------- /cpp/boost/bimap/basic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/bimap/basic/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | int main() { 7 | //std::string <-> int 8 | typedef boost::bimap bimap; 9 | bimap animals; 10 | 11 | animals.insert({"cat", 4}); 12 | animals.insert({"shark", 0}); 13 | animals.insert({"spider", 8}); 14 | 15 | auto res = animals.insert({"dog", 4}); 16 | std::cout << "insert res second:" << res.second << std::endl;//0 17 | std::cout << "insert res first.left:" << res.first->left << std::endl;//cat 18 | std::cout << "insert res first.right:" << res.first->right << std::endl;//4 19 | 20 | std::cout << animals.left.count("cat") << std::endl; //1 21 | std::cout << animals.right.count(8) << std::endl; //1 22 | 23 | for (const auto& animal: animals) { 24 | std::cout << animal.left << " " << animal.right << std::endl; 25 | } 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /cpp/boost/bimap/student/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/bimap/student/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | int main() { 7 | boost::bimap, boost::bimaps::tagged> students; 8 | 9 | int student_id = 1; 10 | students.by().insert(std::make_pair(student_id++, "Jeff")); 11 | students.by().insert(std::make_pair(student_id++, "Tom")); 12 | students.by().insert(std::make_pair("Ying", student_id++)); 13 | students.by().insert(std::make_pair("Shabby", student_id++)); 14 | students.by().insert(std::make_pair("Tom", student_id++)); 15 | 16 | for (const auto& iter: students) { 17 | std::cout << iter.left << "->" << iter.right << std::endl; 18 | } 19 | 20 | std::cout << students.by().find(3)->second << std::endl; // Ying 21 | std::cout << students.by().count("Tom") << std::endl; // 2 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /cpp/boost/bimap/tag/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/bimap/tag/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | int main() { 7 | boost::bimap, boost::bimaps::tagged> bm; 8 | bm.by().insert(std::make_pair(1, "samus")); 9 | bm.by().insert(std::make_pair(2, "adam")); 10 | 11 | bm.by().insert(std::make_pair("link", 10)); 12 | bm.by().insert(std::make_pair("zelda", 11)); 13 | 14 | for (const auto& iter: bm) { 15 | std::cout << iter.left << "->" << iter.right << std::endl; 16 | } 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /cpp/boost/bimap/unconstrained-set-of/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/bimap/unconstrained-set-of/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | int main() { 7 | typedef boost::bimap, boost::bimaps::unconstrained_set_of> bimap; 8 | bimap animals; 9 | 10 | animals.insert({"cat", 4}); 11 | animals.insert({"shark", 0}); 12 | animals.insert({"dog", 4}); 13 | 14 | for (const auto& animal: animals) { 15 | std::cout << animal.left << " " << animal.right << std::endl; 16 | } 17 | 18 | auto it = animals.left.find("cat"); 19 | //animals.left.modify_key(it, boost::bimaps::_key = "elephant"); 20 | for (const auto& animal: animals) { 21 | std::cout << animal.left << " " << animal.right << std::endl; 22 | } 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /cpp/boost/container/list_emplace/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/container/list_emplace/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Non-copyable and non-movable class 5 | class non_copy_movable { 6 | non_copy_movable(const non_copy_movable &); 7 | non_copy_movable &operator=(const non_copy_movable &); 8 | 9 | public: 10 | non_copy_movable(int = 0) {} 11 | }; 12 | 13 | int main() { 14 | using namespace boost::container; 15 | 16 | // Store non-copyable and non-movable objects in a list 17 | list l; 18 | non_copy_movable ncm; 19 | 20 | // A new element will be built calling non_copy_movable(int) contructor 21 | l.emplace(l.begin(), 0); 22 | assert(l.size() == 1); 23 | 24 | // A new element will be value initialized 25 | l.emplace(l.begin()); 26 | assert(l.size() == 2); 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /cpp/boost/container/move_container/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/container/move_container/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Non-copyable class 6 | class non_copyable { 7 | BOOST_MOVABLE_BUT_NOT_COPYABLE(non_copyable) 8 | 9 | public: 10 | non_copyable() {} 11 | non_copyable(BOOST_RV_REF(non_copyable)) {} 12 | non_copyable& operator=(BOOST_RV_REF(non_copyable)) { 13 | return *this; 14 | } 15 | }; 16 | 17 | int main() { 18 | using namespace boost::container; 19 | 20 | // Store non-copyable objects in a vector 21 | vector v; 22 | non_copyable nc; 23 | v.push_back(boost::move(nc)); 24 | assert(v.size() == 1); 25 | 26 | // Reserve no longer needs copy-constructible 27 | v.reserve(100); 28 | assert(v.capacity() >= 100); 29 | 30 | // This resize overload only needs movable and default constructible 31 | v.resize(200); 32 | assert(v.size() == 200); 33 | 34 | // Containers are also movable 35 | vector v_other(boost::move(v)); 36 | assert(v_other.size() == 200); 37 | assert(v.empty()); 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /cpp/boost/container/vector_move_container/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/container/vector_move_container/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Non-copyable class 6 | class non_copyable { 7 | BOOST_MOVABLE_BUT_NOT_COPYABLE(non_copyable) 8 | 9 | public: 10 | non_copyable() {} 11 | non_copyable(BOOST_RV_REF(non_copyable)) {} 12 | non_copyable& operator=(BOOST_RV_REF(non_copyable)) { 13 | return *this; 14 | } 15 | }; 16 | 17 | int main() { 18 | using namespace boost::container; 19 | 20 | // Store non-copyable objects in a vector 21 | vector v; 22 | non_copyable nc; 23 | v.push_back(boost::move(nc)); 24 | assert(v.size() == 1); 25 | 26 | // Reserve no longer needs copy-constructible 27 | v.reserve(100); 28 | assert(v.capacity() >= 100); 29 | 30 | // This resize overload only needs movable and default constructible 31 | v.resize(200); 32 | assert(v.size() == 200); 33 | 34 | // Containers are also movable 35 | vector v_other(boost::move(v)); 36 | assert(v_other.size() == 200); 37 | assert(v.empty()); 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /cpp/boost/multi_index/README.md: -------------------------------------------------------------------------------- 1 | # Multi-index Containers Library 2 | 3 | ## Refs 4 | * 5 | * 6 | * -------------------------------------------------------------------------------- /cpp/boost/multi_index/basic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | find_package(Boost REQUIRED) 5 | include_directories(${Boost_INCLUDE_DIR}) 6 | link_directories(${Boost_LIBRARY_DIRS}) 7 | set(Boost_USE_STATIC_LIBS OFF) 8 | set(Boost_USE_MULTITHREADED ON) 9 | set(Boost_USE_STATIC_RUNTIME OFF) 10 | set(BOOST_ALL_DYN_LINK ON) 11 | 12 | add_executable(${PROJECT_NAME} main.cpp) 13 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/multi_index/basic/main.cpp: -------------------------------------------------------------------------------- 1 | #if !defined(NDEBUG) 2 | #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING 3 | #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE 4 | #endif 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using boost::multi_index_container; 15 | using namespace boost::multi_index; 16 | 17 | /* an employee record holds its ID, name and age */ 18 | 19 | struct employee { 20 | int id; 21 | std::string name; 22 | int age; 23 | 24 | employee(int id_, std::string name_, int age_) 25 | : id(id_), name(name_), age(age_) { 26 | } 27 | 28 | friend std::ostream& operator<<(std::ostream& os, const employee& e) { 29 | os << e.id << " " << e.name << " " << e.age << std::endl; 30 | return os; 31 | } 32 | }; 33 | 34 | /* tags for accessing the corresponding indices of employee_set */ 35 | 36 | struct id {}; 37 | struct name {}; 38 | struct age {}; 39 | 40 | /* see Compiler specifics: Use of member_offset for info on 41 | * BOOST_MULTI_INDEX_MEMBER 42 | */ 43 | 44 | /* Define a multi_index_container of employees with following indices: 45 | * - a unique index sorted by employee::id, 46 | * - a non-unique index sorted by employee::name, 47 | * - a non-unique index sorted by employee::age. 48 | */ 49 | 50 | typedef multi_index_container< 51 | employee, 52 | indexed_by< 53 | ordered_unique, BOOST_MULTI_INDEX_MEMBER(employee, int, id)>, 54 | ordered_non_unique, BOOST_MULTI_INDEX_MEMBER( 55 | employee, std::string, name)>, 56 | ordered_non_unique, 57 | BOOST_MULTI_INDEX_MEMBER(employee, int, age)> > > 58 | employee_set; 59 | 60 | template 61 | void print_out_by(const MultiIndexContainer& s) { 62 | /* obtain a reference to the index tagged by Tag */ 63 | 64 | const typename boost::multi_index::index::type& 65 | i = get(s); 66 | 67 | typedef typename MultiIndexContainer::value_type value_type; 68 | 69 | /* dump the elements of the index to cout */ 70 | 71 | std::copy(i.begin(), i.end(), 72 | std::ostream_iterator(std::cout)); 73 | } 74 | 75 | 76 | int main() { 77 | employee_set es; 78 | 79 | es.insert(employee(0, "Joe", 31)); 80 | es.insert(employee(1, "Robert", 27)); 81 | es.insert(employee(2, "John", 40)); 82 | 83 | /* next insertion will fail, as there is an employee with 84 | * the same ID 85 | */ 86 | 87 | es.insert(employee(2, "Aristotle", 2387)); 88 | 89 | es.insert(employee(3, "Albert", 20)); 90 | es.insert(employee(4, "John", 57)); 91 | 92 | /* list the employees sorted by ID, name and age */ 93 | 94 | std::cout << "by ID" << std::endl; 95 | print_out_by(es); 96 | std::cout << std::endl; 97 | 98 | std::cout << "by name" << std::endl; 99 | print_out_by(es); 100 | std::cout << std::endl; 101 | 102 | std::cout << "by age" << std::endl; 103 | print_out_by(es); 104 | std::cout << std::endl; 105 | 106 | return 0; 107 | } -------------------------------------------------------------------------------- /cpp/boost/multi_index/const_mem_fun/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/multi_index/const_mem_fun/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "boost/multi_index_container.hpp" 5 | #include "boost/multi_index/random_access_index.hpp" 6 | #include "boost/multi_index/ordered_index.hpp" 7 | #include "boost/multi_index/mem_fun.hpp" 8 | 9 | // Employee只有name一个成员 10 | // name_length成员函数返回name的长度 11 | struct Employee { 12 | Employee(const std::string& name_) : 13 | name(name_) { 14 | } 15 | 16 | std::size_t name_length() const { return name.size(); } 17 | 18 | std::string name; 19 | };// Employee 20 | 21 | typedef boost::multi_index::multi_index_container< 22 | Employee, 23 | boost::multi_index::indexed_by< 24 | // 第一个索引使用 const_mem_fun 定义,fun取Employee::name_length,也就是name的长度 25 | boost::multi_index::ordered_non_unique< 26 | boost::multi_index::const_mem_fun, 27 | // 降序排列 28 | std::greater 29 | >, 30 | // 支持按照插入顺序随机读写 31 | boost::multi_index::random_access<> 32 | > 33 | > EmployeeSet; 34 | 35 | int main() { 36 | EmployeeSet employees; 37 | 38 | employees.insert({"Jeff Dean"}); 39 | employees.insert({"Google"}); 40 | employees.insert({"Bidu"}); 41 | employees.insert({"Markus Heule"}); 42 | employees.insert({"Vlad Losev"}); 43 | 44 | // ordered_non_unique按照name长度降序输出 45 | // Markus Heule 46 | // Vlad Losev 47 | // Jeff Dean 48 | // Google 49 | // Bidu 50 | for (const auto employee : employees.get<0>()) { 51 | std::cout << employee.name << std::endl; 52 | } 53 | 54 | // random_access按照插入顺序顺序输出 55 | // Jeff Dean 56 | // Google 57 | // Bidu 58 | // Markus Heule 59 | // Vlad Losev 60 | for (const auto employee : employees.get<1>()) { 61 | std::cout << employee.name << std::endl; 62 | } 63 | 64 | // random_access 支持 operator[] at capacity reserve 等接口 65 | // Jeff Dean 66 | std::cout << employees.get<1>()[0].name << std::endl; 67 | // Google 68 | std::cout << employees.get<1>().at(1).name << std::endl; 69 | 70 | return 0; 71 | } -------------------------------------------------------------------------------- /cpp/boost/multi_index/multiple_sorts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/multi_index/multiple_sorts/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "boost/multi_index_container.hpp"//boost::multi_index::multi_index_container 5 | #include "boost/multi_index/ordered_index.hpp"//insert 6 | #include "boost/multi_index/identity.hpp"//identity 7 | #include "boost/multi_index/member.hpp"//member 8 | 9 | struct Employee { 10 | Employee(int id_, const std::string& name_) : 11 | id(id_), 12 | name(name_) { 13 | } 14 | 15 | int id; 16 | std::string name; 17 | 18 | //default compare by id 19 | bool operator<(const Employee& employee) const { 20 | return id < employee.id; 21 | } 22 | 23 | friend std::ostream& operator<<(std::ostream& out, const Employee& employee) { 24 | out << employee.id << "\t" << employee.name << std::endl; 25 | return out; 26 | } 27 | };//Employee 28 | 29 | typedef boost::multi_index::multi_index_container< 30 | Employee, 31 | boost::multi_index::indexed_by< 32 | boost::multi_index::ordered_unique< 33 | boost::multi_index::identity >, 34 | boost::multi_index::ordered_non_unique< 35 | boost::multi_index::member > 36 | > 37 | > EmployeeSet; 38 | 39 | int main() { 40 | EmployeeSet employees; 41 | 42 | employees.insert({5, "Jeff Dean"}); 43 | employees.insert({1, "Google"}); 44 | employees.insert({3, "Bidu"}); 45 | employees.insert({2, "Markus Heule"}); 46 | employees.insert({4, "Vlad Losev"}); 47 | 48 | //1 Google 49 | //2 Markus Heule 50 | //3 Bidu 51 | //4 Vlad Losev 52 | //5 Jeff Dean 53 | std::copy( 54 | employees.begin(), //equal to employees.get<0>() 55 | employees.end(), 56 | std::ostream_iterator(std::cout)); 57 | 58 | //3 Bidu 59 | //1 Google 60 | //5 Jeff Dean 61 | //2 Markus Heule 62 | //4 Vlad Losev 63 | const EmployeeSet::nth_index<1>::type& name_index = employees.get<1>(); 64 | std::copy( 65 | name_index.begin(), 66 | name_index.end(), 67 | std::ostream_iterator(std::cout)); 68 | 69 | return 0; 70 | } -------------------------------------------------------------------------------- /cpp/boost/multi_index/project/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/multi_index/project/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "boost/multi_index_container.hpp" 5 | #include "boost/multi_index/random_access_index.hpp" 6 | #include "boost/multi_index/ordered_index.hpp" 7 | #include "boost/multi_index/mem_fun.hpp" 8 | 9 | struct by_name_length {}; 10 | 11 | // Employee只有name一个成员 12 | // name_length成员函数返回name的长度 13 | struct Employee { 14 | Employee(const std::string& name_) : 15 | name(name_) { 16 | } 17 | 18 | std::size_t name_length() const { return name.size(); } 19 | 20 | std::string name; 21 | };// Employee 22 | 23 | typedef boost::multi_index::multi_index_container< 24 | Employee, 25 | boost::multi_index::indexed_by< 26 | // 第一个索引使用 const_mem_fun 定义,fun取Employee::name_length,也就是name的长度 27 | boost::multi_index::ordered_non_unique< 28 | // tag 定义 29 | boost::multi_index::tag, 30 | boost::multi_index::const_mem_fun, 31 | // 降序排列 32 | std::greater 33 | >, 34 | // 支持按照插入顺序随机读写 35 | boost::multi_index::random_access<> 36 | > 37 | > EmployeeSet; 38 | 39 | int main() { 40 | EmployeeSet employees; 41 | 42 | employees.insert({"Jeff Dean"}); 43 | employees.insert({"Google"}); 44 | employees.insert({"Bidu"}); 45 | employees.insert({"Markus Heule"}); 46 | employees.insert({"Vlad Losev"}); 47 | 48 | // name_length("Google") == 6 49 | auto name_length_iter = employees.get().find(6); 50 | auto iter = employees.project<1>(name_length_iter); 51 | 52 | for (; iter != employees.get<1>().end(); ++iter) { 53 | std::cout << iter->name << std::endl; 54 | } 55 | 56 | return 0; 57 | } -------------------------------------------------------------------------------- /cpp/boost/multi_index/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/multi_index/simple/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | int main() { 9 | boost::multi_index::multi_index_container employees; 10 | 11 | employees.insert("Jeff Dean"); 12 | employees.insert("Google"); 13 | employees.insert("Baidu"); 14 | employees.insert("Markus Heule"); 15 | employees.insert("Vlad Losev"); 16 | employees.insert("Ufo"); 17 | 18 | for (const auto& employee: employees) { 19 | std::cout << employee << std::endl; 20 | } 21 | 22 | std::cout << employees.size() << std::endl; 23 | employees.erase(employees.find("Ufo")); 24 | 25 | for (const auto& employee: employees) { 26 | std::cout << employee << std::endl; 27 | } 28 | 29 | auto it1 = employees.lower_bound("J"); 30 | auto it2 = employees.upper_bound("N"); 31 | 32 | for (; it1 != it2; ++it1) { 33 | std::cout << *it1 << std::endl; 34 | } 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /cpp/boost/multi_index/tag/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/multi_index/tag/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "boost/multi_index_container.hpp" 5 | #include "boost/multi_index/random_access_index.hpp" 6 | #include "boost/multi_index/ordered_index.hpp" 7 | #include "boost/multi_index/mem_fun.hpp" 8 | 9 | struct by_name_length {}; 10 | 11 | // Employee只有name一个成员 12 | // name_length成员函数返回name的长度 13 | struct Employee { 14 | Employee(const std::string& name_) : 15 | name(name_) { 16 | } 17 | 18 | std::size_t name_length() const { return name.size(); } 19 | 20 | std::string name; 21 | };// Employee 22 | 23 | typedef boost::multi_index::multi_index_container< 24 | Employee, 25 | boost::multi_index::indexed_by< 26 | // 第一个索引使用 const_mem_fun 定义,fun取Employee::name_length,也就是name的长度 27 | boost::multi_index::ordered_non_unique< 28 | // tag 定义 29 | boost::multi_index::tag, 30 | boost::multi_index::const_mem_fun, 31 | // 降序排列 32 | std::greater 33 | >, 34 | // 支持按照插入顺序随机读写 35 | boost::multi_index::random_access<> 36 | > 37 | > EmployeeSet; 38 | 39 | int main() { 40 | EmployeeSet employees; 41 | 42 | employees.insert({"Jeff Dean"}); 43 | employees.insert({"Google"}); 44 | employees.insert({"Bidu"}); 45 | employees.insert({"Markus Heule"}); 46 | employees.insert({"Vlad Losev"}); 47 | 48 | // ordered_non_unique按照name长度降序输出 49 | // Markus Heule 50 | // Vlad Losev 51 | // Jeff Dean 52 | // Google 53 | // Bidu 54 | for (const auto employee : employees.get<0>()) { 55 | std::cout << employee.name << std::endl; 56 | } 57 | 58 | // tag 59 | for (const auto employee: employees.get()) { 60 | std::cout << employee.name << std::endl; 61 | } 62 | 63 | // random_access按照插入顺序顺序输出 64 | // Jeff Dean 65 | // Google 66 | // Bidu 67 | // Markus Heule 68 | // Vlad Losev 69 | for (const auto employee : employees.get<1>()) { 70 | std::cout << employee.name << std::endl; 71 | } 72 | 73 | // random_access 支持 operator[] at capacity reserve 等接口 74 | // Jeff Dean 75 | std::cout << employees.get<1>()[0].name << std::endl; 76 | // Google 77 | std::cout << employees.get<1>().at(1).name << std::endl; 78 | 79 | return 0; 80 | } -------------------------------------------------------------------------------- /cpp/boost/multi_index/word_count/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(boost_demo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | find_package(Boost REQUIRED) 9 | include_directories(${Boost_INCLUDE_DIR}) 10 | link_directories(${Boost_LIBRARY_DIRS}) 11 | set(Boost_USE_STATIC_LIBS OFF) 12 | set(Boost_USE_MULTITHREADED ON) 13 | set(Boost_USE_STATIC_RUNTIME OFF) 14 | set(BOOST_ALL_DYN_LINK ON) 15 | 16 | add_executable(${PROJECT_NAME} main.cpp) 17 | target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -------------------------------------------------------------------------------- /cpp/boost/multi_index/word_count/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "boost/algorithm/string.hpp" 7 | #include "boost/multi_index_container.hpp" 8 | #include "boost/multi_index/ordered_index.hpp" 9 | #include "boost/multi_index/hashed_index.hpp" 10 | #include "boost/multi_index/identity.hpp" 11 | #include "boost/multi_index/member.hpp" 12 | 13 | //WordCnt类,记录了单词及对应的出现个数 14 | struct WordCnt { 15 | std::string word; 16 | int cnt; 17 | 18 | WordCnt(const std::string& word_, int cnt_) : 19 | word(word_), 20 | cnt(cnt_) { 21 | } 22 | 23 | //默认按照cnt排序 24 | bool operator<(const WordCnt& rhs) const { 25 | return cnt < rhs.cnt; 26 | } 27 | };//WordCnt 28 | 29 | typedef boost::multi_index::multi_index_container< 30 | //容器内元素类型 31 | WordCnt, 32 | boost::multi_index::indexed_by< 33 | //有序非唯一,顺序参考identtiy,也就是WordCnt.operator< 34 | boost::multi_index::ordered_non_unique< 35 | boost::multi_index::identity >, 36 | //无序,也就是hash表,hashkey使用 WorkdCnt::word 37 | boost::multi_index::hashed_unique< 38 | boost::multi_index::member > 39 | > 40 | > WordCntContainer; 41 | 42 | int main() { 43 | WordCntContainer word_cnt_container; 44 | 45 | std::vector contents; 46 | //文本 -> 单词vec 47 | boost::split(contents, 48 | "hello hello hello hello hello cpp cpp cpp cpp go go go python python shell", 49 | boost::is_any_of(" ")); 50 | 51 | //取第二个索引,也就是hash表 52 | auto& word_index = word_cnt_container.get<1>(); 53 | for (size_t i = 0; i < contents.size(); ++i) { 54 | const std::string& word = contents[i]; 55 | auto iter = word_index.find(word); 56 | //存在则cnt+1,否则插入1 57 | if (iter == word_index.end()) { 58 | word_index.insert({word, 1}); 59 | } else { 60 | word_index.modify(iter, [](WordCnt& word_cnt){ word_cnt.cnt++; }); 61 | } 62 | } 63 | 64 | //取word_cnt_container,即第一个索引,也就是按照cnt升序排列 65 | for (const auto word_cnt : word_cnt_container) { 66 | //shell 1 67 | //python 2 68 | //go 3 69 | //cpp 4 70 | //hello 5 71 | std::cout << word_cnt.word << "\t" << word_cnt.cnt << std::endl; 72 | } 73 | 74 | return 0; 75 | } -------------------------------------------------------------------------------- /cpp/boost/program_options/README.md: -------------------------------------------------------------------------------- 1 | ## build 2 | * `g++ first.cpp -lboost_program_options` 3 | -------------------------------------------------------------------------------- /cpp/boost/program_options/first.cpp: -------------------------------------------------------------------------------- 1 | /* The simplest usage of the library. 2 | */ 3 | 4 | #include 5 | 6 | namespace po = boost::program_options; 7 | 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | int main(int ac, char *av[]) { 14 | try { 15 | 16 | po::options_description desc("Allowed options"); 17 | desc.add_options() 18 | ("help", "produce help message") 19 | ("compression", po::value(), "set compression level"); 20 | 21 | po::variables_map vm; 22 | po::store(po::parse_command_line(ac, av, desc), vm); 23 | po::notify(vm); 24 | 25 | if (vm.count("help")) { 26 | cout << desc << "\n"; 27 | return 0; 28 | } 29 | 30 | if (vm.count("compression")) { 31 | cout << "Compression level was set to " 32 | << vm["compression"].as() << ".\n"; 33 | } else { 34 | cout << "Compression level was not set.\n"; 35 | } 36 | } 37 | catch (exception &e) { 38 | cerr << "error: " << e.what() << "\n"; 39 | return 1; 40 | } 41 | catch (...) { 42 | cerr << "Exception of unknown type!\n"; 43 | } 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /cpp/cast/reinterpret_cast.cc: -------------------------------------------------------------------------------- 1 | // 辅助哈希函数 2 | #include 3 | 4 | typedef unsigned long PointerType; 5 | 6 | // Returns a hash code based on an address 7 | unsigned short Hash(void *p) { 8 | PointerType val = reinterpret_cast(p); 9 | return (unsigned short)(val ^ (val >> 16)); 10 | } 11 | 12 | using namespace std; 13 | 14 | int main() { 15 | int a[20]; 16 | for (int i = 0; i < 20; i++) { 17 | cout << Hash(a + i) << endl; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /cpp/cgen/cppclass/cpplib/main.c: -------------------------------------------------------------------------------- 1 | #include "my_wrapper.h" 2 | #include 3 | 4 | int main(int argc, char* argv[]) { 5 | MyClass* c = NewMyClass(); 6 | MyClassIntSet(c, 3); 7 | printf("%i\n", MyClassIntGet(c)); 8 | DeleteMyClass(c); 9 | 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /cpp/cgen/cppclass/cpplib/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "my_class.h" 3 | 4 | using namespace std; 5 | 6 | int main(int argc, char* argv[]) { 7 | { 8 | MyClass c = MyClass(); 9 | c.int_set(3); 10 | cout << c.int_get() << endl; 11 | } 12 | { 13 | MyClass* c = new MyClass(); 14 | c->int_set(3); 15 | cout << c->int_get() << endl; 16 | delete c; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /cpp/cgen/cppclass/cpplib/my_class.cc: -------------------------------------------------------------------------------- 1 | #include "my_class.h" 2 | 3 | void MyClass::int_set(int i) { 4 | m_i = i; 5 | } 6 | 7 | int MyClass::int_get() { 8 | return m_i; 9 | } 10 | -------------------------------------------------------------------------------- /cpp/cgen/cppclass/cpplib/my_class.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class MyClass { 4 | private: 5 | int m_i; 6 | public: 7 | void int_set(int i); 8 | int int_get(); 9 | }; 10 | -------------------------------------------------------------------------------- /cpp/cgen/cppclass/cpplib/my_wrapper.cc: -------------------------------------------------------------------------------- 1 | #include "my_class.h" 2 | #include "my_wrapper.h" 3 | 4 | extern "C" { 5 | MyClass* NewMyClass() { 6 | return new MyClass(); 7 | } 8 | 9 | void MyClassIntSet(MyClass* v, int i) { 10 | v->int_set(i); 11 | } 12 | 13 | int MyClassIntGet(MyClass* v) { 14 | return v->int_get(); 15 | } 16 | 17 | void DeleteMyClass(MyClass* v) { 18 | delete v; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /cpp/cgen/cppclass/cpplib/my_wrapper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct MyClass MyClass; 8 | 9 | // constructor 10 | MyClass* NewMyClass(); 11 | 12 | // method setter 13 | void MyClassIntSet(MyClass* v, int i); 14 | 15 | // method getter 16 | int MyClassIntGet(MyClass* v); 17 | 18 | // destructor 19 | void DeleteMyClass(MyClass* v); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif -------------------------------------------------------------------------------- /cpp/class/virtual.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class shape { 6 | public: 7 | shape() { }; 8 | 9 | virtual void draw() { 10 | printf("shape\n"); 11 | } 12 | }; 13 | 14 | class rectangle : public shape { 15 | public: 16 | rectangle() { }; 17 | 18 | void draw() { 19 | printf("rectangle\n"); 20 | } 21 | }; 22 | 23 | class round : public shape { 24 | public: 25 | round() { }; 26 | 27 | void draw() { 28 | printf("round\n"); 29 | } 30 | }; 31 | 32 | int main() { 33 | shape *s; 34 | 35 | s = new rectangle(); 36 | s->draw(); 37 | 38 | s = new round(); 39 | s->draw(); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /cpp/const/variable.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() { 6 | const int const_a = 1; 7 | const int &a = const_a; 8 | auto b = a; 9 | b++; 10 | cout << b << endl; 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /cpp/constexpr/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | constexpr int foo(int i) { 7 | return i + 5; 8 | } 9 | 10 | int main() { 11 | int i = 10; 12 | std::array arr; // OK 13 | 14 | foo(i); // Call is Ok 15 | 16 | // But... 17 | // std::array arr1; // Error 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /cpp/cpprestsdk/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.7) 2 | 3 | set (CMAKE_CXX_STANDARD 14) 4 | 5 | if (NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) 6 | include_directories("/usr/local/include" 7 | "/usr/local/opt/openssl/include") 8 | link_directories("/usr/local/lib" 9 | "/usr/local/opt/openssl/lib") 10 | add_executable(bing_request bing_request.cc) 11 | target_link_libraries(bing_request cpprest) 12 | endif() 13 | -------------------------------------------------------------------------------- /cpp/cpprestsdk/bing_request.cc: -------------------------------------------------------------------------------- 1 | /*** 2 | * Copyright (C) Microsoft. All rights reserved. 3 | * Licensed under the MIT license. See LICENSE.txt file in the project root for 4 | *full license information. 5 | * 6 | * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ 7 | * 8 | * bing_request.cc - Simple cmd line application that makes an HTTP GET request 9 | *to bing searching and outputting the resulting HTML response body into a 10 | *file. 11 | * 12 | * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 13 | ****/ 14 | 15 | #include 16 | #include 17 | 18 | using namespace utility; 19 | using namespace web::http; 20 | using namespace web::http::client; 21 | using namespace concurrency::streams; 22 | 23 | /* Can pass proxy information via environment variable http_proxy. 24 | Example: 25 | Linux: export http_proxy=http://192.1.8.1:8080 26 | */ 27 | web::http::client::http_client_config client_config_for_proxy() { 28 | web::http::client::http_client_config client_config; 29 | #ifdef _WIN32 30 | wchar_t* pValue; 31 | size_t len; 32 | auto err = _wdupenv_s(&pValue, &len, L"http_proxy"); 33 | if (!err) { 34 | std::unique_ptr holder( 35 | pValue, [](wchar_t* p) { free(p); }); 36 | uri proxy_uri(std::wstring(pValue, len)); 37 | #else 38 | if (const char* env_http_proxy = std::getenv("http_proxy")) { 39 | uri proxy_uri(utility::conversions::to_string_t(env_http_proxy)); 40 | #endif 41 | web::web_proxy proxy(proxy_uri); 42 | client_config.set_proxy(proxy); 43 | } 44 | 45 | return client_config; 46 | } 47 | 48 | 49 | #ifdef _WIN32 50 | int wmain(int argc, wchar_t* args[]) 51 | #else 52 | int main(int argc, char* args[]) 53 | #endif 54 | { 55 | if (argc != 3) { 56 | printf("Usage: BingRequest.exe search_term output_file\n"); 57 | return -1; 58 | } 59 | const string_t searchTerm = args[1]; 60 | const string_t outputFileName = args[2]; 61 | 62 | // Open a stream to the file to write the HTTP response body into. 63 | auto fileBuffer = std::make_shared>(); 64 | file_buffer::open(outputFileName, std::ios::out) 65 | .then([=](streambuf outFile) -> pplx::task { 66 | *fileBuffer = outFile; 67 | 68 | // Create an HTTP request. 69 | // Encode the URI query since it could contain special characters 70 | // like spaces. 71 | http_client client(U("http://www.bing.com/"), 72 | client_config_for_proxy()); 73 | return client.request(methods::GET, 74 | uri_builder(U("/search")) 75 | .append_query(U("q"), searchTerm) 76 | .to_string()); 77 | }) 78 | 79 | // Write the response body into the file buffer. 80 | .then([=](http_response response) -> pplx::task { 81 | printf("Response status code %u returned.\n", 82 | response.status_code()); 83 | 84 | return response.body().read_to_end(*fileBuffer); 85 | }) 86 | 87 | // Close the file buffer. 88 | .then([=](size_t) { return fileBuffer->close(); }) 89 | 90 | // Wait for the entire response body to be written into the file. 91 | .wait(); 92 | 93 | return 0; 94 | } -------------------------------------------------------------------------------- /cpp/endian/is_little_endian.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | bool srs_is_little_endian() { 6 | // convert to network(big-endian) order, if not equals, 7 | // the system is little-endian, so need to convert the int64 8 | static int little_endian_check = -1; 9 | 10 | if (little_endian_check == -1) { 11 | union { 12 | int32_t i; 13 | int8_t c; 14 | } little_check_union; 15 | 16 | little_check_union.i = 0x01; 17 | little_endian_check = little_check_union.c; 18 | } 19 | 20 | return (little_endian_check == 1); 21 | } 22 | 23 | int main() { 24 | bool r = srs_is_little_endian(); 25 | printf("srs_is_little_endian: %d\n", r); 26 | } 27 | -------------------------------------------------------------------------------- /cpp/exception/new_exception.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | struct MyException : public exception { 7 | const char* what() const throw() { 8 | return "C++ Exception"; 9 | } 10 | }; 11 | 12 | int main() { 13 | try { 14 | throw MyException(); 15 | } catch (MyException& e) { 16 | std::cout << "MyException caught" << std::endl; 17 | std::cout << e.what() << std::endl; 18 | } catch (std::exception& e) { 19 | //其他的错误 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /cpp/exception/try_catch_throw.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | double division(int a, int b){ 6 | if (b == 0) { 7 | throw "Division by zero condition!"; 8 | } 9 | 10 | return (a / b); 11 | } 12 | 13 | int main() { 14 | int x = 50; 15 | int y = 0; 16 | double z = 0; 17 | 18 | try { 19 | z = division(x, y); 20 | cout << z << endl; 21 | } catch (const char* msg) { 22 | cerr << msg << endl; 23 | } 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /cpp/gengetopt/Makefile: -------------------------------------------------------------------------------- 1 | APPNAME = app 2 | OBJECTS = main.o cmdline.o 3 | 4 | CC = gcc 5 | CXX = g++ 6 | 7 | all: $(OBJECTS) 8 | $(CXX) $(OBJECTS) -o $(APPNAME) 9 | cmdline.o: cmdline.c 10 | $(CXX) -c $< -o $@ 11 | main.o: main.cpp 12 | $(CXX) -c $< -o $@ 13 | cmdline.c: cmdline.ggo 14 | gengetopt --input=cmdline.ggo --include-getopt 15 | 16 | clean: 17 | rm -rf *.o $(APPNAME) 18 | -------------------------------------------------------------------------------- /cpp/gengetopt/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Refs 3 | * 4 | -------------------------------------------------------------------------------- /cpp/gengetopt/app: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akagi201/learning-c-cpp/998370e4fdd59c867f3b1e2b8840f38500c5c634/cpp/gengetopt/app -------------------------------------------------------------------------------- /cpp/gengetopt/cmdline.ggo: -------------------------------------------------------------------------------- 1 | version "0.1.0" 2 | package "app" 3 | purpose "Sample application description. 4 | 5 | By Akagi201 " 6 | 7 | # Options 8 | option "filename" f "String argument" string required 9 | option "size" s "Optional argument, takes exactly 3 int values separated by commas" multiple(3) optional int 10 | option "array" a "Required argument, takes 1 or more args" multiple(1-) required int 11 | option "long-option" - "Option without short version" optional float 12 | option "default-value" d "Argument with default value" optional float default="0.003" 13 | option "console" c "Flag with default 'off'" flag off 14 | -------------------------------------------------------------------------------- /cpp/gengetopt/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "cmdline.h" 5 | 6 | int main(int argc, char *argv[]) { 7 | gengetopt_args_info ai; 8 | if (cmdline_parser(argc, argv, &ai) != 0) { 9 | exit(1); 10 | } 11 | 12 | std::cout << ai.filename_arg << std::endl; 13 | 14 | if (ai.size_given) { 15 | std::cout << ai.size_arg[0] << " " 16 | << ai.size_arg[1] << " " 17 | << ai.size_arg[2] << std::endl; 18 | } 19 | 20 | for (int i = 0; i < ai.array_given; ++i) { 21 | std::cout << ai.array_arg[i] << " "; 22 | } 23 | std::cout << std::endl; 24 | 25 | if (ai.long_option_given) { 26 | std::cout << ai.long_option_arg << std::endl; 27 | } 28 | 29 | std::cout << ai.default_value_arg << std::endl; 30 | std::cout << ai.console_flag << std::endl; 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /cpp/gperf/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all test clean 2 | 3 | all: test 4 | 5 | 6 | command_line: command_line.cpp perfecthash.h command_options.h 7 | $(CXX) $< -std=c++11 -lstdc++ -o $@ 8 | 9 | perfecthash.h: command_line_options.gperf 10 | gperf -CGD -N IsValidCommandLineOption -K Option -L C++ -t $< > $@ 11 | 12 | clean: 13 | rm -f perfecthash.h 14 | 15 | test: command_line 16 | ./command_line +helpverbose -xyz +nolog 17 | -------------------------------------------------------------------------------- /cpp/gperf/README.md: -------------------------------------------------------------------------------- 1 | ### gperf-sample 2 | 3 | Simple example of gperf usage with a makefile 4 | -------------------------------------------------------------------------------- /cpp/gperf/command_line.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "perfecthash.h" 6 | 7 | 8 | 9 | int main(int argc, const char** argv) { 10 | 11 | for (int i=1; iOption, opt->OptionCode); 15 | } else { 16 | fprintf(stderr, "InvalidOption: %s\n", argv[i]); 17 | } 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /cpp/gperf/command_line_options.gperf: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "command_options.h" 3 | typedef struct CommandOptionCode CommandOptionCode; 4 | %} 5 | struct CommandOption 6 | { 7 | const char *Option; 8 | int OptionCode; 9 | }; 10 | %% 11 | +helpverbose, CommandOptionCode::HELPVERBOSE 12 | +password, CommandOptionCode::PASSWORD 13 | +nocopyright, CommandOptionCode::NOCOPYRIGHT 14 | +nolog, CommandOptionCode::NOLOG 15 | +_64bit, CommandOptionCode::_64BIT 16 | -------------------------------------------------------------------------------- /cpp/gperf/command_options.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMANDOPTIONS_H 2 | #define __COMMANDOPTIONS_H 3 | struct CommandOptionCode 4 | { 5 | enum 6 | { 7 | HELPVERBOSE = 1, 8 | PASSWORD = 2, 9 | NOCOPYRIGHT = 3, 10 | NOLOG = 4, 11 | _64BIT = 5 12 | }; 13 | }; 14 | #endif 15 | -------------------------------------------------------------------------------- /cpp/hash/hash.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @file hash.cpp 3 | * @auther Akagi201 4 | * 5 | * @date 2016/07/06 6 | */ 7 | 8 | #include "hash.h" 9 | 10 | /* 11 | * Set hash `key` to `val`. 12 | */ 13 | 14 | void hash_set(hash_t *self, char *key, void *val) { 15 | int ret; 16 | khiter_t k = kh_put(ptr, self, key, &ret); 17 | kh_value(self, k) = val; 18 | } 19 | 20 | /* 21 | * Get hash `key`, or NULL. 22 | */ 23 | 24 | void *hash_get(hash_t *self, char *key) { 25 | khiter_t k = kh_get(ptr, self, key); 26 | return k == kh_end(self) ? NULL : kh_value(self, k); 27 | } 28 | 29 | /* 30 | * Check if hash `key` exists. 31 | */ 32 | 33 | int hash_has(hash_t *self, char *key) { 34 | khiter_t k = kh_get(ptr, self, key); 35 | return k != kh_end(self); 36 | } 37 | 38 | /* 39 | * Remove hash `key`. 40 | */ 41 | 42 | void hash_del(hash_t *self, char *key) { 43 | khiter_t k = kh_get(ptr, self, key); 44 | kh_del(ptr, self, k); 45 | } 46 | 47 | // tests 48 | 49 | #ifdef TEST_HASH 50 | 51 | #include 52 | #include 53 | #include 54 | 55 | void test_hash_set() { 56 | hash_t *hash = hash_new(); 57 | assert(0 == hash_size(hash)); 58 | 59 | hash_set(hash, "name", "tobi"); 60 | hash_set(hash, "species", "ferret"); 61 | assert(2 == hash_size(hash)); 62 | 63 | assert(0 == strcmp("tobi", hash_get(hash, "name"))); 64 | assert(0 == strcmp("ferret", hash_get(hash, "species"))); 65 | } 66 | 67 | void test_hash_get() { 68 | hash_t *hash = hash_new(); 69 | hash_set(hash, "foo", "bar"); 70 | assert(0 == strcmp("bar", hash_get(hash, "foo"))); 71 | assert(NULL == hash_get(hash, "bar")); 72 | } 73 | 74 | void test_hash_has() { 75 | hash_t *hash = hash_new(); 76 | hash_set(hash, "foo", "bar"); 77 | assert(1 == hash_has(hash, "foo")); 78 | assert(0 == hash_has(hash, "bar")); 79 | } 80 | 81 | void test_hash_size() { 82 | hash_t *hash = hash_new(); 83 | assert(0 == hash_size(hash)); 84 | hash_set(hash, "foo", "bar"); 85 | assert(1 == hash_size(hash)); 86 | hash_set(hash, "bar", "baz"); 87 | assert(2 == hash_size(hash)); 88 | } 89 | 90 | void test_hash_del() { 91 | hash_t *hash = hash_new(); 92 | hash_set(hash, "foo", "bar"); 93 | assert(1 == hash_has(hash, "foo")); 94 | assert(0 == hash_has(hash, "bar")); 95 | hash_del(hash, "foo"); 96 | hash_del(hash, "bar"); 97 | assert(0 == hash_has(hash, "foo")); 98 | } 99 | 100 | void test_hash_clear() { 101 | hash_t *hash = hash_new(); 102 | hash_set(hash, "foo", "bar"); 103 | hash_set(hash, "bar", "baz"); 104 | hash_set(hash, "raz", "jaz"); 105 | assert(3 == hash_size(hash)); 106 | hash_clear(hash); 107 | assert(0 == hash_size(hash)); 108 | } 109 | 110 | void test_hash_each() { 111 | hash_t *hash = hash_new(); 112 | hash_set(hash, "name", "tj"); 113 | hash_set(hash, "age", "25"); 114 | 115 | const char *keys[2]; 116 | void *vals[2]; 117 | int n = 0; 118 | 119 | hash_each(hash, { 120 | keys[n] = key; 121 | vals[n] = val; 122 | n++; 123 | }); 124 | 125 | assert(0 == strcmp("age", keys[0]) || 0 == strcmp("name", keys[0])); 126 | assert(0 == strcmp("age", keys[1]) || 0 == strcmp("name", keys[1])); 127 | assert(0 == strcmp("25", vals[0]) || 0 == strcmp("tj", vals[0])); 128 | assert(0 == strcmp("25", vals[1]) || 0 == strcmp("tj", vals[1])); 129 | } 130 | 131 | void test_hash_each_key() { 132 | hash_t *hash = hash_new(); 133 | hash_set(hash, "name", "tj"); 134 | hash_set(hash, "age", "25"); 135 | 136 | const char *keys[2]; 137 | int n = 0; 138 | 139 | hash_each_key(hash, { 140 | keys[n++] = key; 141 | }); 142 | 143 | assert(0 == strcmp("age", keys[0]) || 0 == strcmp("name", keys[0])); 144 | assert(0 == strcmp("age", keys[1]) || 0 == strcmp("name", keys[1])); 145 | } 146 | 147 | void test_hash_each_val() { 148 | hash_t *hash = hash_new(); 149 | hash_set(hash, "name", "tj"); 150 | hash_set(hash, "age", "25"); 151 | 152 | void *vals[2]; 153 | int n = 0; 154 | 155 | hash_each_val(hash, { 156 | vals[n++] = val; 157 | }); 158 | 159 | assert(0 == strcmp("25", vals[0]) || 0 == strcmp("tj", vals[0])); 160 | assert(0 == strcmp("25", vals[1]) || 0 == strcmp("tj", vals[1])); 161 | } 162 | 163 | int main(){ 164 | test_hash_set(); 165 | test_hash_get(); 166 | test_hash_has(); 167 | test_hash_del(); 168 | test_hash_size(); 169 | test_hash_clear(); 170 | test_hash_each(); 171 | test_hash_each_key(); 172 | test_hash_each_val(); 173 | printf("\n \e[32m\u2713 \e[90mok\e[0m\n\n"); 174 | return 0; 175 | } 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /cpp/hash/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @file hash.h 3 | * @auther Akagi201 4 | * 5 | * @date 2016/07/06 6 | */ 7 | 8 | #ifndef HASH_H_ 9 | #define HASH_H_ 10 | 11 | #include "khash.h" 12 | 13 | // pointer hash 14 | 15 | KHASH_MAP_INIT_STR(ptr, void *) 16 | 17 | /* 18 | * Hash type. 19 | */ 20 | 21 | typedef khash_t(ptr) hash_t; 22 | 23 | /* 24 | * Allocate a new hash. 25 | */ 26 | 27 | #define hash_new() kh_init(ptr) 28 | 29 | /* 30 | * Destroy the hash. 31 | */ 32 | 33 | #define hash_free(self) kh_destroy(ptr, self) 34 | 35 | /* 36 | * Hash size. 37 | */ 38 | 39 | #define hash_size kh_size 40 | 41 | /* 42 | * Remove all pairs in the hash. 43 | */ 44 | 45 | #define hash_clear(self) kh_clear(ptr, self) 46 | 47 | /* 48 | * Iterate hash keys and ptrs, populating 49 | * `key` and `val`. 50 | */ 51 | 52 | #define hash_each(self, block) { \ 53 | const char *key; \ 54 | void *val; \ 55 | for (khiter_t k = kh_begin(self); k < kh_end(self); ++k) { \ 56 | if (!kh_exist(self, k)) continue; \ 57 | key = kh_key(self, k); \ 58 | val = kh_value(self, k); \ 59 | block; \ 60 | } \ 61 | } 62 | 63 | /* 64 | * Iterate hash keys, populating `key`. 65 | */ 66 | 67 | #define hash_each_key(self, block) { \ 68 | const char *key; \ 69 | for (khiter_t k = kh_begin(self); k < kh_end(self); ++k) { \ 70 | if (!kh_exist(self, k)) continue; \ 71 | key = kh_key(self, k); \ 72 | block; \ 73 | } \ 74 | } 75 | 76 | /* 77 | * Iterate hash ptrs, populating `val`. 78 | */ 79 | 80 | #define hash_each_val(self, block) { \ 81 | void *val; \ 82 | for (khiter_t k = kh_begin(self); k < kh_end(self); ++k) { \ 83 | if (!kh_exist(self, k)) continue; \ 84 | val = kh_value(self, k); \ 85 | block; \ 86 | } \ 87 | } 88 | 89 | // protos 90 | 91 | void hash_set(hash_t *self, char *key, void *val); 92 | 93 | void *hash_get(hash_t *self, char *key); 94 | 95 | int hash_has(hash_t *self, char *key); 96 | 97 | void hash_del(hash_t *self, char *key); 98 | 99 | void hash_clear(hash_t *self); 100 | 101 | #endif // HASH_H_ 102 | -------------------------------------------------------------------------------- /cpp/hash/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include "hash.h" 5 | 6 | int main() { 7 | hash_t *hash = hash_new(); 8 | hash_set(hash, "name", (void *)"Akagi201"); 9 | hash_set(hash, "age", (void *)"22"); 10 | 11 | hash_each(hash, { 12 | printf("%s: %s\n", key, (char *) val); 13 | }); 14 | 15 | hash_free(hash); 16 | 17 | return 0; 18 | } -------------------------------------------------------------------------------- /cpp/homework/assignment2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akagi201/learning-c-cpp/998370e4fdd59c867f3b1e2b8840f38500c5c634/cpp/homework/assignment2.pdf -------------------------------------------------------------------------------- /cpp/homework/sun_hw1_q1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void get_binary(double x, int *b, int m) { 5 | double c = x; 6 | for (int i = 0; i < m; i++) { 7 | b[i] = floor(2 * c); 8 | c = 2 * c - b[i]; 9 | } 10 | } 11 | 12 | int main() { 13 | int b[30] = {}; 14 | get_binary(0.1, b, 30); 15 | 16 | for (int i = 0; i < 30; i++) { 17 | printf("%d", b[i]); 18 | } 19 | 20 | printf("\n"); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /cpp/homework/sun_hw1_q2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Kahan Sum 5 | double kahan_sum(double *a, int length) { 6 | double sum = a[1]; 7 | double c = 0.0, y, t; 8 | int i; 9 | 10 | for (i = 2; i < length; i++) { 11 | y = a[i] - c; 12 | t = sum + y; 13 | c = (t - sum) - y; 14 | sum = t; 15 | } 16 | 17 | return sum; 18 | } 19 | 20 | // Naive Sum 21 | double naive_sum(double *a, int length) { 22 | double sum = 0; 23 | for (int i = 1; i < length; i++) { 24 | sum += a[i]; 25 | } 26 | 27 | return sum; 28 | } 29 | 30 | int main() { 31 | double table[10000] = {}; 32 | table[0] = 1.0; 33 | for (int i = 1; i < 10000; i++) { 34 | table[i] = 1e-16; 35 | } 36 | printf("naive = %1.14e\n", naive_sum(table, 10000)); 37 | printf("kahan = %1.14e\n", kahan_sum(table, 10000)); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /cpp/metadata/hash.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @file hash.cpp 3 | * @auther Akagi201 4 | * 5 | * @date 2016/07/06 6 | */ 7 | 8 | #include "hash.h" 9 | 10 | /* 11 | * Set hash `key` to `val`. 12 | */ 13 | 14 | void hash_set(hash_t *self, char *key, void *val) { 15 | int ret; 16 | khiter_t k = kh_put(ptr, self, key, &ret); 17 | kh_value(self, k) = val; 18 | } 19 | 20 | /* 21 | * Get hash `key`, or NULL. 22 | */ 23 | 24 | void *hash_get(hash_t *self, char *key) { 25 | khiter_t k = kh_get(ptr, self, key); 26 | return k == kh_end(self) ? NULL : kh_value(self, k); 27 | } 28 | 29 | /* 30 | * Check if hash `key` exists. 31 | */ 32 | 33 | int hash_has(hash_t *self, char *key) { 34 | khiter_t k = kh_get(ptr, self, key); 35 | return k != kh_end(self); 36 | } 37 | 38 | /* 39 | * Remove hash `key`. 40 | */ 41 | 42 | void hash_del(hash_t *self, char *key) { 43 | khiter_t k = kh_get(ptr, self, key); 44 | kh_del(ptr, self, k); 45 | } 46 | 47 | // tests 48 | 49 | #ifdef TEST_HASH 50 | 51 | #include 52 | #include 53 | #include 54 | 55 | void test_hash_set() { 56 | hash_t *hash = hash_new(); 57 | assert(0 == hash_size(hash)); 58 | 59 | hash_set(hash, "name", "tobi"); 60 | hash_set(hash, "species", "ferret"); 61 | assert(2 == hash_size(hash)); 62 | 63 | assert(0 == strcmp("tobi", hash_get(hash, "name"))); 64 | assert(0 == strcmp("ferret", hash_get(hash, "species"))); 65 | } 66 | 67 | void test_hash_get() { 68 | hash_t *hash = hash_new(); 69 | hash_set(hash, "foo", "bar"); 70 | assert(0 == strcmp("bar", hash_get(hash, "foo"))); 71 | assert(NULL == hash_get(hash, "bar")); 72 | } 73 | 74 | void test_hash_has() { 75 | hash_t *hash = hash_new(); 76 | hash_set(hash, "foo", "bar"); 77 | assert(1 == hash_has(hash, "foo")); 78 | assert(0 == hash_has(hash, "bar")); 79 | } 80 | 81 | void test_hash_size() { 82 | hash_t *hash = hash_new(); 83 | assert(0 == hash_size(hash)); 84 | hash_set(hash, "foo", "bar"); 85 | assert(1 == hash_size(hash)); 86 | hash_set(hash, "bar", "baz"); 87 | assert(2 == hash_size(hash)); 88 | } 89 | 90 | void test_hash_del() { 91 | hash_t *hash = hash_new(); 92 | hash_set(hash, "foo", "bar"); 93 | assert(1 == hash_has(hash, "foo")); 94 | assert(0 == hash_has(hash, "bar")); 95 | hash_del(hash, "foo"); 96 | hash_del(hash, "bar"); 97 | assert(0 == hash_has(hash, "foo")); 98 | } 99 | 100 | void test_hash_clear() { 101 | hash_t *hash = hash_new(); 102 | hash_set(hash, "foo", "bar"); 103 | hash_set(hash, "bar", "baz"); 104 | hash_set(hash, "raz", "jaz"); 105 | assert(3 == hash_size(hash)); 106 | hash_clear(hash); 107 | assert(0 == hash_size(hash)); 108 | } 109 | 110 | void test_hash_each() { 111 | hash_t *hash = hash_new(); 112 | hash_set(hash, "name", "tj"); 113 | hash_set(hash, "age", "25"); 114 | 115 | const char *keys[2]; 116 | void *vals[2]; 117 | int n = 0; 118 | 119 | hash_each(hash, { 120 | keys[n] = key; 121 | vals[n] = val; 122 | n++; 123 | }); 124 | 125 | assert(0 == strcmp("age", keys[0]) || 0 == strcmp("name", keys[0])); 126 | assert(0 == strcmp("age", keys[1]) || 0 == strcmp("name", keys[1])); 127 | assert(0 == strcmp("25", vals[0]) || 0 == strcmp("tj", vals[0])); 128 | assert(0 == strcmp("25", vals[1]) || 0 == strcmp("tj", vals[1])); 129 | } 130 | 131 | void test_hash_each_key() { 132 | hash_t *hash = hash_new(); 133 | hash_set(hash, "name", "tj"); 134 | hash_set(hash, "age", "25"); 135 | 136 | const char *keys[2]; 137 | int n = 0; 138 | 139 | hash_each_key(hash, { 140 | keys[n++] = key; 141 | }); 142 | 143 | assert(0 == strcmp("age", keys[0]) || 0 == strcmp("name", keys[0])); 144 | assert(0 == strcmp("age", keys[1]) || 0 == strcmp("name", keys[1])); 145 | } 146 | 147 | void test_hash_each_val() { 148 | hash_t *hash = hash_new(); 149 | hash_set(hash, "name", "tj"); 150 | hash_set(hash, "age", "25"); 151 | 152 | void *vals[2]; 153 | int n = 0; 154 | 155 | hash_each_val(hash, { 156 | vals[n++] = val; 157 | }); 158 | 159 | assert(0 == strcmp("25", vals[0]) || 0 == strcmp("tj", vals[0])); 160 | assert(0 == strcmp("25", vals[1]) || 0 == strcmp("tj", vals[1])); 161 | } 162 | 163 | int main(){ 164 | test_hash_set(); 165 | test_hash_get(); 166 | test_hash_has(); 167 | test_hash_del(); 168 | test_hash_size(); 169 | test_hash_clear(); 170 | test_hash_each(); 171 | test_hash_each_key(); 172 | test_hash_each_val(); 173 | printf("\n \e[32m\u2713 \e[90mok\e[0m\n\n"); 174 | return 0; 175 | } 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /cpp/metadata/hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * @file hash.h 3 | * @auther Akagi201 4 | * 5 | * @date 2016/07/06 6 | */ 7 | 8 | #ifndef HASH_H_ 9 | #define HASH_H_ 10 | 11 | #include "khash.h" 12 | 13 | // pointer hash 14 | 15 | KHASH_MAP_INIT_STR(ptr, void *) 16 | 17 | /* 18 | * Hash type. 19 | */ 20 | 21 | typedef khash_t(ptr) hash_t; 22 | 23 | /* 24 | * Allocate a new hash. 25 | */ 26 | 27 | #define hash_new() kh_init(ptr) 28 | 29 | /* 30 | * Destroy the hash. 31 | */ 32 | 33 | #define hash_free(self) kh_destroy(ptr, self) 34 | 35 | /* 36 | * Hash size. 37 | */ 38 | 39 | #define hash_size kh_size 40 | 41 | /* 42 | * Remove all pairs in the hash. 43 | */ 44 | 45 | #define hash_clear(self) kh_clear(ptr, self) 46 | 47 | /* 48 | * Iterate hash keys and ptrs, populating 49 | * `key` and `val`. 50 | */ 51 | 52 | #define hash_each(self, block) { \ 53 | const char *key; \ 54 | void *val; \ 55 | for (khiter_t k = kh_begin(self); k < kh_end(self); ++k) { \ 56 | if (!kh_exist(self, k)) continue; \ 57 | key = kh_key(self, k); \ 58 | val = kh_value(self, k); \ 59 | block; \ 60 | } \ 61 | } 62 | 63 | /* 64 | * Iterate hash keys, populating `key`. 65 | */ 66 | 67 | #define hash_each_key(self, block) { \ 68 | const char *key; \ 69 | for (khiter_t k = kh_begin(self); k < kh_end(self); ++k) { \ 70 | if (!kh_exist(self, k)) continue; \ 71 | key = kh_key(self, k); \ 72 | block; \ 73 | } \ 74 | } 75 | 76 | /* 77 | * Iterate hash ptrs, populating `val`. 78 | */ 79 | 80 | #define hash_each_val(self, block) { \ 81 | void *val; \ 82 | for (khiter_t k = kh_begin(self); k < kh_end(self); ++k) { \ 83 | if (!kh_exist(self, k)) continue; \ 84 | val = kh_value(self, k); \ 85 | block; \ 86 | } \ 87 | } 88 | 89 | // protos 90 | 91 | void hash_set(hash_t *self, char *key, void *val); 92 | 93 | void *hash_get(hash_t *self, char *key); 94 | 95 | int hash_has(hash_t *self, char *key); 96 | 97 | void hash_del(hash_t *self, char *key); 98 | 99 | void hash_clear(hash_t *self); 100 | 101 | #endif // HASH_H_ 102 | -------------------------------------------------------------------------------- /cpp/metadata/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "strsplit.h" 6 | #include "trim.h" 7 | #include "substr.h" 8 | #include "hash.h" 9 | 10 | #define OBJECT_STR "Object" 11 | #define PROPERTY_STR "Property" 12 | #define NUMBER_STR "Number" 13 | #define STRING_STR "String" 14 | #define BOOLEAN_STR "Boolean" 15 | 16 | char textbuf[2048]; 17 | 18 | typedef struct metadata_property_s { 19 | char type[16]; 20 | char value[256]; 21 | } metadata_property_t; 22 | 23 | typedef struct metadata_s { 24 | hash_t *meta; 25 | int len; 26 | } metadata_t; 27 | 28 | // 0: success / not 0: fail 29 | void parse_metadata(char *meta_str, metadata_t *metadata) { 30 | if (NULL == meta_str || NULL == metadata) { 31 | return; 32 | } 33 | 34 | char *line = NULL; 35 | 36 | line = strtok(strdup(textbuf), "\n"); 37 | metadata_property_t meta_property; 38 | memset(metadata, 0, sizeof(metadata_t)); 39 | memset(&meta_property, 0, sizeof(meta_property)); 40 | metadata->meta = hash_new(); 41 | 42 | char *parts[256] = {NULL}; 43 | int size = 0; 44 | 45 | char *line_parts[256] = {NULL}; 46 | int line_size = 0; 47 | char *key = NULL; 48 | char *type = NULL; 49 | char *value = NULL; 50 | 51 | size = strsplit(textbuf, parts, "\n"); 52 | 53 | for (int i = 0; i < size; i++) { 54 | // printf("%s\n", trim(parts[i])); 55 | line_size = strsplit(trim(parts[i]), line_parts, " "); 56 | 57 | if (0 == strcmp(line_parts[0], OBJECT_STR)) { 58 | // printf("%s\n", substr(line_parts[1], 1, -1)); 59 | metadata->len = atoi(substr(line_parts[1], 1, -1)); 60 | // printf("%d\n", metadata->len); 61 | } else if (0 == strcmp(line_parts[0], PROPERTY_STR)) { 62 | key = substr(line_parts[1], 1, strlen(line_parts[1]) - 1); 63 | type = line_parts[2]; 64 | value = line_parts[3]; 65 | 66 | // printf("key: %s, len: %lu\n", key, strlen(key)); 67 | // printf("type: %s, len: %lu\n", type, strlen(type)); 68 | // printf("value: %s, len: %lu\n", value, strlen(value)); 69 | 70 | metadata_property_t *meta_property = (metadata_property_t *)calloc(1, sizeof(metadata_property_t)); 71 | 72 | memcpy(meta_property->type, type, strlen(type)); 73 | memcpy(meta_property->value, value, strlen(value)); 74 | 75 | hash_set(metadata->meta, key, (void *)meta_property); 76 | } 77 | 78 | for (int i = 0; i < line_size; i++) { 79 | free(line_parts[i]); 80 | } 81 | } 82 | 83 | for (int i = 0; i < size; i++) { 84 | free(parts[i]); 85 | } 86 | } 87 | 88 | void print_metadata(const metadata_t *metadata) { 89 | printf("print metadata begin\n"); 90 | if (NULL == metadata) { 91 | return; 92 | } 93 | metadata_property_t *meta_property = NULL; 94 | printf("len: %d\n", metadata->len); 95 | 96 | hash_each(metadata->meta, { 97 | meta_property = (metadata_property_t *) val; 98 | printf("key: %s, type: %s, value: %s\n", key, meta_property->type, meta_property->value); 99 | }); 100 | printf("print metadata end\n"); 101 | } 102 | 103 | void free_metadata(metadata_t *metadata) { 104 | if (NULL == metadata) { 105 | return; 106 | } 107 | metadata_property_t *meta_property = NULL; 108 | hash_each_val(metadata->meta, { 109 | meta_property = (metadata_property_t *) val; 110 | free(meta_property); 111 | }); 112 | hash_free(metadata->meta); 113 | } 114 | 115 | int main() { 116 | char *line = NULL; 117 | FILE *fp = NULL; 118 | 119 | fp = fopen("meta.txt", "r"); 120 | memset(textbuf, 0, sizeof(textbuf)); 121 | fread(textbuf, 1, sizeof(textbuf), fp); 122 | 123 | metadata_t metadata; 124 | memset(&metadata, 0, sizeof(metadata)); 125 | 126 | parse_metadata(textbuf, &metadata); 127 | print_metadata(&metadata); 128 | free_metadata(&metadata); 129 | 130 | return 0; 131 | } 132 | -------------------------------------------------------------------------------- /cpp/metadata/meta.txt: -------------------------------------------------------------------------------- 1 | Object (22 items) 2 | Property 'width' Number 640.0 3 | Property 'height' Number 360.0 4 | Property 'videodatarate' Number 509.6 5 | Property 'framerate' Number 24.0 6 | Property 'videocodecid' Number 7.0 7 | Property 'audiodatarate' Number 91.4 8 | Property 'audiosamplerate' Number 44100.0 9 | Property 'audiosamplesize' Number 16.0 10 | Property 'stereo' Boolean true 11 | Property 'audiocodecid' Number 10.0 12 | Property 'major_brand' String isom 13 | Property 'minor_version' String 1 14 | Property 'compatible_brands' String isom 15 | Property 'encoder' String Lavf55.19.104 16 | Property 'filesize' Number 0.0 17 | Property 'server' String UPYUN/4.0.119(BMS) 18 | Property 'srs_primary' String UPYUN/3.0release 19 | Property 'srs_authors' String Chnvideo 20 | Property 'server_version' String 4.0.119 21 | Property 'srs_pid' Number 2667347.0 22 | Property 'srs_id' Number 217209.0 23 | Property 'srs_server_ip' String 183.134.101.203 24 | -------------------------------------------------------------------------------- /cpp/metadata/strsplit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "strsplit.h" 4 | //#include "strdup/strdup.h" 5 | 6 | int strsplit(const char *str, char *parts[], const char *delimiter) { 7 | char *pch; 8 | int i = 0; 9 | char *copy = NULL, *tmp = NULL; 10 | 11 | copy = strdup(str); 12 | if (!copy) { 13 | goto bad; 14 | } 15 | 16 | pch = strtok(copy, delimiter); 17 | 18 | tmp = strdup(pch); 19 | if (!tmp) { 20 | goto bad; 21 | } 22 | 23 | parts[i++] = tmp; 24 | 25 | while (pch) { 26 | pch = strtok(NULL, delimiter); 27 | if (NULL == pch) { 28 | break; 29 | } 30 | 31 | tmp = strdup(pch); 32 | if (!tmp) { 33 | goto bad; 34 | } 35 | 36 | parts[i++] = tmp; 37 | } 38 | 39 | free(copy); 40 | return i; 41 | 42 | bad: 43 | free(copy); 44 | for (int j = 0; j < i; j++) { 45 | free(parts[j]); 46 | } 47 | return -1; 48 | } 49 | -------------------------------------------------------------------------------- /cpp/metadata/strsplit.h: -------------------------------------------------------------------------------- 1 | #ifndef STRSPLIT_H 2 | #define STRSPLIT_H 1 3 | 4 | int strsplit(const char *, char *[], const char *); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /cpp/metadata/substr.cpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // substr.c 4 | // 5 | // Copyright (c) 2013 Stephen Mathieson 6 | // MIT licensed 7 | // 8 | 9 | #include 10 | #include 11 | #include "substr.h" 12 | 13 | /* 14 | * Get a substring of `str` from `start` to `end` 15 | */ 16 | 17 | char *substr(const char *str, int start, int end) { 18 | if (0 > start) return NULL; 19 | int len = strlen(str); 20 | // -1 == length of string 21 | if (-1 == end) end = len; 22 | if (end <= start) return NULL; 23 | int diff = end - start; 24 | if (len == diff) return strdup(str); 25 | if (len < start) return NULL; 26 | if (len + 1 < end) return NULL; 27 | 28 | char *res = (char *)malloc(sizeof(char) * diff + 1); 29 | if (NULL == res) return NULL; 30 | memset(res, '\0', diff + 1); 31 | strncpy(res, str + start, diff); 32 | return res; 33 | } 34 | -------------------------------------------------------------------------------- /cpp/metadata/substr.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // substr.h 4 | // 5 | // Copyright (c) 2013 Stephen Mathieson 6 | // MIT licensed 7 | // 8 | 9 | 10 | #ifndef SUBSTR_H_ 11 | #define SUBSTR_H_ 12 | 13 | char *substr(const char *str, int start, int end); 14 | 15 | #endif // SUBSTR_H_ 16 | -------------------------------------------------------------------------------- /cpp/metadata/trim.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "trim.h" 4 | 5 | char *trim_left(char *str) { 6 | int len = strlen(str); 7 | char *cur = str; 8 | 9 | while (*cur && isspace(*cur)) { 10 | ++cur; 11 | --len; 12 | } 13 | 14 | if (str != cur) { 15 | memmove(str, cur, len + 1); 16 | } 17 | 18 | return str; 19 | } 20 | 21 | char *trim_right(char *str) { 22 | int len = strlen(str); 23 | char *cur = str + len - 1; 24 | 25 | while (cur != str && isspace(*cur)) { 26 | --cur; 27 | } 28 | cur[isspace(*cur) ? 0 : 1] = '\0'; 29 | 30 | return str; 31 | } 32 | 33 | char *trim(char *str) { 34 | trim_right(str); 35 | trim_left(str); 36 | return str; 37 | } 38 | -------------------------------------------------------------------------------- /cpp/metadata/trim.h: -------------------------------------------------------------------------------- 1 | #ifndef TRIM_H 2 | #define TRIM_H 1 3 | 4 | char *trim(char *); 5 | 6 | char *trim_right(char *); 7 | 8 | char *trim_left(char *); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /cpp/rand/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(cppdemo) 2 | cmake_minimum_required(VERSION 3.0) 3 | 4 | set( CMAKE_CXX_STANDARD 14 ) 5 | set( CMAKE_CXX_EXTENSIONS ON ) 6 | set( CXX_STANDARD_REQUIRED ON) 7 | 8 | add_executable(${PROJECT_NAME} main.cpp) 9 | -------------------------------------------------------------------------------- /cpp/rand/README.md: -------------------------------------------------------------------------------- 1 | # rand 2 | 3 | ## Refs 4 | * -------------------------------------------------------------------------------- /cpp/rand/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "rand.hpp" 5 | 6 | int main() { 7 | std::cout << "time: " << std::time(nullptr) << std::endl; 8 | auto r = eosio::random(uint64_t(std::time(nullptr))); 9 | std::cout << "rand: " << r.next() << std::endl; 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /cpp/rand/rand.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /// High performance random generator 6 | /// http://xorshift.di.unimi.it/ 7 | 8 | namespace eosio { 9 | class random { 10 | private: 11 | uint64_t seed; 12 | 13 | public: 14 | random(uint64_t seed) { 15 | this->seed = seed; 16 | } 17 | 18 | uint64_t next() { 19 | uint64_t z = (seed += UINT64_C(0x9E3779B97F4A7C15)); 20 | z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9); 21 | z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB); 22 | return z ^ (z >> 31); 23 | } 24 | 25 | template 26 | void shuffle(Range&& range) { 27 | int idx_count = range.size(); 28 | for (auto idx = range.rbegin(); idx != range.rend() - 1; ++idx , --idx_count) { 29 | std::swap(range.at(next() % idx_count), *idx); 30 | } 31 | } 32 | }; 33 | } -------------------------------------------------------------------------------- /cpp/spdlog/basic.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "spdlog/spdlog.h" 3 | 4 | int main(int, char* []) { 5 | // Multithreaded console logger(with color support) 6 | auto console = spdlog::stdout_color_mt("console"); 7 | console->info("Welcome to spdlog!"); 8 | console->info("An info message example {}..", 1); 9 | 10 | try { 11 | // Create basic file logger (not rotated) 12 | auto my_logger = 13 | spdlog::basic_logger_mt("basic_logger", "logs/basic.txt"); 14 | 15 | // create a file rotating logger with 5mb size max and 3 rotated files 16 | auto file_logger = spdlog::rotating_logger_mt( 17 | "file_logger", "myfilename", 1024 * 1024 * 5, 3); 18 | } catch (const spdlog::spdlog_ex& ex) { 19 | std::cout << "Log initialization failed: " << ex.what() << std::endl; 20 | } 21 | } -------------------------------------------------------------------------------- /cpp/spdlog/example.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "spdlog/spdlog.h" 5 | 6 | void async_example(); 7 | void syslog_example(); 8 | void user_defined_example(); 9 | void err_handler_example(); 10 | 11 | namespace spd = spdlog; 12 | int main(int, char* []) { 13 | try { 14 | // Console logger with color 15 | auto console = spd::stdout_color_mt("console"); 16 | console->info("Welcome to spdlog!"); 17 | console->error("Some error message with arg{}..", 1); 18 | 19 | // Formatting examples 20 | console->warn("Easy padding in numbers like {:08d}", 12); 21 | console->critical( 22 | "Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 23 | 42); 24 | console->info("Support for floats {:03.2f}", 1.23456); 25 | console->info("Positional args are {1} {0}..", "too", "supported"); 26 | console->info("{:<30}", "left aligned"); 27 | 28 | 29 | spd::get("console")->info( 30 | "loggers can be retrieved from a global registry using the " 31 | "spdlog::get(logger_name) function"); 32 | 33 | // Create basic file logger (not rotated) 34 | auto my_logger = 35 | spd::basic_logger_mt("basic_logger", "logs/basic.txt"); 36 | my_logger->info("Some log message"); 37 | 38 | // Create a file rotating logger with 5mb size max and 3 rotated files 39 | auto rotating_logger = spd::rotating_logger_mt( 40 | "some_logger_name", "logs/mylogfile", 1048576 * 5, 3); 41 | for (int i = 0; i < 10; ++i) 42 | rotating_logger->info("{} * {} equals {:>10}", i, i, i * i); 43 | 44 | // Create a daily logger - a new file is created every day on 2:30am 45 | auto daily_logger = 46 | spd::daily_logger_mt("daily_logger", "logs/daily", 2, 30); 47 | // trigger flush if the log severity is error or higher 48 | daily_logger->flush_on(spd::level::err); 49 | daily_logger->info(123.44); 50 | 51 | // Customize msg format for all messages 52 | spd::set_pattern("*** [%H:%M:%S %z] [thread %t] %v ***"); 53 | rotating_logger->info("This is another message with custom format"); 54 | 55 | 56 | // Runtime log levels 57 | spd::set_level(spd::level::info); // Set global log level to info 58 | console->debug("This message shold not be displayed!"); 59 | console->set_level( 60 | spd::level::debug); // Set specific logger's log level 61 | console->debug("This message shold be displayed.."); 62 | 63 | // Compile time log levels 64 | // define SPDLOG_DEBUG_ON or SPDLOG_TRACE_ON 65 | SPDLOG_TRACE(console, "Enabled only #ifdef SPDLOG_TRACE_ON..{} ,{}", 1, 66 | 3.23); 67 | SPDLOG_DEBUG(console, "Enabled only #ifdef SPDLOG_DEBUG_ON.. {} ,{}", 68 | 1, 3.23); 69 | 70 | // Asynchronous logging is very fast.. 71 | // Just call spdlog::set_async_mode(q_size) and all created loggers 72 | // from now on will be asynchronous.. 73 | async_example(); 74 | 75 | // syslog example. linux/osx only 76 | syslog_example(); 77 | 78 | // android example. compile with NDK 79 | android_example(); 80 | 81 | // Log user-defined types example 82 | user_defined_example(); 83 | 84 | // Change default log error handler 85 | err_handler_example(); 86 | 87 | // Apply a function on all registered loggers 88 | spd::apply_all([&](std::shared_ptr l) { 89 | l->info("End of example."); 90 | }); 91 | 92 | // Release and close all loggers 93 | spd::drop_all(); 94 | } 95 | // Exceptions will only be thrown upon failed logger or sink construction 96 | // (not during logging) 97 | catch (const spd::spdlog_ex& ex) { 98 | std::cout << "Log init failed: " << ex.what() << std::endl; 99 | return 1; 100 | } 101 | } 102 | 103 | void async_example() { 104 | size_t q_size = 4096; // queue size must be power of 2 105 | spd::set_async_mode(q_size); 106 | auto async_file = 107 | spd::daily_logger_st("async_file_logger", "logs/async_log.txt"); 108 | for (int i = 0; i < 100; ++i) 109 | async_file->info("Async message #{}", i); 110 | } 111 | 112 | // syslog example 113 | void syslog_example() { 114 | #ifdef SPDLOG_ENABLE_SYSLOG 115 | std::string ident = "spdlog-example"; 116 | auto syslog_logger = spd::syslog_logger("syslog", ident, LOG_PID); 117 | syslog_logger->warn("This is warning that will end up in syslog.."); 118 | #endif 119 | } 120 | 121 | // user defined types logging by implementing operator<< 122 | struct my_type { 123 | int i; 124 | template 125 | friend OStream& operator<<(OStream& os, const my_type& c) { 126 | return os << "[my_type i=" << c.i << "]"; 127 | } 128 | }; 129 | 130 | #include // must be included 131 | void user_defined_example() { 132 | spd::get("console")->info("user defined type: {}", my_type{14}); 133 | } 134 | 135 | // 136 | // custom error handler 137 | // 138 | void err_handler_example() { 139 | spd::set_error_handler([](const std::string& msg) { 140 | std::cerr << "my err handler: " << msg << std::endl; 141 | }); 142 | // (or logger->set_error_handler(..) to set for specific logger) 143 | } -------------------------------------------------------------------------------- /cpp/stl/copy/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main() { 8 | std::vector from_vector(10); 9 | std::iota(from_vector.begin(), from_vector.end(), 0); 10 | 11 | std::vector to_vector; 12 | std::copy(from_vector.begin(), from_vector.end(), 13 | std::back_inserter(to_vector)); 14 | // or, alternatively, 15 | // std::vector to_vector(from_vector.size()); 16 | // std::copy(from_vector.begin(), from_vector.end(), to_vector.begin()); 17 | // either way is equivalent to 18 | // std::vector to_vector = from_vector; 19 | 20 | std::cout << "to_vector contains: "; 21 | 22 | std::copy(to_vector.begin(), to_vector.end(), 23 | std::ostream_iterator(std::cout, " ")); 24 | std::cout << '\n'; 25 | } 26 | -------------------------------------------------------------------------------- /cpp/swig/cmake-python-swig-rpath-example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | cmake_minimum_required(VERSION 2.6) 3 | project(stats) 4 | add_subdirectory(src) 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /cpp/swig/cmake-python-swig-rpath-example/README.md: -------------------------------------------------------------------------------- 1 | # cmake-python-swig-rpath-example 2 | How do CMake, Python, SWIG and RPATH work together? 3 | 4 | We are encouraged (aren't we?) to use modern tools appropriate for the job - and those seem to be 5 | (at least in my little part of the scientific world) CMake, Python, C++ and SWIG to glue them together. 6 | 7 | How should we do that exactly? 8 | 9 | Err... 10 | 11 | Now try it using RPATH. 12 | 13 | Now try it on a Mac... 14 | 15 | 16 | Hmm... 17 | 18 | I did some googling and reading and the answer to that was utterly opaque to me. 19 | 20 | So here's a project simply designed to be the project that I would have liked to have found 21 | several weeks ago. 22 | 23 | Some interesting reading: 24 | 25 | https://cmake.org/Wiki/CMake_RPATH_handling 26 | 27 | https://blog.kitware.com/upcoming-in-cmake-2-8-12-osx-rpath-support/ 28 | 29 | http://stackoverflow.com/questions/33991581/install-name-tool-to-update-a-executable-to-search-for-dylib-in-mac-os-x 30 | 31 | -------------------------------------------------------------------------------- /cpp/swig/cmake-python-swig-rpath-example/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | FIND_PACKAGE(SWIG REQUIRED) 3 | FIND_PACKAGE(PythonLibs) 4 | 5 | INCLUDE(${SWIG_USE_FILE}) 6 | 7 | INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src) 8 | INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) 9 | 10 | # we want to make a shared library libtriv_stats.dylib that 11 | # is compiled from sources stats.cc (standard CMake usage) 12 | # 13 | ADD_LIBRARY(triv_stats SHARED stats.cc) 14 | 15 | # libtriv_stats.dylib depends on the maths library (standard 16 | # CMake usage) 17 | # 18 | TARGET_LINK_LIBRARIES(triv_stats "m") 19 | 20 | # stats.i include C++ header - so tell SWIG that it should 21 | # compile in C++ mode 22 | # 23 | SET_SOURCE_FILES_PROPERTIES(stats.i PROPERTIES CPLUSPLUS ON) 24 | 25 | # running swig on stats.i makes the python module simple_module (see how 26 | # simple_module is used in test.py) - I use "simple_module" but 27 | # I could have equally have used "stats" (I'd have to mirror that 28 | # change in test.py) 29 | # 30 | SWIG_ADD_MODULE(simple_module python stats.i) 31 | 32 | # the python module simple_module wraps the class and function 33 | # of stats.hh/.cc - and the library for that compiled code is 34 | # libtriv_stats.dylib 35 | # 36 | SWIG_LINK_LIBRARIES(simple_module triv_stats ${PYTHON_LIBRARIES}) 37 | 38 | if (APPLE) 39 | 40 | # interesting reading: https://blog.kitware.com/upcoming-in-cmake-2-8-12-osx-rpath-support/ 41 | 42 | # INSTALL_NAME_DIR overrides MACOSX_RPATH. Try not to do that. 43 | 44 | # this sets the install_name of libtriv_stats.dylib as @rpath/libtriv_stats.dylib 45 | SET_TARGET_PROPERTIES(triv_stats PROPERTIES MACOSX_RPATH TRUE) 46 | SET_TARGET_PROPERTIES(triv_stats PROPERTIES CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 47 | 48 | # Use rpath for _simple_module.so 49 | SET_TARGET_PROPERTIES(_simple_module PROPERTIES MACOSX_RPATH TRUE) 50 | 51 | # append directories in the linker search path and outside the project to the INSTALL_RPATH 52 | SET_TARGET_PROPERTIES(_simple_module PROPERTIES CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 53 | 54 | # this is where libtriv_stats.dylib is installed relative to where _simple_module.so is installed 55 | SET_TARGET_PROPERTIES(_simple_module PROPERTIES INSTALL_RPATH "@loader_path/../../..") 56 | 57 | else() 58 | 59 | SET_TARGET_PROPERTIES(_simple_module PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") 60 | SET_TARGET_PROPERTIES(_simple_module PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE) 61 | 62 | endif() 63 | 64 | INSTALL(TARGETS triv_stats DESTINATION lib) 65 | INSTALL(TARGETS _simple_module DESTINATION lib/python2.7/site-packages) 66 | INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/simple_module.py DESTINATION lib/python2.7/site-packages) 67 | -------------------------------------------------------------------------------- /cpp/swig/cmake-python-swig-rpath-example/src/stats.cc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #include "stats.hh" 6 | 7 | void 8 | stats::add(const std::pair &datum) { 9 | 10 | data.push_back(datum); 11 | } 12 | 13 | void 14 | stats::add(double x, double y) { 15 | std::pair p(x,y); 16 | data.push_back(p); 17 | } 18 | 19 | double 20 | stats::mean_x() const { 21 | 22 | double sum = 0; 23 | unsigned int n = data.size(); 24 | for (unsigned int i=0; i 0) { 44 | double sum_sq = 0; 45 | for (unsigned int i=0; i 3 | #include 4 | 5 | class stats { 6 | 7 | std::vector > data; 8 | 9 | public: 10 | 11 | void add(const std::pair &datum); 12 | void add(double x, double y); 13 | 14 | double mean_x() const; 15 | double mean_y() const; 16 | double variance_y() const; 17 | double standard_deviation_y() const; 18 | 19 | }; 20 | -------------------------------------------------------------------------------- /cpp/swig/cmake-python-swig-rpath-example/src/stats.i: -------------------------------------------------------------------------------- 1 | 2 | %module simple_module 3 | 4 | %{ 5 | #include "Python.h" 6 | #include "stats.hh" 7 | %} 8 | 9 | %include "stats.hh" 10 | -------------------------------------------------------------------------------- /cpp/swig/cmake-python-swig-rpath-example/test/test.py: -------------------------------------------------------------------------------- 1 | 2 | import simple_module 3 | 4 | s = simple_module.stats() 5 | s.add(1,2) 6 | s.add(2,3) 7 | 8 | print s.standard_deviation_y() 9 | 10 | -------------------------------------------------------------------------------- /cpp/swig/tutorial/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(example) 4 | 5 | FIND_PACKAGE(SWIG REQUIRED) 6 | INCLUDE(${SWIG_USE_FILE}) 7 | 8 | FIND_PACKAGE(PythonLibs REQUIRED) 9 | INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) 10 | 11 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) 12 | 13 | SET(CMAKE_SWIG_FLAGS "") 14 | 15 | SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES C ON) 16 | SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall") 17 | SWIG_ADD_MODULE(example python example.i example.c) 18 | SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES}) 19 | 20 | -------------------------------------------------------------------------------- /cpp/swig/tutorial/README.md: -------------------------------------------------------------------------------- 1 | ## Python 2 | 3 | ``` 4 | swig -python example.i 5 | gcc -c -fpic `python-config --cflags` example.c example_wrap.c 6 | gcc -shared example.o example_wrap.o -o _example.so 7 | ``` 8 | 9 | -------------------------------------------------------------------------------- /cpp/swig/tutorial/example.c: -------------------------------------------------------------------------------- 1 | double my_variable = 3.0; 2 | 3 | // Compute factorial of n 4 | int fact(int n) { 5 | if (n <= 1) { 6 | return 1; 7 | } else { 8 | return n * fact(n-1); 9 | } 10 | } 11 | 12 | // Compute n mod m 13 | int my_mod(int n, int m) { 14 | return (n % m); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /cpp/swig/tutorial/example.i: -------------------------------------------------------------------------------- 1 | %module example 2 | %{ 3 | // Put headers and other declarations here 4 | extern double my_variable; 5 | extern int fact(int); 6 | extern int my_mod(int n, int m); 7 | %} 8 | 9 | extern double my_variable; 10 | extern int fact(int); 11 | extern int my_mod(int n, int m); 12 | 13 | -------------------------------------------------------------------------------- /cpp/swig/tutorial/example.py: -------------------------------------------------------------------------------- 1 | # This file was automatically generated by SWIG (http://www.swig.org). 2 | # Version 3.0.8 3 | # 4 | # Do not make changes to this file unless you know what you are doing--modify 5 | # the SWIG interface file instead. 6 | 7 | 8 | 9 | 10 | 11 | from sys import version_info 12 | if version_info >= (2, 6, 0): 13 | def swig_import_helper(): 14 | from os.path import dirname 15 | import imp 16 | fp = None 17 | try: 18 | fp, pathname, description = imp.find_module('_example', [dirname(__file__)]) 19 | except ImportError: 20 | import _example 21 | return _example 22 | if fp is not None: 23 | try: 24 | _mod = imp.load_module('_example', fp, pathname, description) 25 | finally: 26 | fp.close() 27 | return _mod 28 | _example = swig_import_helper() 29 | del swig_import_helper 30 | else: 31 | import _example 32 | del version_info 33 | try: 34 | _swig_property = property 35 | except NameError: 36 | pass # Python < 2.2 doesn't have 'property'. 37 | 38 | 39 | def _swig_setattr_nondynamic(self, class_type, name, value, static=1): 40 | if (name == "thisown"): 41 | return self.this.own(value) 42 | if (name == "this"): 43 | if type(value).__name__ == 'SwigPyObject': 44 | self.__dict__[name] = value 45 | return 46 | method = class_type.__swig_setmethods__.get(name, None) 47 | if method: 48 | return method(self, value) 49 | if (not static): 50 | if _newclass: 51 | object.__setattr__(self, name, value) 52 | else: 53 | self.__dict__[name] = value 54 | else: 55 | raise AttributeError("You cannot add attributes to %s" % self) 56 | 57 | 58 | def _swig_setattr(self, class_type, name, value): 59 | return _swig_setattr_nondynamic(self, class_type, name, value, 0) 60 | 61 | 62 | def _swig_getattr_nondynamic(self, class_type, name, static=1): 63 | if (name == "thisown"): 64 | return self.this.own() 65 | method = class_type.__swig_getmethods__.get(name, None) 66 | if method: 67 | return method(self) 68 | if (not static): 69 | return object.__getattr__(self, name) 70 | else: 71 | raise AttributeError(name) 72 | 73 | def _swig_getattr(self, class_type, name): 74 | return _swig_getattr_nondynamic(self, class_type, name, 0) 75 | 76 | 77 | def _swig_repr(self): 78 | try: 79 | strthis = "proxy of " + self.this.__repr__() 80 | except Exception: 81 | strthis = "" 82 | return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) 83 | 84 | try: 85 | _object = object 86 | _newclass = 1 87 | except AttributeError: 88 | class _object: 89 | pass 90 | _newclass = 0 91 | 92 | 93 | 94 | def fact(arg1): 95 | return _example.fact(arg1) 96 | fact = _example.fact 97 | 98 | def my_mod(n, m): 99 | return _example.my_mod(n, m) 100 | my_mod = _example.my_mod 101 | # This file is compatible with both classic and new-style classes. 102 | 103 | cvar = _example.cvar 104 | 105 | -------------------------------------------------------------------------------- /cpp/swig/tutorial/example.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Akagi201/learning-c-cpp/998370e4fdd59c867f3b1e2b8840f38500c5c634/cpp/swig/tutorial/example.pyc -------------------------------------------------------------------------------- /cpp/tuple/tie.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct S { 7 | int n; 8 | std::string s; 9 | float d; 10 | bool operator<(const S& rhs) const { 11 | // compares n to rhs.n, 12 | // then s to rhs.s, 13 | // then d to rhs.d 14 | return std::tie(n, s, d) < std::tie(rhs.n, rhs.s, rhs.d); 15 | } 16 | }; 17 | 18 | int main() { 19 | std::set set_of_s; // S is LessThanComparable 20 | 21 | S value{42, "Test", 3.14}; 22 | std::set::iterator iter; 23 | bool inserted; 24 | 25 | // unpacks the return value of insert into iter and inserted 26 | std::tie(iter, inserted) = set_of_s.insert(value); 27 | 28 | if (inserted) { 29 | std::cout << "Value was inserted successfully\n"; 30 | } 31 | } -------------------------------------------------------------------------------- /cpp/vector/erase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | vector arr = {0, 1, 2, 3, 4}; 8 | for (vector::iterator it=arr.begin(); it != arr.end();) { 9 | if (*it == 0) { 10 | it = arr.erase(it); 11 | } else { 12 | ++it; 13 | } 14 | } 15 | cout << arr[0] << endl; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /cpp/vector/erase_remove.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | vector name; 8 | name.push_back("world"); 9 | name.push_back("hello"); 10 | // erase-remove idiom, C++ erase vector element by value rather than by position 11 | // https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom 12 | name.erase(remove(name.begin(), name.end(), "world"), name.end()); 13 | cout << name[0] << " " << name.size() << endl; 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /cpp/vector/mem.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // vector v; 7 | char ch; 8 | 9 | int main() { 10 | vector v; 11 | for (int i = 0; i < 1000000; i++) { 12 | v.push_back("abcdefghijklmn"); 13 | } 14 | cin >> ch; 15 | // 检查内存 35M 16 | 17 | v.clear(); 18 | cin >> ch; 19 | // 检查内存 35M 20 | 21 | cout << "Vector 的容量 " << v.capacity() << endl; 22 | 23 | vector(v).swap(v); 24 | cout << "Vector 的容量 " << v.capacity() << endl; 25 | 26 | cin >> ch; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /cpp/vector/push_unique.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() { 7 | vector name; 8 | name.push_back("world"); 9 | name.push_back("hello"); 10 | if (find(name.begin(), name.end(), "hello") == name.end()) { 11 | name.push_back("hello"); 12 | } 13 | cout << name[0] << " " << name.size() << endl; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "clang-tidy starting "$*" ..." 4 | 5 | sleep 1 6 | 7 | TIDY="clang-tidy" 8 | 9 | if [ -f /usr/local/opt/llvm/bin/clang-tidy ]; then 10 | TIDY="/usr/local/opt/llvm/bin/clang-tidy" 11 | fi 12 | 13 | FORMAT="clang-format" 14 | 15 | if [ -f /usr/local/bin/clang-format ]; then 16 | FORMAT="/usr/local/bin/clang-format" 17 | fi 18 | 19 | $TIDY \ 20 | -fix \ 21 | -fix-errors \ 22 | -header-filter=.* \ 23 | --checks=readability-braces-around-statements,misc-macro-parentheses \ 24 | $* \ 25 | -- -I. 26 | 27 | echo "clang-tidy finished!" 28 | 29 | echo "clang-format starting "$*" ..." 30 | 31 | sleep 1 32 | 33 | $FORMAT -sort-includes -i $* 34 | 35 | echo "clang-format finished!" 36 | 37 | --------------------------------------------------------------------------------