Ignore:
Timestamp:
Jul 3, 2006 10:08:47 PM (17 years ago)
Author:
bennylp
Message:

Various performance improvements in PJSIP: (1) optimizing for common case to minimize stricmp() calls (header names, method, URI schemes), (2) added functionality in scanner to parse and unescape in-place, (3) etc..

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjsip/src/pjsip/sip_parser.c

    r576 r583  
    116116            pjsip_PARAM_CHAR_SPEC,      /* For scanning pname (or pvalue when 
    117117                                         * it's not quoted.) */ 
     118            pjsip_PARAM_CHAR_SPEC_ESC,  /* The variant without escaped char */ 
    118119            pjsip_HDR_CHAR_SPEC,        /* Chars in hname or hvalue */ 
     120            pjsip_HDR_CHAR_SPEC_ESC,    /* Variant without escaped char */ 
    119121            pjsip_PROBE_USER_HOST_SPEC, /* Hostname characters. */ 
    120122            pjsip_PASSWD_SPEC,          /* Password. */ 
     123            pjsip_PASSWD_SPEC_ESC,      /* Variant without escaped char */ 
    121124            pjsip_USER_SPEC,            /* User */ 
     125            pjsip_USER_SPEC_ESC,        /* Variant without escaped char */ 
    122126            pjsip_NOT_COMMA_OR_NEWLINE, /* Array separator. */ 
    123127            pjsip_NOT_NEWLINE,          /* For eating up header.*/ 
     
    202206 
    203207/* Case insensitive comparison */ 
    204 #define parser_stricmp(s1, s2)  (pj_stricmp_alnum(&s1, &s2)) 
     208#define parser_stricmp(s1, s2)  (s1.slen!=s2.slen || pj_stricmp_alnum(&s1, &s2)) 
     209 
     210 
     211/* Get a token and unescape */ 
     212PJ_INLINE(void) parser_get_and_unescape(pj_scanner *scanner, pj_pool_t *pool, 
     213                                        const pj_cis_t *spec,  
     214                                        const pj_cis_t *unesc_spec, 
     215                                        pj_str_t *token) 
     216{ 
     217#if defined(PJSIP_UNESCAPE_IN_PLACE) && PJSIP_UNESCAPE_IN_PLACE!=0 
     218    PJ_UNUSED_ARG(pool); 
     219    PJ_UNUSED_ARG(spec); 
     220    pj_scan_get_unescape(scanner, unesc_spec, token); 
     221#else 
     222    PJ_UNUSED_ARG(unesc_spec); 
     223    pj_scan_get(scanner, spec, token); 
     224    *token = pj_str_unescape(pool, token); 
     225#endif 
     226} 
     227 
    205228 
    206229 
     
    314337    pj_cis_add_str(&pjsip_PARAM_CHAR_SPEC, PARAM_CHAR); 
    315338 
     339    status = pj_cis_dup(&pjsip_PARAM_CHAR_SPEC_ESC, &pjsip_PARAM_CHAR_SPEC); 
     340    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
     341    pj_cis_del_str(&pjsip_PARAM_CHAR_SPEC_ESC, ESCAPED); 
     342 
    316343    status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC, &pjsip_ALNUM_SPEC); 
    317344    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    318345    pj_cis_add_str(&pjsip_HDR_CHAR_SPEC, HDR_CHAR); 
    319346 
     347    status = pj_cis_dup(&pjsip_HDR_CHAR_SPEC_ESC, &pjsip_HDR_CHAR_SPEC); 
     348    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
     349    pj_cis_del_str(&pjsip_HDR_CHAR_SPEC_ESC, ESCAPED); 
     350 
    320351    status = pj_cis_dup(&pjsip_USER_SPEC, &pjsip_ALNUM_SPEC); 
    321352    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    322353    pj_cis_add_str( &pjsip_USER_SPEC, UNRESERVED ESCAPED USER_UNRESERVED ); 
    323354 
     355    status = pj_cis_dup(&pjsip_USER_SPEC_ESC, &pjsip_USER_SPEC); 
     356    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
     357    pj_cis_del_str( &pjsip_USER_SPEC_ESC, ESCAPED); 
     358 
    324359    status = pj_cis_dup(&pjsip_PASSWD_SPEC, &pjsip_ALNUM_SPEC); 
    325360    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
    326361    pj_cis_add_str( &pjsip_PASSWD_SPEC, UNRESERVED ESCAPED PASS); 
     362 
     363    status = pj_cis_dup(&pjsip_PASSWD_SPEC_ESC, &pjsip_PASSWD_SPEC); 
     364    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status); 
     365    pj_cis_del_str( &pjsip_PASSWD_SPEC, ESCAPED); 
    327366 
    328367    status = pj_cis_init(&cis_buf, &pjsip_PROBE_USER_HOST_SPEC); 
     
    460499 
    461500    /* Equal length and equal hash. compare the strings. */ 
    462     return pj_ansi_strcmp(r1->hname, name); 
     501    return pj_memcmp(r1->hname, name, name_len); 
    463502} 
    464503 
     
    469508    unsigned    pos; 
    470509    handler_rec rec; 
    471     unsigned    i; 
    472510 
    473511    if (handler_count >= PJ_ARRAY_SIZE(handler)) { 
     512        pj_assert(!"Too many handlers!"); 
    474513        return PJ_ETOOMANY; 
    475514    } 
     
    482521        return PJ_ENAMETOOLONG; 
    483522    } 
    484     /* Name is copied in lowercase. */ 
    485     for (i=0; i<rec.hname_len; ++i) { 
    486         rec.hname[i] = (char)pj_tolower(name[i]); 
    487     } 
    488     rec.hname[i] = '\0'; 
    489     /* Hash value is calculated from the lowercase name. */ 
    490     rec.hname_hash = pj_hash_calc(0, rec.hname, PJ_HASH_KEY_STRING); 
     523    /* Copy name. */ 
     524    pj_memcpy(rec.hname, name, rec.hname_len); 
     525    rec.hname[rec.hname_len] = '\0'; 
     526 
     527    /* Calculate hash value. */ 
     528    rec.hname_hash = pj_hash_calc(0, rec.hname, rec.hname_len); 
    491529 
    492530    /* Get the pos to insert the new handler. */ 
     
    523561                                               pjsip_parse_hdr_func *fptr) 
    524562{ 
     563    unsigned i, len; 
     564    char hname_lcase[PJSIP_MAX_HNAME_LEN+1]; 
    525565    pj_status_t status; 
    526566 
     567    /* Check that name is not too long */ 
     568    len = pj_ansi_strlen(hname); 
     569    if (len > PJSIP_MAX_HNAME_LEN) { 
     570        pj_assert(!"Header name is too long!"); 
     571        return PJ_ENAMETOOLONG; 
     572    } 
     573 
     574    /* Register the normal Mixed-Case name */ 
    527575    status = int_register_parser(hname, fptr); 
    528576    if (status != PJ_SUCCESS) { 
    529577        return status; 
    530578    } 
     579 
     580    /* Get the lower-case name */ 
     581    for (i=0; i<len; ++i) { 
     582        hname_lcase[i] = (char)pj_tolower(hname[i]); 
     583    } 
     584    hname_lcase[len] = '\0'; 
     585 
     586    /* Register the lower-case version of the name */ 
     587    status = int_register_parser(hname_lcase, fptr); 
     588    if (status != PJ_SUCCESS) { 
     589        return status; 
     590    } 
     591     
     592 
     593    /* Register the shortname version of the name */ 
    531594    if (hshortname) { 
    532595        status = int_register_parser(hshortname, fptr); 
     
    537600} 
    538601 
     602 
    539603/* Find handler to parse the header name. */ 
    540 static pjsip_parse_hdr_func * find_handler(const pj_str_t *hname) 
     604static pjsip_parse_hdr_func * find_handler_imp(pj_uint32_t  hash,  
     605                                               const pj_str_t *hname) 
    541606{ 
    542607    handler_rec *first; 
    543     char         hname_copy[PJSIP_MAX_HNAME_LEN]; 
    544     pj_uint32_t  hash; 
    545608    int          comp; 
    546609    unsigned     n; 
    547  
    548     if (hname->slen >= PJSIP_MAX_HNAME_LEN) { 
    549         /* Guaranteed not to be able to find handler. */ 
    550         return NULL; 
    551     } 
    552  
    553     /* Calculate hash value while converting the header to lowercase.  
    554      * Don't assume that 'hname' is NULL terminated. 
    555      */ 
    556     hash = pj_hash_calc_tolower(0, hname_copy, hname); 
    557     hname_copy[hname->slen] = '\0'; 
    558610 
    559611    /* Binary search for the handler. */ 
     
    565617        handler_rec *mid = first + half; 
    566618 
    567         comp = compare_handler(mid, hname_copy, hname->slen, hash); 
     619        comp = compare_handler(mid, hname->ptr, hname->slen, hash); 
    568620        if (comp < 0) { 
    569621            first = ++mid; 
     
    580632} 
    581633 
     634 
     635/* Find handler to parse the header name. */ 
     636static pjsip_parse_hdr_func* find_handler(const pj_str_t *hname) 
     637{ 
     638    pj_uint32_t hash; 
     639    char hname_copy[PJSIP_MAX_HNAME_LEN]; 
     640    pj_str_t tmp; 
     641    pjsip_parse_hdr_func *handler; 
     642 
     643    if (hname->slen >= PJSIP_MAX_HNAME_LEN) { 
     644        /* Guaranteed not to be able to find handler. */ 
     645        return NULL; 
     646    } 
     647 
     648    /* First, common case, try to find handler with exact name */ 
     649    hash = pj_hash_calc(0, hname->ptr, hname->slen); 
     650    handler = find_handler_imp(hash, hname); 
     651    if (handler) 
     652        return handler; 
     653 
     654 
     655    /* If not found, try converting the header name to lowercase and 
     656     * search again. 
     657     */ 
     658    hash = pj_hash_calc_tolower(0, hname_copy, hname); 
     659    tmp.ptr = hname_copy; 
     660    tmp.slen = hname->slen; 
     661    return find_handler_imp(hash, &tmp); 
     662} 
     663 
     664 
    582665/* Find URI handler. */ 
    583666static pjsip_parse_uri_func* find_uri_handler(const pj_str_t *scheme) 
     
    585668    unsigned i; 
    586669    for (i=0; i<uri_handler_count; ++i) { 
    587         if (pj_stricmp_alnum(&uri_handler[i].scheme, scheme)==0) 
     670        if (parser_stricmp(uri_handler[i].scheme, (*scheme))==0) 
    588671            return uri_handler[i].parse; 
    589672    } 
     
    9621045{ 
    9631046    /* pname */ 
    964     pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pname); 
    965     *pname = pj_str_unescape(pool, pname); 
     1047    parser_get_and_unescape(scanner, pool, &pjsip_PARAM_CHAR_SPEC, 
     1048                            &pjsip_PARAM_CHAR_SPEC_ESC, pname); 
    9661049 
    9671050    /* init pvalue */ 
     
    9811064                } 
    9821065            } else if(pj_cis_match(&pjsip_PARAM_CHAR_SPEC, *scanner->curptr)) { 
    983                 pj_scan_get(scanner, &pjsip_PARAM_CHAR_SPEC, pvalue); 
    984                 *pvalue = pj_str_unescape(pool, pvalue); 
     1066                parser_get_and_unescape(scanner, pool, &pjsip_PARAM_CHAR_SPEC,  
     1067                                        &pjsip_PARAM_CHAR_SPEC_ESC, pvalue); 
    9851068            } 
    9861069        } 
     
    10081091 
    10091092    /* hname */ 
    1010     pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hname); 
    1011     *hname = pj_str_unescape(pool, hname); 
     1093    parser_get_and_unescape(scanner, pool, &pjsip_HDR_CHAR_SPEC,  
     1094                            &pjsip_HDR_CHAR_SPEC_ESC, hname); 
    10121095 
    10131096    /* Init hvalue */ 
     
    10211104            pj_cis_match(&pjsip_HDR_CHAR_SPEC, *scanner->curptr)) 
    10221105        { 
    1023             pj_scan_get(scanner, &pjsip_HDR_CHAR_SPEC, hvalue); 
    1024             *hvalue = pj_str_unescape(pool, hvalue); 
     1106            parser_get_and_unescape(scanner, pool, &pjsip_HDR_CHAR_SPEC, 
     1107                                    &pjsip_HDR_CHAR_SPEC, hvalue); 
    10251108        } 
    10261109    } 
     
    10641147                                 pj_str_t *user, pj_str_t *pass) 
    10651148{ 
    1066     pj_scan_get( scanner, &pjsip_USER_SPEC, user); 
    1067     *user = pj_str_unescape(pool, user); 
     1149    parser_get_and_unescape(scanner, pool, &pjsip_USER_SPEC,  
     1150                            &pjsip_USER_SPEC_ESC, user); 
    10681151 
    10691152    if ( *scanner->curptr == ':') { 
    10701153        pj_scan_get_char( scanner ); 
    1071         pj_scan_get( scanner, &pjsip_PASSWD_SPEC, pass); 
    1072         *pass = pj_str_unescape(pool, pass); 
     1154        parser_get_and_unescape(scanner, pool, &pjsip_PASSWD_SPEC, 
     1155                                &pjsip_PASSWD_SPEC_ESC, pass); 
    10731156    } else { 
    10741157        pass->ptr = NULL; 
     
    14361519        int_parse_param( scanner, pool, &pname, &pvalue); 
    14371520        if (!parser_stricmp(pname, pjsip_Q_STR) && pvalue.slen) { 
    1438             char *dot_pos = memchr(pvalue.ptr, '.', pvalue.slen); 
     1521            char *dot_pos = pj_memchr(pvalue.ptr, '.', pvalue.slen); 
    14391522            if (!dot_pos) { 
    14401523                hdr->q1000 = pj_strtoul(&pvalue); 
Note: See TracChangeset for help on using the changeset viewer.