📄 handy.h
字号:
/* In EBCDIC we do not do locales: therefore() isupper() is fine. */# define isUPPER(c) isupper(c)# define isLOWER(c) islower(c)# define isALNUMC(c) isalnum(c)# define isASCII(c) isascii(c)# define isCNTRL(c) iscntrl(c)# define isGRAPH(c) isgraph(c)# define isPRINT(c) isprint(c)# define isPUNCT(c) ispunct(c)# define isXDIGIT(c) isxdigit(c)# define toUPPER(c) toupper(c)# define toLOWER(c) tolower(c)#else# define isUPPER(c) ((c) >= 'A' && (c) <= 'Z')# define isLOWER(c) ((c) >= 'a' && (c) <= 'z')# define isALNUMC(c) (isALPHA(c) || isDIGIT(c))# define isASCII(c) ((c) <= 127)# define isCNTRL(c) ((c) < ' ' || (c) == 127)# define isGRAPH(c) (isALNUM(c) || isPUNCT(c))# define isPRINT(c) (((c) >= 32 && (c) < 127))# define isPUNCT(c) (((c) >= 33 && (c) <= 47) || ((c) >= 58 && (c) <= 64) || ((c) >= 91 && (c) <= 96) || ((c) >= 123 && (c) <= 126))# define isXDIGIT(c) (isDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))# define toUPPER(c) (isLOWER(c) ? (c) - ('a' - 'A') : (c))# define toLOWER(c) (isUPPER(c) ? (c) + ('a' - 'A') : (c))#endif#ifdef USE_NEXT_CTYPE# define isALNUM_LC(c) \ (NXIsAlNum((unsigned int)(c)) || (char)(c) == '_')# define isIDFIRST_LC(c) \ (NXIsAlpha((unsigned int)(c)) || (char)(c) == '_')# define isALPHA_LC(c) NXIsAlpha((unsigned int)(c))# define isSPACE_LC(c) NXIsSpace((unsigned int)(c))# define isDIGIT_LC(c) NXIsDigit((unsigned int)(c))# define isUPPER_LC(c) NXIsUpper((unsigned int)(c))# define isLOWER_LC(c) NXIsLower((unsigned int)(c))# define isALNUMC_LC(c) NXIsAlNum((unsigned int)(c))# define isCNTRL_LC(c) NXIsCntrl((unsigned int)(c))# define isGRAPH_LC(c) NXIsGraph((unsigned int)(c))# define isPRINT_LC(c) NXIsPrint((unsigned int)(c))# define isPUNCT_LC(c) NXIsPunct((unsigned int)(c))# define toUPPER_LC(c) NXToUpper((unsigned int)(c))# define toLOWER_LC(c) NXToLower((unsigned int)(c))#else /* !USE_NEXT_CTYPE */# if defined(CTYPE256) || (!defined(isascii) && !defined(HAS_ISASCII))# define isALNUM_LC(c) (isalnum((unsigned char)(c)) || (char)(c) == '_')# define isIDFIRST_LC(c) (isalpha((unsigned char)(c)) || (char)(c) == '_')# define isALPHA_LC(c) isalpha((unsigned char)(c))# define isSPACE_LC(c) isspace((unsigned char)(c))# define isDIGIT_LC(c) isdigit((unsigned char)(c))# define isUPPER_LC(c) isupper((unsigned char)(c))# define isLOWER_LC(c) islower((unsigned char)(c))# define isALNUMC_LC(c) isalnum((unsigned char)(c))# define isCNTRL_LC(c) iscntrl((unsigned char)(c))# define isGRAPH_LC(c) isgraph((unsigned char)(c))# define isPRINT_LC(c) isprint((unsigned char)(c))# define isPUNCT_LC(c) ispunct((unsigned char)(c))# define toUPPER_LC(c) toupper((unsigned char)(c))# define toLOWER_LC(c) tolower((unsigned char)(c))# else# define isALNUM_LC(c) (isascii(c) && (isalnum(c) || (c) == '_'))# define isIDFIRST_LC(c) (isascii(c) && (isalpha(c) || (c) == '_'))# define isALPHA_LC(c) (isascii(c) && isalpha(c))# define isSPACE_LC(c) (isascii(c) && isspace(c))# define isDIGIT_LC(c) (isascii(c) && isdigit(c))# define isUPPER_LC(c) (isascii(c) && isupper(c))# define isLOWER_LC(c) (isascii(c) && islower(c))# define isALNUMC_LC(c) (isascii(c) && isalnum(c))# define isCNTRL_LC(c) (isascii(c) && iscntrl(c))# define isGRAPH_LC(c) (isascii(c) && isgraph(c))# define isPRINT_LC(c) (isascii(c) && isprint(c))# define isPUNCT_LC(c) (isascii(c) && ispunct(c))# define toUPPER_LC(c) toupper(c)# define toLOWER_LC(c) tolower(c)# endif#endif /* USE_NEXT_CTYPE */#define isPSXSPC_LC(c) (isSPACE_LC(c) || (c) == '\v')#define isBLANK_LC(c) isBLANK(c) /* could be wrong */#define isALNUM_uni(c) is_uni_alnum(c)#define isIDFIRST_uni(c) is_uni_idfirst(c)#define isALPHA_uni(c) is_uni_alpha(c)#define isSPACE_uni(c) is_uni_space(c)#define isDIGIT_uni(c) is_uni_digit(c)#define isUPPER_uni(c) is_uni_upper(c)#define isLOWER_uni(c) is_uni_lower(c)#define isALNUMC_uni(c) is_uni_alnumc(c)#define isASCII_uni(c) is_uni_ascii(c)#define isCNTRL_uni(c) is_uni_cntrl(c)#define isGRAPH_uni(c) is_uni_graph(c)#define isPRINT_uni(c) is_uni_print(c)#define isPUNCT_uni(c) is_uni_punct(c)#define isXDIGIT_uni(c) is_uni_xdigit(c)#define toUPPER_uni(c,s,l) to_uni_upper(c,s,l)#define toTITLE_uni(c,s,l) to_uni_title(c,s,l)#define toLOWER_uni(c,s,l) to_uni_lower(c,s,l)#define toFOLD_uni(c,s,l) to_uni_fold(c,s,l)#define isPSXSPC_uni(c) (isSPACE_uni(c) ||(c) == '\f')#define isBLANK_uni(c) isBLANK(c) /* could be wrong */#define isALNUM_LC_uvchr(c) (c < 256 ? isALNUM_LC(c) : is_uni_alnum_lc(c))#define isIDFIRST_LC_uvchr(c) (c < 256 ? isIDFIRST_LC(c) : is_uni_idfirst_lc(c))#define isALPHA_LC_uvchr(c) (c < 256 ? isALPHA_LC(c) : is_uni_alpha_lc(c))#define isSPACE_LC_uvchr(c) (c < 256 ? isSPACE_LC(c) : is_uni_space_lc(c))#define isDIGIT_LC_uvchr(c) (c < 256 ? isDIGIT_LC(c) : is_uni_digit_lc(c))#define isUPPER_LC_uvchr(c) (c < 256 ? isUPPER_LC(c) : is_uni_upper_lc(c))#define isLOWER_LC_uvchr(c) (c < 256 ? isLOWER_LC(c) : is_uni_lower_lc(c))#define isALNUMC_LC_uvchr(c) (c < 256 ? isALNUMC_LC(c) : is_uni_alnumc_lc(c))#define isCNTRL_LC_uvchr(c) (c < 256 ? isCNTRL_LC(c) : is_uni_cntrl_lc(c))#define isGRAPH_LC_uvchr(c) (c < 256 ? isGRAPH_LC(c) : is_uni_graph_lc(c))#define isPRINT_LC_uvchr(c) (c < 256 ? isPRINT_LC(c) : is_uni_print_lc(c))#define isPUNCT_LC_uvchr(c) (c < 256 ? isPUNCT_LC(c) : is_uni_punct_lc(c))#define isPSXSPC_LC_uni(c) (isSPACE_LC_uni(c) ||(c) == '\f')#define isBLANK_LC_uni(c) isBLANK(c) /* could be wrong */#define isALNUM_utf8(p) is_utf8_alnum(p)/* The ID_Start of Unicode is quite limiting: it assumes a L-class * character (meaning that you cannot have, say, a CJK character). * Instead, let's allow ID_Continue but not digits. */#define isIDFIRST_utf8(p) (is_utf8_idcont(p) && !is_utf8_digit(p))#define isALPHA_utf8(p) is_utf8_alpha(p)#define isSPACE_utf8(p) is_utf8_space(p)#define isDIGIT_utf8(p) is_utf8_digit(p)#define isUPPER_utf8(p) is_utf8_upper(p)#define isLOWER_utf8(p) is_utf8_lower(p)#define isALNUMC_utf8(p) is_utf8_alnumc(p)#define isASCII_utf8(p) is_utf8_ascii(p)#define isCNTRL_utf8(p) is_utf8_cntrl(p)#define isGRAPH_utf8(p) is_utf8_graph(p)#define isPRINT_utf8(p) is_utf8_print(p)#define isPUNCT_utf8(p) is_utf8_punct(p)#define isXDIGIT_utf8(p) is_utf8_xdigit(p)#define toUPPER_utf8(p,s,l) to_utf8_upper(p,s,l)#define toTITLE_utf8(p,s,l) to_utf8_title(p,s,l)#define toLOWER_utf8(p,s,l) to_utf8_lower(p,s,l)#define isPSXSPC_utf8(c) (isSPACE_utf8(c) ||(c) == '\f')#define isBLANK_utf8(c) isBLANK(c) /* could be wrong */#define isALNUM_LC_utf8(p) isALNUM_LC_uvchr(utf8_to_uvchr(p, 0))#define isIDFIRST_LC_utf8(p) isIDFIRST_LC_uvchr(utf8_to_uvchr(p, 0))#define isALPHA_LC_utf8(p) isALPHA_LC_uvchr(utf8_to_uvchr(p, 0))#define isSPACE_LC_utf8(p) isSPACE_LC_uvchr(utf8_to_uvchr(p, 0))#define isDIGIT_LC_utf8(p) isDIGIT_LC_uvchr(utf8_to_uvchr(p, 0))#define isUPPER_LC_utf8(p) isUPPER_LC_uvchr(utf8_to_uvchr(p, 0))#define isLOWER_LC_utf8(p) isLOWER_LC_uvchr(utf8_to_uvchr(p, 0))#define isALNUMC_LC_utf8(p) isALNUMC_LC_uvchr(utf8_to_uvchr(p, 0))#define isCNTRL_LC_utf8(p) isCNTRL_LC_uvchr(utf8_to_uvchr(p, 0))#define isGRAPH_LC_utf8(p) isGRAPH_LC_uvchr(utf8_to_uvchr(p, 0))#define isPRINT_LC_utf8(p) isPRINT_LC_uvchr(utf8_to_uvchr(p, 0))#define isPUNCT_LC_utf8(p) isPUNCT_LC_uvchr(utf8_to_uvchr(p, 0))#define isPSXSPC_LC_utf8(c) (isSPACE_LC_utf8(c) ||(c) == '\f')#define isBLANK_LC_utf8(c) isBLANK(c) /* could be wrong */#ifdef EBCDIC# ifdef PERL_IMPLICIT_CONTEXT# define toCTRL(c) Perl_ebcdic_control(aTHX_ c)# else# define toCTRL Perl_ebcdic_control# endif#else /* This conversion works both ways, strangely enough. */# define toCTRL(c) (toUPPER(c) ^ 64)#endif/* Line numbers are unsigned, 32 bits. */typedef U32 line_t;#define NOLINE ((line_t) 4294967295UL)/*=head1 Memory Management=for apidoc Am|void|Newx|void* ptr|int nitems|typeThe XSUB-writer's interface to the C C<malloc> function.In 5.9.3, Newx() and friends replace the older New() API, and dropsthe first parameter, I<x>, a debug aid which allowed callers to identifythemselves. This aid has been superseded by a new build option,PERL_MEM_LOG (see L<perlhack/PERL_MEM_LOG>). The older API is stillthere for use in XS modules supporting older perls.=for apidoc Am|void|Newxc|void* ptr|int nitems|type|castThe XSUB-writer's interface to the C C<malloc> function, withcast. See also C<Newx>.=for apidoc Am|void|Newxz|void* ptr|int nitems|typeThe XSUB-writer's interface to the C C<malloc> function. The allocatedmemory is zeroed with C<memzero>. See also C<Newx>.=for apidoc Am|void|Renew|void* ptr|int nitems|typeThe XSUB-writer's interface to the C C<realloc> function.=for apidoc Am|void|Renewc|void* ptr|int nitems|type|castThe XSUB-writer's interface to the C C<realloc> function, withcast.=for apidoc Am|void|Safefree|void* ptrThe XSUB-writer's interface to the C C<free> function.=for apidoc Am|void|Move|void* src|void* dest|int nitems|typeThe XSUB-writer's interface to the C C<memmove> function. The C<src> is thesource, C<dest> is the destination, C<nitems> is the number of items, and C<type> isthe type. Can do overlapping moves. See also C<Copy>.=for apidoc Am|void *|MoveD|void* src|void* dest|int nitems|typeLike C<Move> but returns dest. Useful for encouraging compilers to tail-calloptimise.=for apidoc Am|void|Copy|void* src|void* dest|int nitems|typeThe XSUB-writer's interface to the C C<memcpy> function. The C<src> is thesource, C<dest> is the destination, C<nitems> is the number of items, and C<type> isthe type. May fail on overlapping copies. See also C<Move>.=for apidoc Am|void *|CopyD|void* src|void* dest|int nitems|typeLike C<Copy> but returns dest. Useful for encouraging compilers to tail-calloptimise.=for apidoc Am|void|Zero|void* dest|int nitems|typeThe XSUB-writer's interface to the C C<memzero> function. The C<dest> is thedestination, C<nitems> is the number of items, and C<type> is the type.=for apidoc Am|void *|ZeroD|void* dest|int nitems|typeLike C<Zero> but returns dest. Useful for encouraging compilers to tail-calloptimise.=for apidoc Am|void|StructCopy|type src|type dest|typeThis is an architecture-independent macro to copy one structure to another.=for apidoc Am|void|PoisonWith|void* dest|int nitems|type|U8 byteFill up memory with a byte pattern (a byte repeated over and overagain) that hopefully catches attempts to access uninitialized memory.=for apidoc Am|void|PoisonNew|void* dest|int nitems|typePoisonWith(0xAB) for catching access to allocated but uninitialized memory.=for apidoc Am|void|PoisonFree|void* dest|int nitems|typePoisonWith(0xEF) for catching access to freed memory.=for apidoc Am|void|Poison|void* dest|int nitems|typePoisonWith(0xEF) for catching access to freed memory.=cut *//* Maintained for backwards-compatibility only. Use newSV() instead. */#ifndef PERL_CORE#define NEWSV(x,len) newSV(len)#endif#define MEM_SIZE_MAX ((MEM_SIZE)~0)/* The +0.0 in MEM_WRAP_CHECK_ is an attempt to foil * overly eager compilers that will bleat about e.g. * (U16)n > (size_t)~0/sizeof(U16) always being false. */#ifdef PERL_MALLOC_WRAP#define MEM_WRAP_CHECK(n,t) MEM_WRAP_CHECK_1(n,t,PL_memory_wrap)#define MEM_WRAP_CHECK_1(n,t,a) \ (void)(sizeof(t) > 1 && ((MEM_SIZE)(n)+0.0) > MEM_SIZE_MAX/sizeof(t) && (Perl_croak_nocontext(a),0))#define MEM_WRAP_CHECK_(n,t) MEM_WRAP_CHECK(n,t),#define PERL_STRLEN_ROUNDUP(n) ((void)(((n) > MEM_SIZE_MAX - 2 * PERL_STRLEN_ROUNDUP_QUANTUM) ? (Perl_croak_nocontext(PL_memory_wrap),0):0),((n-1+PERL_STRLEN_ROUNDUP_QUANTUM)&~((MEM_SIZE)PERL_STRLEN_ROUNDUP_QUANTUM-1)))#else#define MEM_WRAP_CHECK(n,t)#define MEM_WRAP_CHECK_1(n,t,a)#define MEM_WRAP_CHECK_2(n,t,a,b)#define MEM_WRAP_CHECK_(n,t)#define PERL_STRLEN_ROUNDUP(n) (((n-1+PERL_STRLEN_ROUNDUP_QUANTUM)&~((MEM_SIZE)PERL_STRLEN_ROUNDUP_QUANTUM-1)))#endif#ifdef PERL_MEM_LOG/* * If PERL_MEM_LOG is defined, all Newx()s, Renew()s, and Safefree()s * go through functions, which are handy for debugging breakpoints, but * which more importantly get the immediate calling environment (file and * line number, and C function name if available) passed in. This info can * then be used for logging the calls, for which one gets a sample * implementation if PERL_MEM_LOG_STDERR is defined. * * Known problems: * - all memory allocs do not get logged, only those * that go through Newx() and derivatives (while all * Safefrees do get logged) * - __FILE__ and __LINE__ do not work everywhere * - __func__ or __FUNCTION__ even less so * - I think more goes on after the perlio frees but * the thing is that STDERR gets closed (as do all * the file descriptors) * - no deeper calling stack than the caller of the Newx() * or the kind, but do I look like a C reflection/introspection * utility to you? * - the function prototypes for the logging functions * probably should maybe be somewhere else than handy.h * - one could consider inlining (macrofying) the logging * for speed, but I am too lazy * - one could imagine recording the allocations in a hash, * (keyed by the allocation address?), and maintain that * through reallocs and frees, but how to do that without * any News() happening...? */Malloc_t Perl_mem_log_alloc(const UV n, const UV typesize, const char *typename, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname);Malloc_t Perl_mem_log_realloc(const UV n, const UV typesize, const char *typename, Malloc_t oldalloc, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname);Malloc_t Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber, const char *funcname);#endif#ifdef PERL_MEM_LOG#define MEM_LOG_ALLOC(n,t,a) Perl_mem_log_alloc(n,sizeof(t),STRINGIFY(t),a,__FILE__,__LINE__,FUNCTION__)#define MEM_LOG_REALLOC(n,t,v,a) Perl_mem_log_realloc(n,sizeof(t),STRINGIFY(t),v,a,__FILE__,__LINE__,FUNCTION__)#define MEM_LOG_FREE(a) Perl_mem_log_free(a,__FILE__,__LINE__,FUNCTION__)#endif#ifndef MEM_LOG_ALLOC#define MEM_LOG_ALLOC(n,t,a) (a)#endif#ifndef MEM_LOG_REALLOC#define MEM_LOG_REALLOC(n,t,v,a) (a)#endif#ifndef MEM_LOG_FREE#define MEM_LOG_FREE(a) (a)#endif#define Newx(v,n,t) (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_ALLOC(n,t,(t*)safemalloc((MEM_SIZE)((n)*sizeof(t))))))#define Newxc(v,n,t,c) (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_ALLOC(n,t,(c*)safemalloc((MEM_SIZE)((n)*sizeof(t))))))#define Newxz(v,n,t) (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_ALLOC(n,t,(t*)safecalloc((n),sizeof(t)))))#ifndef PERL_CORE/* pre 5.9.x compatibility */#define New(x,v,n,t) Newx(v,n,t)#define Newc(x,v,n,t,c) Newxc(v,n,t,c)#define Newz(x,v,n,t) Newxz(v,n,t)#endif#define Renew(v,n,t) \ (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_REALLOC(n,t,v,(t*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))))#define Renewc(v,n,t,c) \ (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_REALLOC(n,t,v,(c*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))))#ifdef PERL_POISON#define Safefree(d) \ ((d) ? (void)(safefree(MEM_LOG_FREE((Malloc_t)(d))), Poison(&(d), 1, Malloc_t)) : (void) 0)#else#define Safefree(d) safefree(MEM_LOG_FREE((Malloc_t)(d)))#endif#define Move(s,d,n,t) (MEM_WRAP_CHECK_(n,t) (void)memmove((char*)(d),(const char*)(s), (n) * sizeof(t)))#define Copy(s,d,n,t) (MEM_WRAP_CHECK_(n,t) (void)memcpy((char*)(d),(const char*)(s), (n) * sizeof(t)))#define Zero(d,n,t) (MEM_WRAP_CHECK_(n,t) (void)memzero((char*)(d), (n) * sizeof(t)))#define MoveD(s,d,n,t) (MEM_WRAP_CHECK_(n,t) memmove((char*)(d),(const char*)(s), (n) * sizeof(t)))#define CopyD(s,d,n,t) (MEM_WRAP_CHECK_(n,t) memcpy((char*)(d),(const char*)(s), (n) * sizeof(t)))#ifdef HAS_MEMSET#define ZeroD(d,n,t) (MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)))#else/* Using bzero(), which returns void. */#define ZeroD(d,n,t) (MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)),d)#endif#define PoisonWith(d,n,t,b) (MEM_WRAP_CHECK_(n,t) (void)memset((char*)(d), (U8)(b), (n) * sizeof(t)))#define PoisonNew(d,n,t) PoisonWith(d,n,t,0xAB)#define PoisonFree(d,n,t) PoisonWith(d,n,t,0xEF)#define Poison(d,n,t) PoisonFree(d,n,t)#ifdef USE_STRUCT_COPY#define StructCopy(s,d,t) (*((t*)(d)) = *((t*)(s)))#else#define StructCopy(s,d,t) Copy(s,d,1,t)#endif#define C_ARRAY_LENGTH(a) (sizeof(a)/sizeof((a)[0]))#ifdef NEED_VA_COPY# ifdef va_copy# define Perl_va_copy(s, d) va_copy(d, s)# else# if defined(__va_copy)# define Perl_va_copy(s, d) __va_copy(d, s)# else# define Perl_va_copy(s, d) Copy(s, d, 1, va_list)# endif# endif#endif/* convenience debug macros */#ifdef USE_ITHREADS#define pTHX_FORMAT "Perl interpreter: 0x%p"#define pTHX__FORMAT ", Perl interpreter: 0x%p"#define pTHX_VALUE_ (void *)my_perl,#define pTHX_VALUE (void *)my_perl#define pTHX__VALUE_ ,(void *)my_perl,#define pTHX__VALUE ,(void *)my_perl#else#define pTHX_FORMAT#define pTHX__FORMAT#define pTHX_VALUE_#define pTHX_VALUE#define pTHX__VALUE_#define pTHX__VALUE#endif /* USE_ITHREADS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -