Skip to content

Instantly share code, notes, and snippets.

@huandu
Created July 12, 2014 15:13
Show Gist options
  • Save huandu/08eb990a9b85ef3b4edb to your computer and use it in GitHub Desktop.
Save huandu/08eb990a9b85ef3b4edb to your computer and use it in GitHub Desktop.
A macro implementation of `strrchr()`
#include <iostream>
using namespace std;
#define _STRRCHR_IMPL_COMMON(str, ch, offset) (str)[sizeof((str)) - 1 - (offset)] == (ch)? (str) + sizeof((str)) - (offset): sizeof((str)) <= (offset) + 1? (str)
#define _STRRCHR_IMPL_31(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 31): (str))
#define _STRRCHR_IMPL_30(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 30): _STRRCHR_IMPL_31(str, ch))
#define _STRRCHR_IMPL_29(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 29): _STRRCHR_IMPL_30(str, ch))
#define _STRRCHR_IMPL_28(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 28): _STRRCHR_IMPL_29(str, ch))
#define _STRRCHR_IMPL_27(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 27): _STRRCHR_IMPL_28(str, ch))
#define _STRRCHR_IMPL_26(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 26): _STRRCHR_IMPL_27(str, ch))
#define _STRRCHR_IMPL_25(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 25): _STRRCHR_IMPL_26(str, ch))
#define _STRRCHR_IMPL_24(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 24): _STRRCHR_IMPL_25(str, ch))
#define _STRRCHR_IMPL_23(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 23): _STRRCHR_IMPL_24(str, ch))
#define _STRRCHR_IMPL_22(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 22): _STRRCHR_IMPL_23(str, ch))
#define _STRRCHR_IMPL_21(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 21): _STRRCHR_IMPL_22(str, ch))
#define _STRRCHR_IMPL_20(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 20): _STRRCHR_IMPL_21(str, ch))
#define _STRRCHR_IMPL_19(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 19): _STRRCHR_IMPL_20(str, ch))
#define _STRRCHR_IMPL_18(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 18): _STRRCHR_IMPL_19(str, ch))
#define _STRRCHR_IMPL_17(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 17): _STRRCHR_IMPL_18(str, ch))
#define _STRRCHR_IMPL_16(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 16): _STRRCHR_IMPL_17(str, ch))
#define _STRRCHR_IMPL_15(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 15): _STRRCHR_IMPL_16(str, ch))
#define _STRRCHR_IMPL_14(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 14): _STRRCHR_IMPL_15(str, ch))
#define _STRRCHR_IMPL_13(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 13): _STRRCHR_IMPL_14(str, ch))
#define _STRRCHR_IMPL_12(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 12): _STRRCHR_IMPL_13(str, ch))
#define _STRRCHR_IMPL_11(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 11): _STRRCHR_IMPL_12(str, ch))
#define _STRRCHR_IMPL_10(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 10): _STRRCHR_IMPL_11(str, ch))
#define _STRRCHR_IMPL_9(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 9): _STRRCHR_IMPL_10(str, ch))
#define _STRRCHR_IMPL_8(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 8): _STRRCHR_IMPL_9(str, ch))
#define _STRRCHR_IMPL_7(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 7): _STRRCHR_IMPL_8(str, ch))
#define _STRRCHR_IMPL_6(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 6): _STRRCHR_IMPL_7(str, ch))
#define _STRRCHR_IMPL_5(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 5): _STRRCHR_IMPL_6(str, ch))
#define _STRRCHR_IMPL_4(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 4): _STRRCHR_IMPL_5(str, ch))
#define _STRRCHR_IMPL_3(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 3): _STRRCHR_IMPL_4(str, ch))
#define _STRRCHR_IMPL_2(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 2): _STRRCHR_IMPL_3(str, ch))
#define _STRRCHR_IMPL_1(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 1): _STRRCHR_IMPL_2(str, ch))
#define _STRRCHR_IMPL_0(str, ch) (_STRRCHR_IMPL_COMMON(str, ch, 0): _STRRCHR_IMPL_1(str, ch))
// a macro version of strrchr().
// it has several limitations:
// - str must be a literal string, e.g. "a string".
// - if ch cannot be found in last 32 characters, it will return the whole string.
// this limit can be increased by adding more _STRRCHR_IMPL_* macros.
#define _STRRCHR(str, ch) (sizeof((str)) <= 1? (str): _STRRCHR_IMPL_0(str, ch))
#define __FILENAME__ _STRRCHR(__FILE__, '/')
int main() {
cout << "full file path: \t" << __FILE__ << endl;
cout << "short filename: \t" << __FILENAME__ << endl;
cout << endl;
cout << "case 1: \n expected: \tefgh.c\n actual: \t" << _STRRCHR("0123/2345/4567/6789/8901/0123/2345/4567/6789/abcd/cdef/efgh.c", '/') << endl;
cout << "case 2: \n expected: \tabcdcdefefgh.c\n actual: \t" << _STRRCHR("abcdcdefefgh.c", '/') << endl;
cout << "case 3: \n expected: \tabcd/cdef/0123456789012345678901234567890.c\n actual: \t" << _STRRCHR("abcd/cdef/0123456789012345678901234567890.c", '/') << endl;
return 0;
}
@swpustc
Copy link

swpustc commented Mar 14, 2017

handle wchar_t[]

#define _STRRCHR_IMPL_COMMON(str, ch, offset)   (str)[sizeof((str)) / sizeof((str)[0]) - 1 - (offset)] == (ch) ?    \
                                             ((str) + sizeof((str)) / sizeof((str)[0])     - (offset)) :            \
                                                      sizeof((str)) / sizeof((str)[0])    <= (offset) + 1 ? (str)
...
#define _STRRCHR(str, ch) (sizeof((str)) <= sizeof((str)[0]) ? (str) : _STRRCHR_IMPL_0(str, ch))
#define __FILENAME__  _STRRCHR(__FILE__, '/')
#define __FILENAMEW__ _STRRCHR(__FILEW__, L'/')

fixed sizeof

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment