青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

無我

讓內心永遠燃燒著偉大的光明的精神之火!
靈活的思考,嚴謹的實現
豪邁的氣魄、頑強的意志和周全的思考

eSNACC對ASN.1內置字符串的編碼和解碼

eSNACC運行時庫直接支持各種各樣的ASN.1字符串定義。這包括PrintableString, BMPString, TeletexString, NumericString, IA5String, UniversalString, UTF8String, VisibleString。其做法也大同小異,所有這些字符串都是在eSNACC的字節串基礎上typedef過來的,例如:

typedef AsnOcts PrintableString; /* [UNIVERSAL 19] IMPLICIT OCTET STRING */

只是根據各自特性的不同而在編碼解碼時有某些判斷,或者加了某些判斷函數等。只有UTF8String相對比較復雜一些。讓我們一起來分析一下吧。  

 

/******************************PrintableString************************************************/

PrintableString也就是可打印字符組成的字符串。因為要求是可以打印的字符,其判斷函數在串中全部為可打印字符的函數時返回0,否則返回-1。

static int chkPrintableString(PrintableString *checkBuf)
{
    unsigned 
int i;
    
char temp;

    
if (checkBuf == NULL)
        
return -1;
    
    
for (i = 0; i < checkBuf->octetLen; i++)
    
{
        temp 
= checkBuf->octs[i];
        
/* Check A-Z */
        
if ((temp < 'A'|| (temp > 'Z'))
        
{
            
/* Check for a-z */
            
if ((temp < 'a'|| (temp > 'z'))
            
{
                
/* Check for 0-9 */
                
if ((temp < '0'|| (temp > '9'))
                
{
                    
switch (temp)
                    
{
                    
case ' ':        /* space */
                    
case '\'':        /* apostrophe */
                    case '(':        /* left parenthesis */
                    
case ')':        /* right parenthesis */
                    
case '+':        /* plus sign */
                    
case ',':        /* comma */
                    
case '-':        /* hyphen */
                    
case '.':        /* full stop (period) */
                    
case '/':        /* solidus */
                    
case ':':        /* colon */
                    
case '=':        /* equal sign */
                    
case '?':        /* question mark */
                        
break;

                    
default:
                        
return -1;
                    }

                }

            }

        }

    }


    
return 0;
}
 /* end of chkPrintableString() */

然后在編碼和解碼時判斷本函數的要求是否滿足,否則報錯。

/******************************************************************************************/

 

/************************************BMPString**********************************************/

BMPString也就是UNICODE_STRING,也就是雙字節字符。所以要求其內部字節串的長度必須是2的倍數,不然編碼和解碼時就會報錯。

AsnLen BEncBMPStringContent(GenBuf *b, BMPString *octs)
{
    
if ((octs->octetLen % 2!= 0)
    
{
        BufSetWriteError (b, TRUE);
    }

    
return BEncAsnOctsContent(b, octs);
}
 /* end of BEncBMPStringContent() */

void BDecBMPStringContent(GenBuf *b, AsnTag tagId, AsnLen len,BMPString *result, AsnLen *bytesDecoded,ENV_TYPE env)
{
    BDecAsnOctsContent(b, tagId, len, result, bytesDecoded, env);
    
if ((result->octetLen % 2!= 0)
    
{
        Asn1Error (
"BDecBMPStringContent: ERROR - Invalid BMPString Format");
        longjmp (env, 
-40);
    }

}

 

/*****************************************************************************************/

 

/******************************TeletexString*************************************************/

TeletexString就是8位字節串,所以與AsnOcts是一樣的,只是標簽不同,這也就體現在編碼和解碼時對標簽的處理不同。 

/******************************************************************************************/

 

/******************************NumericString*************************************************/

NumericString就是要求由數字組成的串,不過可以有空格。判斷函數如下:

static int chkNumericString(NumericString *checkBuf)
{
    unsigned 
int i;
    
    
if (checkBuf == NULL)
        
return -1;

    
for (i = 0; i < checkBuf->octetLen; i++)
    
{
        
if ((checkBuf->octs[i] != ' '&& 
            ((checkBuf
->octs[i] < '0'|| (checkBuf->octs[i] > '9')))
            
return -1;
    }


    
return 0;
}
 /* end of chkNumericString() */

/******************************************************************************************/

 

/******************************IA5String****************************************************/

在微軟的網站上,對IA5的解釋是:The International Alphabet number 5 (IA5) is generally equivalent to the ASCII alphabet, but different versions can include accents or other characters specific to a regional language. eSNACC給的判斷函數是:

static int checkIA5String(IA5String *octs)
{
    unsigned 
int i;

    
if (octs == NULL)
        
return -1;

    
for (i = 0; i < octs->octetLen; i++)
    
{
        
if ((unsigned char)octs->octs[i] > 0x7F)
            
return -1;
    }


    
return 0;
}

/******************************************************************************************/

 

 

/******************************UniversalString************************************************/

UniversalString要求是用4個字節表示字符的串。所以在編碼和解碼時要求字節串的長度為4的整數倍:

AsnLen BEncUniversalStringContent(GenBuf *b, UniversalString *octs)
{
    
if ((octs->octetLen % 4!= 0)
    
{    
        Asn1Error (
"BEncUniversalStringContent: ERROR - Invalid UniversalString Format");
        GenBufSetWriteError (b, TRUE);
    }

    
return BEncAsnOctsContent(b, octs);
}
 /* end of BEncUniversalStringContent() */

void BDecUniversalStringContent(GenBuf *b, AsnTag tagId, AsnLen len,UniversalString *result, AsnLen *bytesDecoded,ENV_TYPE env)
{
    BDecAsnOctsContent (b, tagId, len, result, bytesDecoded, env);
    
if ((result->octetLen % 4!= 0)
    
{
        Asn1Error (
"BDecUniversalStringContent: ERROR - Invalid UniversalString Format");
        longjmp (env, 
-40);
    }

}
 /* end of BDecUniversalStringContent() */

/******************************************************************************************/

  

/******************************VisibleString**************************************************/

VisibleString,具體定義不明確,直接給出eSNACC對串內容的判斷函數吧: 

static int chkVisibleString(VisibleString *checkBuf)
{
    unsigned 
int i;
    
char temp;

    
if (checkBuf == NULL)
        
return -1;
    
    
for (i = 0; i < checkBuf->octetLen; i++)
    
{
        temp 
= checkBuf->octs[i];
        
/* Check A-Z */
        
        
if((unsigned int)temp > 128)
        
{
            
return -1;
        }

    }


    
return 0;
}
 /* end of chkVisibleString() */

/******************************************************************************************/

 

/******************************UTF8String***************************************************/

壓軸好戲在后頭,所以最后讓我們來分析一個最有價值含量的!

UTF-8是UNICODE的一種變長字符編碼又稱萬國碼,由Ken Thompson于1992年創建。現在已經標準化為RFC 3629。UTF-8用1到6個字節編碼UNICODE字符。eSNACC用字節串來表示UTF8String,但是有一個判斷這個字節串是否有效UTF8String的函數,并且還定義了UTF8String和wchar類型相互轉換的函數,或許從這些函數中,我們能學習eSNACC是怎么處理UTF-8編碼的。

我們先看一些定義和utf8的判斷函數:

typedef struct
{
    unsigned 
char mask;
    unsigned 
char value;
    unsigned 
long maxCharValue;
}
 MaskValue;

/* Global Values */
#define MAX_UTF8_OCTS_PER_CHAR        6

const MaskValue gUTF8Masks[MAX_UTF8_OCTS_PER_CHAR] = {
    
0x800x000x0000007F },        /* one-byte encoding   標記為0XXX XXXX*/
    
0xE00xC00x000007FF },        /* two-byte encoding   標記為110X XXXX*/
    
0xF00xE00x0000FFFF },        /* three-byte encoding 標記為1110 XXXX*/
    
0xF80xF00x0001FFFF },        /* four-byte encoding  標記為1111 0XXX*/
    
0xFC0xF80x03FFFFFF },        /* five-byte encoding  標記為1111 10XX*/
    
0xFE0xFC0x07FFFFFF }        /* six-byte encoding   標記為1111 110X*/
}
;

 

static bool IsValidUTF8String(UTF8String* octs)
{
    unsigned 
long i;
    unsigned 
int j;

    
if (octs == NULL)
        
return false;

    i 
= 0;
    
while (i < octs->octetLen)
    
{
        
/* Determine the number of UTF-8 octets that follow the first */
        
for (j = 0; (j < MAX_UTF8_OCTS_PER_CHAR) && 
            ((gUTF8Masks[j].mask 
& octs->octs[i]) != gUTF8Masks[j].value); j++)
            ;

        
/* Return false if the first octet was invalid or if the number of 
        subsequent octets exceeds the UTF8String length 
*/

        
if ((j == MAX_UTF8_OCTS_PER_CHAR) || ((i + j) >= octs->octetLen))
            
return false;

        
/* Skip over first octet */
        i
++;

        
/* Check that each subsequent octet is properly formatted */
        
for (; j > 0; j--)
        
{
            
if ((octs->octs[i++& 0xC0!= 0x80)
                
return false;
        }

    }


    
return true;
}

 

首先通過掩碼來判斷第一個字節,確定當前這個字符是用幾個字節來表示的。可能的是1-6,如果不是就會報錯。如果是一個,那么當前這個字節就是這個字符了,也就是只要字符小于0x7F,就只需要一個字符:這對應了MaskValue中的maxCharValue。其余的情況類似。而函數末尾那個for說明了:utf8的格式為:如果一個字符用了大于1個字節來表示,那么除了第一個用于表長度的字節以外,后面的表值的字節必須是10XX XXXX的樣式。

 

那么一個wchar字符是如何用utf8來表示的呢?我們看看wchar -> utf8的函數:

int CvtWchar2UTF8(wchar_t *inStr, char **utf8Str)
{
    size_t wLen;
    unsigned 
int i, j, x, y;
    size_t wchar_size 
= sizeof(wchar_t);
    wchar_t temp_wchar;

    
/* Check parameters */
    
if ((inStr == NULL) || (utf8Str == NULL))
        
return -1;

    wLen 
= wcslen(inStr);

    
/* Allocate and clear memory for a worst case UTF-8 string */
    
*utf8Str = (char*)calloc(wLen * (wchar_size / 2 * 3+ 1sizeof(char));
    
if (*utf8Str == NULL)
        
return -2;

    
/* Convert each wide character into a UTF-8 char sequence */
    
for (i = 0, x = 0; i < wLen; i++)
    
{
        temp_wchar 
= inStr[i];

        
/* Return an error if the wide character is invalid */
        
if (temp_wchar < 0)
        
{
            free(
*utf8Str);
            
*utf8Str = NULL;
            
return -3;
        }


        
/* Determine the number of characters required to encode this wide
        character 
*/

        
for (j = 0; (j < MAX_UTF8_OCTS_PER_CHAR) &&
            (temp_wchar 
> gUTF8Masks[j].maxCharValue); j++)
            ;

        
/* Return an error if the wide character is invalid */
        
if (j == MAX_UTF8_OCTS_PER_CHAR)
        
{
            free(
*utf8Str);
            
*utf8Str = NULL;
            
return -3;
        }


        
/* Skip over the first UTF-8 octet and encode the remaining octets
        (if any) from right-to-left.  Fill in the least significant six bits
        of each octet with the low-order bits from the wide character value 
*/

        
for (y = j; y > 0; y--)
        
{
            (
*utf8Str)[x + y] = (char)(0x80 | (temp_wchar & 0x3F));
            temp_wchar 
>>= 6;
        }


        
/* Encode the first UTF-8 octet */
        (
*utf8Str)[x] = gUTF8Masks[j].value;
        (
*utf8Str)[x++|= ~gUTF8Masks[j].mask & temp_wchar;

        
/* Update the UTF-8 string index (skipping over the subsequent octets
        already encoded 
*/

        x 
+= j;
    }


    
return 0;
}
 /* end of CvtWchar2UTF8() */

本函數第一次為存儲utf8的串分配足夠多的內存:“如果UNICODE字符由2個字節表示,則編碼成UTF-8很可能需要3個字節,而如果UNICODE字符由4個字節表示,則編碼成UTF-8可能需要6個字節。”但是此處總是用3或者6個字節來存。

然后遍歷每一個wchar字符,獲取存放他所需的字節數,然后反序來設定字節內容。最后設定長度標記字節。對單字節表示的情況,其實這就是原值。

對應的utf8 -> wchar 函數:

int CvtUTF8towchar(char *utf8Str, wchar_t **outStr)
{
    unsigned 
int len, i, j, x;
    size_t wchar_size 
= sizeof(wchar_t);

    
if ((utf8Str == NULL) || (outStr == NULL))
        
return -1;

    len 
= strlen(utf8Str);
    
    
/* Allocate and clear the memory for a worst case result wchar_t string */
    
*outStr = (wchar_t*)calloc(len + 1sizeof(wchar_t));
    
if (*outStr == NULL)
        
return -2;

    
/* Convert the UTF-8 string to a wchar_t string */
    i 
= 0;
    x 
= 0;
    
while (i < len)
    
{
        
/* Determine the number of UTF-8 octets that follow the first */
        
for (j = 0; (j < MAX_UTF8_OCTS_PER_CHAR) && 
            ((gUTF8Masks[j].mask 
& utf8Str[i]) != gUTF8Masks[j].value); j++)
            ;

        
/* Return an error if the first octet was invalid or if the number of
        subsequent octets exceeds the UTF-8 string length 
*/

        
if ((j == MAX_UTF8_OCTS_PER_CHAR) || ((i + j) >= len))
        
{
            free(
*outStr);
            
*outStr = NULL;
            
return -3;
        }


        
/* Return an error if the size of the wchar_t doesn't support the
        size of this UTF-8 character 
*/

        
if ((j > 2&& (wchar_size < 4))
        
{
            free(
*outStr);
            
*outStr = NULL;
            
return -4;
        }


        
/* Copy the bits from the first octet into the wide character */
        (
*outStr)[x] = (char)(~gUTF8Masks[j].mask & utf8Str[i++]);

        
/* Add in the bits from each subsequent octet */
        
for (; j > 0; j--)
        
{
            
/* Return an error if a subsequent octet isn't properly formatted */
            
if ((utf8Str[i] & 0xC0!= 0x80)
            
{
                free(
*outStr);
                
*outStr = NULL;
                
return -3;
            }


            (
*outStr)[x] <<= 6;
            (
*outStr)[x] |= utf8Str[i++& 0x3F;
        }

        x
++;
    }


    
/* Reallocate the wchar string memory to its correct size */
    
if (x < len)
    
{
        
*outStr = (wchar_t*)realloc(*outStr, (x + 1* sizeof(wchar_t));
        
if (*outStr == NULL)
            
return -2;
    }


    
return 0;
}

以上這兩個函數都是利用掩碼值做一些按位操作,我一直想著有沒有辦法說明其意義,不過很遺憾,我實在沒想出能用漢語說明白的辦法。看來還是大家從計算機世界的語言去弄明白吧~

 

/******************************************************************************************/

完。

posted on 2012-04-24 11:41 Tim 閱讀(1311) 評論(1)  編輯 收藏 引用 所屬分類: eSNACC學習

評論

# re: eSNACC對ASN.1內置字符串的編碼和解碼[未登錄] 2012-04-27 09:38 Tina

加油!  回復  更多評論   

<2012年4月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

導航

統計

公告

本博客原創文章,歡迎轉載和交流。不過請注明以下信息:
作者:TimWu
郵箱:timfly@yeah.net
來源:m.shnenglu.com/Tim
感謝您對我的支持!

留言簿(9)

隨筆分類(173)

IT

Life

搜索

積分與排名

最新隨筆

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲综合激情| 在线观看欧美黄色| 午夜精品久久久久久 | 亚洲欧美亚洲| 日韩午夜电影| 亚洲老板91色精品久久| 亚洲激情第一区| 日韩一区二区免费高清| 夜色激情一区二区| 亚洲欧美日韩在线综合| 久久成人av少妇免费| 久久久av毛片精品| 欧美大片一区二区三区| 亚洲每日在线| 亚洲影院色无极综合| 久久久蜜臀国产一区二区| 欧美劲爆第一页| 国产视频一区免费看| 国产精品永久免费观看| 国产免费一区二区三区香蕉精| 精久久久久久久久久久| 中文无字幕一区二区三区| 欧美呦呦网站| 亚洲电影欧美电影有声小说| 亚洲黄一区二区三区| 亚洲一区黄色| 欧美电影打屁股sp| 国产视频欧美| 正在播放亚洲一区| 欧美+日本+国产+在线a∨观看| 亚洲高清av| 午夜综合激情| 久久久之久亚州精品露出| 欧美日韩亚洲一区二| 在线观看欧美一区| 亚洲制服丝袜在线| 欧美激情亚洲综合一区| 妖精成人www高清在线观看| 一区二区三区在线观看国产| 欧美三区在线视频| 国内精品美女av在线播放| 欧美一区午夜精品| 国产精品美女一区二区| 国产精品久久久久久久久婷婷| 国产一区二区丝袜高跟鞋图片| 日韩一级免费观看| 欧美va天堂| 欧美在线视频导航| 欧美午夜不卡影院在线观看完整版免费 | 一本色道久久88综合日韩精品| 久久精品国产77777蜜臀| 欧美日韩免费在线观看| 亚洲国产精品久久久| 久久久成人精品| 亚洲视屏一区| 欧美日韩国产精品一卡| 91久久精品国产| 蜜月aⅴ免费一区二区三区| 亚洲愉拍自拍另类高清精品| 欧美日韩一区二区在线播放| 亚洲美女色禁图| 欧美福利在线| 久久成人精品无人区| 欧美性色视频在线| 国产精品99久久久久久久久久久久 | 亚洲系列中文字幕| 亚洲黄色有码视频| 快播亚洲色图| 在线看欧美日韩| 美女主播一区| 久久―日本道色综合久久| 黑人一区二区| 久久免费视频在线观看| 欧美制服丝袜第一页| 国模私拍视频一区| 久久人体大胆视频| 欧美制服丝袜第一页| 国内精品久久久久久久97牛牛| 欧美在线啊v| 欧美一区国产在线| 狠狠色狠狠色综合| 免费中文字幕日韩欧美| 老司机免费视频一区二区| 亚洲国产日韩一级| 亚洲高清久久| 欧美日韩一区二区三区高清| 午夜国产欧美理论在线播放| 亚洲女ⅴideoshd黑人| 国产日韩免费| 免费成人小视频| 久久精品国产综合| 久久蜜桃av一区精品变态类天堂| 久久精品国产99国产精品| 欧美有码视频| 欧美一区二区在线播放| 亚洲欧美日韩精品综合在线观看| 国产精品麻豆成人av电影艾秋| 亚洲女同同性videoxma| 午夜精品999| 亚洲欧洲精品一区二区三区不卡| 99国内精品久久久久久久软件| 国产伦精品一区二区| 欧美成人综合网站| 国产精品腿扒开做爽爽爽挤奶网站| 久久女同精品一区二区| 欧美日韩国产bt| 麻豆成人综合网| 国产精品福利影院| 亚洲大片精品永久免费| 国产精品日本精品| 亚洲精品日韩精品| 国产一区二区三区久久| 亚洲看片网站| 136国产福利精品导航网址应用| 99re66热这里只有精品4| 黄网站色欧美视频| 亚洲一区影音先锋| av成人动漫| 免费亚洲一区二区| 久久天堂av综合合色| 国产精品久久久久久久第一福利| 欧美日韩一区视频| 欧美电影在线播放| 黄网站免费久久| 欧美一区二区三区在线看| 亚洲一区不卡| 欧美另类高清视频在线| 欧美/亚洲一区| 国产日韩精品一区二区三区| 亚洲毛片网站| 99热在这里有精品免费| 久久免费高清| 久久久噜噜噜久久人人看| 国产精品午夜av在线| 在线中文字幕一区| 亚洲欧美在线网| 国产精品无人区| 亚洲在线一区二区| 亚洲一区免费看| 欧美性猛交xxxx乱大交退制版| 亚洲国产美女久久久久| 亚洲电影观看| 久久香蕉精品| 欧美不卡在线| 亚洲国产岛国毛片在线| 欧美在线|欧美| 久久久.com| 国产精品电影在线观看| 亚洲欧美日本另类| 欧美日韩在线三级| 亚洲免费观看高清完整版在线观看| 亚洲人精品午夜| 欧美黑人多人双交| 亚洲黄色免费电影| 亚洲美女av黄| 欧美日韩国产另类不卡| 亚洲国产另类久久精品| 亚洲欧洲另类| 欧美色中文字幕| 亚洲欧美日韩精品在线| 国产欧美日韩综合一区在线播放| 久久狠狠一本精品综合网| 国产精品亚洲欧美| 欧美制服丝袜第一页| 麻豆国产va免费精品高清在线| 亚洲国产一二三| 欧美精品在线免费观看| 久久精品女人的天堂av| 亚洲欧美区自拍先锋| 韩日精品在线| 欧美二区在线看| 日韩亚洲欧美精品| 欧美一区二区私人影院日本| 精品动漫3d一区二区三区| 蜜臀av国产精品久久久久| 亚洲日本成人网| 久久精品国产亚洲一区二区| 91久久久国产精品| 国产精品久久二区二区| 久久尤物视频| 亚洲自拍偷拍色片视频| 欧美大成色www永久网站婷| 一区二区三区黄色| 国产一区欧美| 欧美日韩国产精品一区| 久久久国产一区二区| 亚洲精品国久久99热| 久久久久国色av免费看影院| 亚洲人体偷拍| 韩日欧美一区二区三区| 欧美午夜片欧美片在线观看| 国产美女精品一区二区三区| 亚洲国产女人aaa毛片在线| 久久精品国产999大香线蕉| 久久视频一区二区| 欧美成人精品在线播放| 亚洲性xxxx| 亚洲高清不卡av| 亚洲欧美综合精品久久成人| 亚洲国产成人精品视频|