📄 textgen.c
字号:
SSMStatus rv = SSM_SUCCESS; PRInt32 i; PRInt32 numParams; /* in case we fail */ *keywdResult = NULL; *paramResult = NULL; if (!orig) { rv = PR_INVALID_ARGUMENT_ERROR; goto loser; } /* Get the keyword out first. */ /* If we have parameters, copy them off. */ space = PL_strchr(orig, punct_ch[TEXTGEN_PUNCT_SPACE]); if (space != NULL) { char ch; ch = space[0]; space[0] = '\0'; keywd = PL_strdup(orig); space[0] = ch; } else { int len, i; len = PL_strlen(orig); keywd = PL_strdup(orig); for (i=len; i>=0 && isspace(keywd[i]); i--) { keywd = '\0'; } } /* Now get the parameters. */ if (space != NULL) { cursor = space+1; numParams = SSMTextGen_CountCommas(cursor)+2; params = SSM_ZNEW_ARRAY(char*, numParams); for (i=0; i<(numParams-1) && cursor != NULL; i++) { comma = PL_strchr(cursor, punct_ch[TEXTGEN_PUNCT_COMMA]); if (comma != NULL) { argLen = comma-cursor; } else { argLen = PL_strlen(cursor); } params[i] = SSM_NEW_ARRAY(char, (argLen+1)); if (params[i] == NULL) { goto loser; } PL_strncpy(params[i], cursor, argLen); params[i][argLen] = '\0'; cursor = (comma == NULL) ? NULL : comma+1; } } goto done; loser: if (rv != SSM_SUCCESS) rv = SSM_FAILURE; if (keywd) { PR_Free(keywd); keywd = NULL; } if (params) { SSMTextGen_DeleteStringPtrArray(params); params = NULL; } done: *keywdResult = keywd; *paramResult = params; return rv;}/* Keyword handler routines */static SSMStatusSSM_KeywordHandlerInitialize(void){ keyword_handlers = SSM_NewCollection(); return SSM_SUCCESS;}SSMStatusSSM_RegisterKeywordHandler(char *keyword, KeywordHandlerFunc func){ SSMStatus rv = SSM_SUCCESS; KeywordHandlerEntry *entry = NULL; if ((!keyword_handlers) || (!keyword) || (!func)) goto loser; entry = (KeywordHandlerEntry *) PR_CALLOC(sizeof(KeywordHandlerEntry)); if (!entry) goto loser; entry->keyword = keyword; entry->func = func; SSM_Enqueue(keyword_handlers, SSM_PRIORITY_NORMAL, entry); goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; if (entry) PR_Free(entry); done: return rv;}SSMStatusSSMTextGen_DeregisterKeywordHandler(KeywordHandlerFunc *func){ KeywordHandlerEntry *e, *found = NULL; PRIntn i; PRIntn numEntries = SSM_Count(keyword_handlers); SSMStatus rv = SSM_SUCCESS; for(i=0;i<numEntries;i++) { e = (KeywordHandlerEntry *) SSM_At(keyword_handlers, i); if ((e != NULL) && (e->func == (KeywordHandlerFunc) func)) { found = e; break; } } if (found) { rv = SSM_Remove(keyword_handlers, found); if (rv == SSM_SUCCESS) { /* Deallocate (found) since we no longer need it. */ PR_Free(found); } } else rv = SSM_FAILURE; return rv;}static SSMStatusSSMTextGen_FindKeywordHandler(char *key, KeywordHandlerFunc *func){ KeywordHandlerEntry *e, *found = NULL; char *key_ch = key; PRIntn i; PRIntn numEntries = SSM_Count(keyword_handlers); *func = NULL; /* in case we fail */ if (key_ch) { for(i=0;i<numEntries;i++) { e = (KeywordHandlerEntry *) SSM_At(keyword_handlers, i); if (!PL_strcmp(e->keyword, key_ch)) { found = e; break; } } } if (found) *func = found->func; return (*func ? SSM_SUCCESS : SSM_FAILURE);}/* Given a numbered keyword argument in (arg), return the appropriate argument from the textgen context. */static SSMStatusSSMTextGen_ReplaceArgument(SSMTextGenContext *cx, char *keywd, char **dest){ SSMStatus rv = SSM_SUCCESS; char *arg = NULL, *param = NULL, *raw; PRInt32 argNum = -1; /* Is the first char a $? If not, bail. */ raw = keywd; if ((!raw) || (raw[0] != punct_ch[TEXTGEN_PUNCT_DOLLAR])) goto loser; /* If we're here, this means that we think we have a numeric parameter. Copy the keyword, lop off the first char, and convert to an arg number. */ arg = keywd+1; argNum = SSMTextGen_atoi(SSMTextGen_GetLocale(cx), arg); if (argNum < 0) goto loser; param = (char *) SSM_At(cx->m_params, argNum-1); if (!param) { SSM_DEBUG("ERROR: Wanted argument %d when only %d args present.\n", argNum, SSM_Count(cx->m_params)); SSMTextGen_Traceback(NULL, cx); goto loser; } *dest = PL_strdup(param); goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; if (*dest) { PR_Free(*dest); *dest = NULL; } done: return rv;}/* Given a PSM keyword (presumably found within a string), replace it with appropriate content.*/static SSMStatusSSMTextGen_ProcessKeyword(SSMTextGenContext *cx, char *src, char **dest){ SSMStatus rv = SSM_SUCCESS; SSMTextGenContext *newcx = NULL; char *keywd = NULL; char **params = NULL; KeywordHandlerFunc func; *dest = NULL; /* in case we fail */ if (PL_strchr(src, '\n')) { /* We've got some text with newlines in it. Keywords in properties * files aren't allowed to have newlines in them. */ goto loser; } /* Split out into keyword and parameters. */ rv = SSMTextGen_SplitKeywordParams(src, &keywd, ¶ms); if (rv != SSM_SUCCESS) goto loser;/* SSM_DebugUTF8String("SSMTextGen_ProcessKeyword - orig src", src); *//* SSM_DebugUTF8String("SSMTextGen_ProcessKeyword - keywd", keywd); *//* if (cx->m_params) *//* { *//* char buf[256]; *//* int i = 0; *//* UnicodeStringPtr param = NULL; *//* for(param = SSM_At(cx->m_params, 0), i = 0; param != NULL; i++) *//* { *//* param = SSM_At(cx->m_params, i); *//* if (param) *//* { *//* PR_snprintf(buf, 256, "SSMTextGen_ProcessKeyword - param[%d]", i+1); *//* SSM_DebugUTF8String(buf, param); *//* } *//* } *//* } */ /* If this is a numbered parameter, replace it with what we have stored in the textgen context. */ rv = SSMTextGen_ReplaceArgument(cx, keywd, dest); if (rv == SSM_SUCCESS) goto done; /* Push the textgen stack. */ newcx = SSMTextGen_PushStack(cx, keywd, params); if (!newcx) goto loser; /* SSMTextGen_PushStack puts the args of params into a * collection. So we can now free the array since the * individual pointers are stored in a collection */ PR_Free(params); params = NULL; /* Look for a keyword handler. */ rv = SSMTextGen_FindKeywordHandler(keywd, &func); if ((rv == SSM_SUCCESS) && (func)) { /* Run the keyword handler. */ rv = (*func)(newcx); if (rv != SSM_SUCCESS) { SSMTextGen_Traceback("Keyword handler returned error %d", newcx); goto loser; } *dest = newcx->m_result; newcx->m_result = NULL; /* so the memory doesn't get deallocated now */ goto done; } /* Treat (keywd) as the name of a string in the properties file. Extract the value, expand it, and return it (if there is something available). (This pushes the textgen stack.) */ rv = SSM_GetAndExpandTextKeyedByString(newcx, keywd, dest); if (rv == SSM_SUCCESS) goto done; loser: if (rv == SSM_SUCCESS) rv = SSM_FAILURE; if (*dest) { PR_Free(*dest); *dest = NULL; } done: if (keywd) PR_Free(keywd); if (newcx) SSMTextGen_DestroyContext(newcx);/* if (params && !newcx) *//* SSMTextGen_DeleteStringPtrArray(params); */ return rv;}typedef struct SSMTextGenResultStr { char *result; int allocSize, curSize;} SSMTextGenResult;SSMStatusssmtextgen_init_segresult(SSMTextGenResult *result, int origLen){ memset (result, 0, sizeof(SSMTextGenResult)); result->allocSize = (int)(origLen*1.5); result->result = SSM_NEW_ARRAY(char, result->allocSize+1); if (result->result == NULL) { return SSM_FAILURE; } result->result[0] = '\0'; result->curSize = 0; return SSM_SUCCESS;}SSMStatusssmtextgen_add_segment(SSMTextGenResult *result, char *segment){ int segLen; segLen = PL_strlen(segment); if ((result->curSize+segLen) > result->allocSize) { char *newString; int newLen, defReallocLen, newSegReallocLen; defReallocLen = result->allocSize*2; newSegReallocLen = segLen + result->curSize; newLen = (defReallocLen > newSegReallocLen) ? defReallocLen : newSegReallocLen * 2; newString = (char *) PR_Realloc(result->result, newLen); if (newString == NULL) { return SSM_FAILURE; } result->result = newString; result->allocSize = newLen; } memcpy(&result->result[result->curSize], segment, segLen); result->curSize += segLen; result->result[result->curSize] = '\0'; return SSM_SUCCESS;}/* Perform substitutions for non-numeric parameters in (str). Parameters in the text are surrounded by curly braces.*/SSMStatusSSMTextGen_SubstituteString(SSMTextGenContext *cx, char *str, char **result){ SSMStatus rv = SSM_SUCCESS; int startOff = 0, leftOff = 0, rightOff = 0; int len, fragLen, rightBraceIndex; char *repl1 = NULL, *repl2 = NULL; PRBool done = PR_FALSE; char *leftBrace, *rightBrace; char *tmp, *raw; SSMTextGenResult segResult; /* in case we fail */ *result = NULL; if ((!str) || (!result)) return SSM_FAILURE; /* Get the length of the source string, and a ptr into it */ raw = str; len = PL_strlen(raw); if (ssmtextgen_init_segresult(&segResult, len) != SSM_SUCCESS) { goto loser; } /* Scan the string for the next keyword, if any. */ while (1) { /* First look for the left brace */ leftBrace = PL_strchr(raw, punct_ch[TEXTGEN_PUNCT_LEFTBRACE]); if (leftBrace == NULL) { if (ssmtextgen_add_segment(&segResult, raw) != SSM_SUCCESS) { goto loser; } break; } /* Look for the corresponding right brace. */ rightBraceIndex = SSMTextGen_FindRightBrace(leftBrace); if (rightBraceIndex >= len) { /* No corresponding right brace, should ignore this one. */ /* We can stop processing here. */ if (ssmtextgen_add_segment(&segResult, raw) != SSM_SUCCESS) { goto loser; } break; } /* Process the keyword. */ /* Get all of the text between the braces and expand it. */ rightBrace = &leftBrace[rightBraceIndex]; fragLen = rightBraceIndex;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -