need to tell the compiler it is a type not a variable by preceding 'typename' keyword.
编程
c++ move forward
lvalue: loactor value
rvalue: read value
here is an example of class definition with only one constructor using template and 'forward' technique to tackle varying parameter:
rvalue.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #include <iostream> #include <functional> using namespace std; template <typename T> constexpr bool is_lvalue(T&) { return true; } template <typename T> constexpr bool is_lvalue(T&&) { return false; } class MyStr { public: template<class T> MyStr(T&& t) { set(forward<T>(t)); } template<class T> void set(T&& t) { if constexpr (conjunction_v<is_convertible<T&, MyStr&>>) { if (!is_lvalue(forward<T>(t))) { str_ = forward<string>(t.str_); cout << "is rvalue, type MyStr." << endl; } else { str_ = t.str_; cout << "is lvalue, type MyStr." << endl; } } else { str_ = forward<T>(t); cout << "is string." << endl; } } template<class T=char> void test() { cout << "test T size is " << sizeof(T) << endl; } string str_; }; int main() { cout << "call constructor:" << endl; MyStr str1("str1"); MyStr str2(str1); MyStr str3(move(str1)); cout << "call member function:" << endl; str1.set("set1"); str2.set(str1); str3.set(move(str1)); str3.test(); return 1; } |
make
1 | g++ -o rvalue -g -O0 -std=c++17 rvalue.cpp |
output
1 2 3 4 5 6 7 8 | call constructor:
is string.
is lvalue, type MyStr.
call member function:
is string.
is lvalue, type MyStr.
is rvalue, type MyStr.
test T size is 1 |
refer to:
http://www.javashuo.com/article/p-olwxiggw-q.html
http://c.biancheng.net/view/7829.html
https://zhuanlan.zhihu.com/p/99524127
生成pcap文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #include <stdlib.h> #include <stdio.h> #include <sys/unistd.h> #include <pcap/pcap.h> typedef struct pcap_log_t pcap_log_t; struct pcap_log_t { pcap_t* pd; pcap_dumper_t* pdumper; }; pcap_log_t* pcap_log_init() { char path[256]; pcap_log_t* pcap = (pcap_log_t*)malloc(sizeof(*pcap)); memset(pcap, 0, sizeof(*pcap)); pcap->pd = pcap_open_dead(/* DLT_RAW */ 1, 65535 /* snaplen */); sprintf(path, "/tmp/pcap_%d.pcap", gettid()); pcap->pdumper = pcap_dump_open(pcap->pd, path); return pcap; } void pcap_log_write(pcap_log_t* pcap, char* packet, int len) { struct pcap_pkthdr hdr; hdr.ts.tv_sec = 0; hdr.ts.tv_usec = 0; hdr.caplen = len; hdr.len = len; pcap_dump((u_char*)pcap->pdumper, &hdr, (const u_char*)packet); pcap_dump_flush(pcap->pdumper); } void pcap_log_fini(pcap_log_t* pcap) { pcap_dump_close(pcap->pdumper); pcap_close(pcap->pd); free(pcap); } int main() { pcap_log_t* pcap = pcap_log_init(); /* while (...) { // packet is raw data from mac layer pcap_log_write(pcap, packet, len); } */ pcap_log_fini(pcap); return 0; } |
refer to:
https://blog.csdn.net/u014260236/article/details/51035484/
gcc多个include目录的优先级
gcc默认include路径
1 2 | `gcc -print-prog-name=cc1` -v `g++ -print-prog-name=cc1` -v |
优先级由大到小对应下表中的从上到下
1 2 3 4 5 | 命令行-I指定,前面的大于后面的 CPATH CPLUS_INCLUDE_PATH #只对c++文件起作用 C_INCLUDE_PATH #只对c文件起作用,即C_INCLUDE_PATH和CPLUS_INCLUDE_PATH不会同时起作用 gcc默认include路径 |
refer to:
http://www.3scard.com/index.php?m=blog&f=view&id=42
asn.1编码的转换
这个工具在
1 | strongswan/src/libstrongswan/asn1 |
以下是使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | #include <asn1/asn1.h> #include <asn1/asn1_parser.h> #define INTEGER_SIZE 32 static chunk_t chunk_to_asn1(chunk_t chunk) { chunk_t x; chunk_t y; chunk_t hash; chunk_t content; chunk_t asn1; x.ptr = chunk.ptr; x.len = INTEGER_SIZE; y.ptr = chunk.ptr + INTEGER_SIZE; y.len = INTEGER_SIZE; content.ptr = y.ptr + INTEGER_SIZE; content.len = chunk.len - INTEGER_SIZE * 3; hash.ptr = content.ptr + content.len; hash.len = INTEGER_SIZE; asn1 = asn1_wrap(ASN1_SEQUENCE, "mmmm", asn1_integer("c", x), asn1_integer("c", y), asn1_simple_object(ASN1_OCTET_STRING, hash), asn1_simple_object(ASN1_OCTET_STRING, content)); chunk_free(&chunk); return asn1; } static const asn1Object_t patterns[] = { { 0, "seq", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ { 1, "x", ASN1_INTEGER, ASN1_BODY }, /* 1 */ { 1, "y", ASN1_INTEGER, ASN1_BODY }, /* 2 */ { 1, "hash", ASN1_OCTET_STRING, ASN1_BODY }, /* 3 */ { 1, "content", ASN1_OCTET_STRING, ASN1_BODY }, /* 4 */ { 0, "exit", ASN1_EOC, ASN1_EXIT } }; #define PATTERN_KEY_X 1 #define PATTERN_KEY_Y 2 #define PATTERN_KEY_HASH 3 #define PATTERN_KEY_CONTENT 4 static chunk_t correct_integer(chunk_t chunk) { if (chunk.len == INTEGER_SIZE + 1) return chunk_skip(chunk, 1); return chunk; } static bool parse_asn1(chunk_t asn1, chunk_t* x, chunk_t* y, chunk_t* hash, chunk_t* content) { chunk_t object; asn1_parser_t *parser; bool success = FALSE; int object_id, oid, i; parser = asn1_parser_create(patterns, asn1); while (parser->iterate(parser, &object_id, &object)) { switch (object_id) { case PATTERN_KEY_X: *x = correct_integer(object); break; case PATTERN_KEY_Y: *y = correct_integer(object); break; case PATTERN_KEY_HASH: *hash = object; break; case PATTERN_KEY_CONTENT: *content = object; break; } } success = parser->success(parser); parser->destroy(parser); return success; } static bool chunk_from_asn1(chunk_t* chunk, chunk_t asn1) { chunk_t x; chunk_t y; chunk_t hash; chunk_t content; if (!parse_asn1(asn1, &x, &y, &hash, &content)) return false; *chunk = chunk_cat("cccc", x, y, content, hash); return true; } static void random_data(chunk_t chunk) { int fd = open("/dev/urandom", O_RDONLY); read(fd, chunk.ptr, chunk.len); close(fd); } int test() { bool is_ok; chunk_t result; chunk_t asn1; chunk_t total = chunk_alloc(INTEGER_SIZE * 3 + 345); random_data(total); asn1 = chunk_to_asn1(total); is_ok = chunk_from_asn1(&result, asn1); chunk_free(&result); chunk_free(&asn1); chunk_free(&total); return is_ok; } |
因为asn1模块里对ASN1_INTEGER类型有个two's complement处理,如果这个数最高位为1,则在此数前加一个0值字节,所以correct_integer函数的目地在于更正输出。
C标准库中的strtok
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <stdlib.h> #include <stdio.h> #include <string.h> #ifdef WIN32 #define EU_STRTOK strtok_s #define EU_STRDUP _strdup #else #define EU_STRTOK strtok_r #define EU_STRDUP strdup #endif int main() { char str[1000] = "Steven Jobs, Bruce Lee, Jack Chen, George W Bush"; char* pNames[100]; int idxNames = 0; char* pWords[100]; int idxWords = 0; char* buf = str; char* outPtr = NULL; while (NULL != (buf = EU_STRTOK(NULL == outPtr? buf : NULL, ",", &outPtr))) { char* innerPtr = NULL; pNames[idxNames++] = EU_STRDUP(buf); while (NULL != (buf = EU_STRTOK(NULL == innerPtr? buf : NULL, " ", &innerPtr))) { pWords[idxWords++] = buf; } } return 0; // here, to watch pNames and pWords contents in debug mode. } |
strtok有一个缺陷,比如对于源串",hello,the,world!",分隔符",",分隔结果会少了空串""。
std版字符串token提取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <iostream> #include <locale> #include <sstream> struct csv_whitespace : std::ctype<wchar_t> { bool do_is(mask m, char_type c) const { if ((m & space) && c == L' ') { return false; // space will NOT be classified as whitespace } if ((m & space) && c == L',') { return true; // comma will be classified as whitespace } return ctype::do_is(m, c); // leave the rest to the parent class } }; int main() { std::wstring in = L"Column 1, Column 2, Column 3\n123,456,789"; std::wstring token; std::wcout << "default locale:\n"; std::wistringstream s1(in); while (s1 >> token) { std::wcout << ">" << token << '\n'; } std::wcout << "locale with modified ctype:\n"; std::wistringstream s2(in); csv_whitespace* my_ws = new csv_whitespace; s2.imbue(std::locale(s2.getloc(), my_ws)); while (s2 >> token) { std::wcout << ">" << token << '\n'; } return 0; } |
std版宽字符转ASCII字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <iostream> #include <locale> int main() { std::locale loc; const char narrow_phrase[] = "Seventy-seven foxes"; wchar_t wide_phrase[sizeof(narrow_phrase)]; std::wcout << L"The first wide character is: "; wchar_t wc = std::use_facet<std::ctype<wchar_t>>(loc).widen(*narrow_phrase); std::wcout << wc << std::endl; std::wcout << L"The wide-character phrase is: "; std::use_facet<std::ctype<wchar_t>>(loc).widen(narrow_phrase, narrow_phrase + sizeof(narrow_phrase), wide_phrase); std::wcout << wide_phrase << std::endl; return 0; } |
std版日期字符串解析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <iostream> #include <sstream> #include <locale> #include <iomanip> int main() { std::tm t = {}; std::istringstream ss("2011-Februar-18 23:12:34"); //ss.imbue(std::locale("de_DE.utf-8")); try { ss.imbue(std::locale("de-DE")); } catch (std::exception e) { std::cout << e.what() << std::endl; } ss >> std::get_time(&t, "%Y-%b-%d %H:%M:%S"); if (ss.fail()) { std::cout << "Parse failed\n"; } else { std::cout << std::put_time(&t, "%c") << '\n'; } return 0; } |
refer to:
https://en.cppreference.com/w/cpp/locale/locale/name
https://social.msdn.microsoft.com/Forums/en-US/0fb287af-bb58-4c60-a3da-14fe84c16948/stdlocaleglobalstdlocalequotzhcnquot-gets-quotbad-locale-namequot?forum=vcgeneral
https://docs.microsoft.com/en-us/cpp/c-runtime-library/locale-names-languages-and-country-region-strings?redirectedfrom=MSDN&view=msvc-160
Windows驱动从设备名获取dos盘符路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | NTSTATUS querySymbolicLink(PUNICODE_STRING symbolicLinkName, PUNICODE_STRING linkTarget) { OBJECT_ATTRIBUTES oa; NTSTATUS status; HANDLE handle; InitializeObjectAttributes(&oa, symbolicLinkName, OBJ_CASE_INSENSITIVE, 0, 0); status = ZwOpenSymbolicLinkObject(&handle, GENERIC_READ, &oa); if (!NT_SUCCESS(status)) return status; linkTarget->MaximumLength = 200 * sizeof(WCHAR); linkTarget->Length = 0; linkTarget->Buffer = ExAllocatePool(PagedPool, linkTarget->MaximumLength); if (!linkTarget->Buffer) { ZwClose(handle); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(linkTarget->Buffer, linkTarget->MaximumLength); status = ZwQuerySymbolicLinkObject(handle, linkTarget, NULL); ZwClose(handle); if (!NT_SUCCESS(status)) { ExFreePool(linkTarget->Buffer); } return status; } WCHAR *rtlVolumeDeviceToDosName(WCHAR *deviceName) { NTSTATUS status; UNICODE_STRING driveLetterName; WCHAR driveLetterNameBuf[128]; WCHAR c; WCHAR driLetter[3]; UNICODE_STRING linkTarget; for (c = L'A'; c <= L'Z'; c++) { RtlInitEmptyUnicodeString(&driveLetterName, driveLetterNameBuf, sizeof(driveLetterNameBuf)); RtlAppendUnicodeToString(&driveLetterName, L"\\??\\"); driLetter[0] = c; driLetter[1] = L':'; driLetter[2] = 0; RtlAppendUnicodeToString(&driveLetterName, driLetter); status = querySymbolicLink(&driveLetterName, &linkTarget); if (!NT_SUCCESS(status)) continue; if (_wcsnicmp(linkTarget.Buffer, deviceName, linkTarget.Length) == 0) { deviceName += linkTarget.Length - 2; deviceName[0] = c; deviceName[1] = L":"; ExFreePool(linkTarget.Buffer); break; } ExFreePool(linkTarget.Buffer); } return deviceName; } WCHAR *getDosPath(WCHAR *path) { WCHAR device[] = L"\\Device\\"; if (strIsStartWith(path, device)) { path = rtlVolumeDeviceToDosName(path); } return path; } |
获取HANDLE对应的文件路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #include <Windows.h> #include <psapi.h> #include <wchar.h> WCHAR *getFilePathByHandle(HANDLE hFile, WCHAR* filePath, int filePathLen) { DWORD dwFileSizeHi = 0; DWORD dwFileSizeLo = GetFileSize(hFile, &dwFileSizeHi); HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileSizeLo, NULL); filePath[0] = 0; if (NULL != hFileMap) { void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1); if (NULL != pMem) { if (0 == GetMappedFileNameW(GetCurrentProcess(), pMem, filePath, filePathLen)) { // GetLastError } UnmapViewOfFile(pMem); } CloseHandle(hFileMap); } return filePath; } wchar_t toLower(wchar_t ch) { if ('A' <= ch && ch <= 'Z') ch = ch - 'A' + 'a'; return ch; } int isNoCaseBeginWith(wchar_t* l, wchar_t* r) { if (*l == 0 && *r == 0) return 1; if (*l == 0 || *r == 0) return 0; for (; 0 != *l && 0 != *r; l++, r++) { if (toLower(*l) != toLower(*r)) return 0; } return 1; } WCHAR* getDosFilePath(WCHAR *dosPath, int len, WCHAR* kernelPath) { wchar_t path[3] = L"C:"; wchar_t szBuf[MAX_PATH] = { 0 }; for (wchar_t ch = L'A'; ch <= L'Z'; ch++) { path[0] = ch; QueryDosDevice(path, szBuf, MAX_PATH); if (isNoCaseBeginWith(kernelPath, szBuf)) { swprintf_s(dosPath, len, L"%s%s", path, kernelPath + wcslen(szBuf)); return dosPath; } } dosPath[0] = 0; return dosPath; } int main() { HANDLE hFile = CreateFileW(L"d:\\test.txt", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0x00, NULL); if (INVALID_HANDLE_VALUE == hFile) { return 0; } WCHAR path[1024]; getFilePathByHandle(hFile, path, 1024); WCHAR dosPath[1024]; getDosFilePath(dosPath, 1024, path); CloseHandle(hFile); return 0; } |
自定义printf输出格式
glibc版,代码可参考
1 2 3 | //libstrongswan/utils/printf_hook/printf_hook_glibc.c
register_printf_specifier
register_printf_function |
要注意的是,由于gcc在编译时不认识自定义格式,默认会提示warning。
禁止此提示的方法是在gcc命令参数中加入
1 | -Wno-format |
vstr from http://www.and.org/vstr/
代码可参考
1 2 | //libstrongswan/utils/printf_hook/printf_hook_vstr.c
vstr_fmt_add |
在win32下,libstrongswan自已写了一个printf,代码在位置在
1 2 | //libstrongswan/utils/printf_hook/printf_hook_builtin.c
builtin_vsnprintf |
msgsnd/msgrcv vs. sendmsg/recvmsg
msgsnd/msgrcv是linux进程间消息队列通信中的api。
sendmsg/recvmsg是socket通信中的api。
这四个函数在win32中都不存在。
refer to:
https://www.cnblogs.com/wuyepeng/p/9748728.html
http://blog.chinaunix.net/uid-20937170-id-4247670.html