📄 msgheaderscanner.cxx
字号:
taNone, sScanNValue); specTransition(sScanNValueInAngles, ccCarriageReturn, taNone, sHalfLineBreakInAnglesInNValue); specHalfLineBreakState(sHalfLineBreakInAnglesInNValue, sAfterLineBreakInAnglesInNValue); specDefaultTransition(sAfterLineBreakInAnglesInNValue, taError, sAfterLineBreakInAnglesInNValue); specTransition(sAfterLineBreakInAnglesInNValue, ccWhitespace, taNone, sScanNValueInAngles); specHalfLineBreakState(sHalfLineBreakAfterLineBreak, sMsgStart); // Most half-line-break states do nothing when they read a line feed, // but sHalfLineBreakAfterLineBreak must end the message header scanning. specTransition(sHalfLineBreakAfterLineBreak, ccLineFeed, taEndHeader, sMsgStart); // Arbitrary but possibly handy.}// Debug follows#if defined(RESIP_MSG_HEADER_SCANNER_DEBUG) static void printText(const char * text, unsigned int textLength){ const char *charPtr = text; for (unsigned int counter = 0; counter < textLength; ++charPtr, ++counter) { char c = *charPtr; switch (c) { case '\\': printf("\\\\"); break; case '\r': printf("\\r"); break; case '\n': printf("\\n"); break; case '\t': printf("\\t"); break; case '\0': printf("\\0"); break; default: putchar(c); } }}static const char *categorySymbol(CharCategory c){ switch(c) { case ccChunkTermSentinel: return "TERM"; case ccOther: return "*"; case ccFieldName: return "FName"; case ccWhitespace: return "WS"; case ccColon: return "\\\":\\\""; case ccDoubleQuotationMark: return "\\\""; case ccLeftAngleBracket: return "\\\"<\\\""; case ccRightAngleBracket: return "\\\">\\\""; case ccBackslash: return "\\\"\\\\\\\""; case ccComma: return "\\\",\\\""; case ccCarriageReturn: return "CR"; case ccLineFeed: return "LF"; } return "??CC??";}static const char *categoryName(CharCategory c){ switch(c) { case ccChunkTermSentinel: return "ccChunkTermSentinel"; case ccOther: return "ccOther"; case ccFieldName: return "ccFieldName"; case ccWhitespace: return "ccWhitespace"; case ccColon: return "ccColon"; case ccDoubleQuotationMark: return "ccDoubleQuotationMark"; case ccLeftAngleBracket: return "ccLeftAngleBracket"; case ccRightAngleBracket: return "ccRightAngleBracket"; case ccBackslash: return "ccBackslash"; case ccComma: return "ccComma"; case ccCarriageReturn: return "ccCarriageReturn"; case ccLineFeed: return "ccLineFeed"; } return "UNKNOWNCC";}static const char *cleanName(const char * name){ // Remove leading type-noise from name static char *leaders[] = { "cc", "s", "taChunkTerm", // hack to make ChunkTermSentinel smaller "ta" }; const int nLeaders = sizeof(leaders)/sizeof(*leaders); int offset = 0; for(int i = 0 ; i < nLeaders ; i++) { unsigned int l = strlen(leaders[i]); if (strstr(name,leaders[i]) == name && strlen(name) > l && isupper(name[l])) { offset = l; break; } } return &name[offset];}static const char * stateName(State state){ const char *stateName; switch (state) { case sMsgStart: stateName = "sMsgStart"; break; case sHalfLineBreakAtMsgStart: stateName = "sHalfLineBreakAtMsgStart"; break; case sScanStatusLine: stateName = "sScanStatusLine"; break; case sHalfLineBreakAfterStatusLine: stateName = "sHalfLineBreakAfterStatusLine"; break; case sAfterLineBreakAfterStatusLine: stateName = "sAfterLineBreakAfterStatusLine"; break; case sScanFieldName: stateName = "sScanFieldName"; break; case sScanWhitespaceAfter1FieldName: stateName = "sScanWhitespaceAfter1FieldName"; break; case sScanWhitespaceAfterNFieldName: stateName = "sScanWhitespaceAfterNFieldName"; break; case sScanWhitespaceOr1Value: stateName = "sScanWhitespaceOr1Value"; break; case sScanWhitespaceOrNValue: stateName = "sScanWhitespaceOrNValue"; break; case sHalfLineBreakInWhitespaceBefore1Value: stateName = "sHalfLineBreakInWhitespaceBefore1Value"; break; case sHalfLineBreakInWhitespaceBeforeNValue: stateName = "sHalfLineBreakInWhitespaceBeforeNValue"; break; case sAfterLineBreakInWhitespaceBefore1Value: stateName = "sAfterLineBreakInWhitespaceBefore1Value"; break; case sAfterLineBreakInWhitespaceBeforeNValue: stateName = "sAfterLineBreakInWhitespaceBeforeNValue"; break; case sScan1Value: stateName = "sScan1Value"; break; case sScanNValue: stateName = "sScanNValue"; break; case sHalfLineBreakIn1Value: stateName = "sHalfLineBreakIn1Value"; break; case sHalfLineBreakInNValue: stateName = "sHalfLineBreakInNValue"; break; case sAfterLineBreakIn1Value: stateName = "sAfterLineBreakIn1Value"; break; case sAfterLineBreakInNValue: stateName = "sAfterLineBreakInNValue"; break; case sScanNValueInQuotes: stateName = "sScanNValueInQuotes"; break; case sAfterEscCharInQuotesInNValue: stateName = "sAfterEscCharInQuotesInNValue"; break; case sHalfLineBreakInQuotesInNValue: stateName = "sHalfLineBreakInQuotesInNValue"; break; case sAfterLineBreakInQuotesInNValue: stateName = "sAfterLineBreakInQuotesInNValue"; break; case sScanNValueInAngles: stateName = "sScanNValueInAngles"; break; case sHalfLineBreakInAnglesInNValue: stateName = "sHalfLineBreakInAnglesInNValue"; break; case sAfterLineBreakInAnglesInNValue: stateName = "sAfterLineBreakInAnglesInNValue"; break; case sHalfLineBreakAfterLineBreak: stateName = "sHalfLineBreakAfterLineBreak"; break; default: stateName = "<unknown>"; }//switch return stateName;}static const char *trActionName(TransitionAction transitionAction){ const char *transitionActionName; switch (transitionAction) { case taNone: transitionActionName = "taNone"; break; case taTermStatusLine: transitionActionName = "taTermStatusLine"; break; case taTermFieldName: transitionActionName = "taTermFieldName"; break; case taBeyondEmptyValue: transitionActionName = "taBeyondEmptyValue"; break; case taTermValueAfterLineBreak: transitionActionName = "taTermValueAfterLineBreak"; break; case taTermValue: transitionActionName = "taTermValue"; break; case taStartText: transitionActionName = "taStartText"; break; case taEndHeader: transitionActionName = "taEndHeader"; break; case taChunkTermSentinel: transitionActionName = "taChunkTermSentinel"; break; case taError: transitionActionName = "taError"; break; default: transitionActionName = "<unknown>"; } return transitionActionName;}static voidprintStateTransition(State state, char character, TransitionAction transitionAction){ printf(" %s['", cleanName(stateName(state))); printText(&character, 1); printf("']: %s\n", cleanName(trActionName(transitionAction)));}#if !defined(RESIP_MSG_HEADER_SCANNER_DEBUG)static const char* stateName(const char*){ return "RECOMPILE_WITH_SCANNER_DEBUG"; }static const char* trActionName(const char*){ return stateName(0); }#endif/// START OF MEMBER METHODSintMsgHeaderScanner::dumpStateMachine(int fd){ FILE *fp = fdopen(fd,"w"); if (!fp) { fprintf(stderr,"MsgHeaderScanner:: unable to open output file\n"); return -1; } // Force instance so things are initialized -- YUCK! MsgHeaderScanner scanner;(void)scanner; fprintf(fp,"digraph MsgHeaderScannerFSM {\n"); fprintf(fp,"\tnode[shape=record\n\t\tfontsize=8\n\t\tfontname=\"Helvetica\"\n\t]\n"); fprintf(fp,"\tedge [ fontsize=6 fontname=\"Helvetica\"]\n"); fprintf(fp,"\tgraph [ ratio=0.8\n\t\tfontsize=6 compound=true ]"); for(int state = 0 ; state < numStates; ++state) { fprintf(fp, " %s [ label = \"%d|%s\" ]\n", cleanName(stateName(state)), state, cleanName(stateName(state)) ); for(int category = 0 ; category < numCharCategories; ++category) { // Skip Verbose Error or Empty Transitions if (stateMachine[state][category].nextState == state && (stateMachine[state][category].action == taError || stateMachine[state][category].action == taNone )) continue; fprintf(fp, " %s -> %s [label=\"%s\\n%s\" ]\n", cleanName(stateName(state)), cleanName(stateName(stateMachine[state][category].nextState)), categorySymbol(category), cleanName(trActionName(stateMachine[state][category].action))); } fprintf(fp,"\n"); } fprintf(fp,"}\n"); return 0;}#endif //defined(RESIP_MSG_HEADER_SCANNER_DEBUG) #if defined(RESIP_MSG_HEADER_SCANNER_DEBUG) static const char *const multiValuedFieldNameArray[] = { "allow-events", "accept-encoding", "accept-language", "allow", "content-language", "proxy-require", "require", "supported", "subscription-state", "unsupported", "security-client", "security-server", "security-verify", "accept", "call-info", "alert-info", "error-info", "record-route", "route", "contact", "authorization", "proxy-authenticate", "proxy-authorization", "www-authenticate", "via", 0};externvoidlookupMsgHeaderFieldInfo( char * fieldName, //inout unsigned int *fieldNameLength, //inout MsgHeaderScanner::TextPropBitMask fieldNameTextPropBitMask, int *fieldKind, //out bool *isMultiValueAllowed) //out{ *isMultiValueAllowed = false; const char *const *multiValuedFieldNamePtr = multiValuedFieldNameArray; for (;;) { const char *multiValuedFieldName = *multiValuedFieldNamePtr; if (!multiValuedFieldName) { break; } if (strncmp(fieldName, multiValuedFieldName, *fieldNameLength) == 0) { *isMultiValueAllowed = true; break; } ++multiValuedFieldNamePtr; }//for}staticbool
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -