📄 jim.c
字号:
objPtr->nextObjPtr = interp->liveList;
if (interp->liveList)
interp->liveList->prevObjPtr = objPtr;
interp->liveList = objPtr;
return objPtr;
}
/* Free an object. Actually objects are never freed, but
* just moved to the free objects list, where they will be
* reused by Jim_NewObj(). */
void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
{
/* Check if the object was already freed, panic. */
if (objPtr->refCount != 0) {
Jim_Panic(interp,"!!!Object %p freed with bad refcount %d", objPtr,
objPtr->refCount);
}
/* Free the internal representation */
Jim_FreeIntRep(interp, objPtr);
/* Free the string representation */
if (objPtr->bytes != NULL) {
if (objPtr->bytes != JimEmptyStringRep)
Jim_Free(objPtr->bytes);
}
/* Unlink the object from the live objects list */
if (objPtr->prevObjPtr)
objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr;
if (objPtr->nextObjPtr)
objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr;
if (interp->liveList == objPtr)
interp->liveList = objPtr->nextObjPtr;
/* Link the object into the free objects list */
objPtr->prevObjPtr = NULL;
objPtr->nextObjPtr = interp->freeList;
if (interp->freeList)
interp->freeList->prevObjPtr = objPtr;
interp->freeList = objPtr;
objPtr->refCount = -1;
}
/* Invalidate the string representation of an object. */
void Jim_InvalidateStringRep(Jim_Obj *objPtr)
{
if (objPtr->bytes != NULL) {
if (objPtr->bytes != JimEmptyStringRep)
Jim_Free(objPtr->bytes);
}
objPtr->bytes = NULL;
}
#define Jim_SetStringRep(o, b, l) \
do { (o)->bytes = b; (o)->length = l; } while (0)
/* Set the initial string representation for an object.
* Does not try to free an old one. */
void Jim_InitStringRep(Jim_Obj *objPtr, const char *bytes, int length)
{
if (length == 0) {
objPtr->bytes = JimEmptyStringRep;
objPtr->length = 0;
} else {
objPtr->bytes = Jim_Alloc(length+1);
objPtr->length = length;
memcpy(objPtr->bytes, bytes, length);
objPtr->bytes[length] = '\0';
}
}
/* Duplicate an object. The returned object has refcount = 0. */
Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr)
{
Jim_Obj *dupPtr;
dupPtr = Jim_NewObj(interp);
if (objPtr->bytes == NULL) {
/* Object does not have a valid string representation. */
dupPtr->bytes = NULL;
} else {
Jim_InitStringRep(dupPtr, objPtr->bytes, objPtr->length);
}
if (objPtr->typePtr != NULL) {
if (objPtr->typePtr->dupIntRepProc == NULL) {
dupPtr->internalRep = objPtr->internalRep;
} else {
objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr);
}
dupPtr->typePtr = objPtr->typePtr;
} else {
dupPtr->typePtr = NULL;
}
return dupPtr;
}
/* Return the string representation for objPtr. If the object
* string representation is invalid, calls the method to create
* a new one starting from the internal representation of the object. */
const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr)
{
if (objPtr->bytes == NULL) {
/* Invalid string repr. Generate it. */
if (objPtr->typePtr->updateStringProc == NULL) {
Jim_Panic(NULL,"UpdataStringProc called against '%s' type.",
objPtr->typePtr->name);
}
objPtr->typePtr->updateStringProc(objPtr);
}
if (lenPtr)
*lenPtr = objPtr->length;
return objPtr->bytes;
}
/* Just returns the length of the object's string rep */
int Jim_Length(Jim_Obj *objPtr)
{
int len;
Jim_GetString(objPtr, &len);
return len;
}
/* -----------------------------------------------------------------------------
* String Object
* ---------------------------------------------------------------------------*/
static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
static Jim_ObjType stringObjType = {
"string",
NULL,
DupStringInternalRep,
NULL,
JIM_TYPE_REFERENCES,
};
void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr)
{
JIM_NOTUSED(interp);
/* This is a bit subtle: the only caller of this function
* should be Jim_DuplicateObj(), that will copy the
* string representaion. After the copy, the duplicated
* object will not have more room in teh buffer than
* srcPtr->length bytes. So we just set it to length. */
dupPtr->internalRep.strValue.maxLength = srcPtr->length;
}
int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr)
{
/* Get a fresh string representation. */
(void) Jim_GetString(objPtr, NULL);
/* Free any other internal representation. */
Jim_FreeIntRep(interp, objPtr);
/* Set it as string, i.e. just set the maxLength field. */
objPtr->typePtr = &stringObjType;
objPtr->internalRep.strValue.maxLength = objPtr->length;
return JIM_OK;
}
Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len)
{
Jim_Obj *objPtr = Jim_NewObj(interp);
if (len == -1)
len = strlen(s);
/* Alloc/Set the string rep. */
if (len == 0) {
objPtr->bytes = JimEmptyStringRep;
objPtr->length = 0;
} else {
objPtr->bytes = Jim_Alloc(len+1);
objPtr->length = len;
memcpy(objPtr->bytes, s, len);
objPtr->bytes[len] = '\0';
}
/* No typePtr field for the vanilla string object. */
objPtr->typePtr = NULL;
return objPtr;
}
/* This version does not try to duplicate the 's' pointer, but
* use it directly. */
Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len)
{
Jim_Obj *objPtr = Jim_NewObj(interp);
if (len == -1)
len = strlen(s);
Jim_SetStringRep(objPtr, s, len);
objPtr->typePtr = NULL;
return objPtr;
}
/* Low-level string append. Use it only against objects
* of type "string". */
void StringAppendString(Jim_Obj *objPtr, const char *str, int len)
{
int needlen;
if (len == -1)
len = strlen(str);
needlen = objPtr->length + len;
if (objPtr->internalRep.strValue.maxLength < needlen ||
objPtr->internalRep.strValue.maxLength == 0) {
if (objPtr->bytes == JimEmptyStringRep) {
objPtr->bytes = Jim_Alloc((needlen*2)+1);
} else {
objPtr->bytes = Jim_Realloc(objPtr->bytes, (needlen*2)+1);
}
objPtr->internalRep.strValue.maxLength = needlen*2;
}
memcpy(objPtr->bytes + objPtr->length, str, len);
objPtr->bytes[objPtr->length+len] = '\0';
objPtr->length += len;
}
/* Low-level wrapper to append an object. */
void StringAppendObj(Jim_Obj *objPtr, Jim_Obj *appendObjPtr)
{
int len;
const char *str;
str = Jim_GetString(appendObjPtr, &len);
StringAppendString(objPtr, str, len);
}
/* Higher level API to append strings to objects. */
void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str,
int len)
{
if (Jim_IsShared(objPtr))
Jim_Panic(interp,"Jim_AppendString called with shared object");
if (objPtr->typePtr != &stringObjType)
SetStringFromAny(interp, objPtr);
StringAppendString(objPtr, str, len);
}
void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr,
Jim_Obj *appendObjPtr)
{
int len;
const char *str;
str = Jim_GetString(appendObjPtr, &len);
Jim_AppendString(interp, objPtr, str, len);
}
void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
{
va_list ap;
if (objPtr->typePtr != &stringObjType)
SetStringFromAny(interp, objPtr);
va_start(ap, objPtr);
while (1) {
char *s = va_arg(ap, char*);
if (s == NULL) break;
Jim_AppendString(interp, objPtr, s, -1);
}
va_end(ap);
}
int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr, int nocase)
{
const char *aStr, *bStr;
int aLen, bLen, i;
if (aObjPtr == bObjPtr) return 1;
aStr = Jim_GetString(aObjPtr, &aLen);
bStr = Jim_GetString(bObjPtr, &bLen);
if (aLen != bLen) return 0;
if (nocase == 0)
return memcmp(aStr, bStr, aLen) == 0;
for (i = 0; i < aLen; i++) {
if (tolower((int)aStr[i]) != tolower((int)bStr[i]))
return 0;
}
return 1;
}
int Jim_StringMatchObj(Jim_Obj *patternObjPtr, Jim_Obj *objPtr,
int nocase)
{
const char *pattern, *string;
int patternLen, stringLen;
pattern = Jim_GetString(patternObjPtr, &patternLen);
string = Jim_GetString(objPtr, &stringLen);
return JimStringMatch(pattern, patternLen, string, stringLen, nocase);
}
int Jim_StringCompareObj(Jim_Obj *firstObjPtr,
Jim_Obj *secondObjPtr, int nocase)
{
const char *s1, *s2;
int l1, l2;
s1 = Jim_GetString(firstObjPtr, &l1);
s2 = Jim_GetString(secondObjPtr, &l2);
return JimStringCompare(s1, l1, s2, l2, nocase);
}
/* Convert a range, as returned by Jim_GetRange(), into
* an absolute index into an object of the specified length.
* This function may return negative values, or values
* bigger or equal to the length of the list if the index
* is out of range. */
static int JimRelToAbsIndex(int len, int index)
{
if (index < 0)
return len + index;
return index;
}
/* Convert a pair of index as normalize by JimRelToAbsIndex(),
* into a range stored in *firstPtr, *lastPtr, *rangeLenPtr, suitable
* for implementation of commands like [string range] and [lrange].
*
* The resulting range is guaranteed to address valid elements of
* the structure. */
static void JimRelToAbsRange(int len, int first, int last,
int *firstPtr, int *lastPtr, int *rangeLenPtr)
{
int rangeLen;
if (first > last) {
rangeLen = 0;
} else {
rangeLen = last-first+1;
if (rangeLen) {
if (first < 0) {
rangeLen += first;
first = 0;
}
if (last >= len) {
rangeLen -= (last-(len-1));
last = len-1;
}
}
}
if (rangeLen < 0) rangeLen = 0;
*firstPtr = first;
*lastPtr = last;
*rangeLenPtr = rangeLen;
}
Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp,
Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr)
{
int first, last;
const char *str;
int len, rangeLen;
if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK ||
Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK)
return NULL;
str = Jim_GetString(strObjPtr, &len);
first = JimRelToAbsIndex(len, first);
last = JimRelToAbsIndex(len, last);
JimRelToAbsRange(len, first, last, &first, &last, &rangeLen);
return Jim_NewStringObj(interp, str+first, rangeLen);
}
static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
{
char *buf = Jim_Alloc(strObjPtr->length+1);
int i;
memcpy(buf, strObjPtr->bytes, strObjPtr->length+1);
for (i = 0; i < strObjPtr->length; i++)
buf[i] = tolower(buf[i]);
return Jim_NewStringObjNoAlloc(interp, buf, strObjPtr->length);
}
static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
{
char *buf = Jim_Alloc(strObjPtr->length+1);
int i;
memcpy(buf, strObjPtr->bytes, strObjPtr->length+1);
for (i = 0; i < strObjPtr->length; i++)
buf[i] = toupper(buf[i]);
return Jim_NewStringObjNoAlloc(interp, buf, strObjPtr->length);
}
/* This is the core of the [format] command.
* TODO: Export it, make it real... for now only %s and %%
* specifiers supported. */
Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
int objc, Jim_Obj *const *objv)
{
const char *fmt;
int fmtLen;
Jim_Obj *resObjPtr;
fmt = Jim_GetString(fmtObjPtr, &fmtLen);
resObjPtr = Jim_NewStringObj(interp, "", 0);
while (fmtLen) {
const char *p = fmt;
char spec[2], c;
jim_wide wideValue;
while (*fmt != '%' && fmtLen) {
fmt++; fmtLen--;
}
Jim_AppendString(interp, resObjPtr, p, fmt-p);
if (fmtLen == 0)
break;
fmt++; fmtLen--; /* skip '%' */
if (*fmt != '%') {
if (objc == 0) {
Jim_FreeNewObj(interp, resObjPtr);
Jim_SetResultString(interp,
"not enough arguments for all format specifiers", -1);
return NULL;
} else {
objc--;
}
}
switch(*fmt) {
case 's':
Jim_AppendObj(interp, resObjPtr, objv[0]);
objv++;
break;
case 'c':
if (Jim_GetWide(interp, objv[0], &wideValue) == JIM_ERR) {
Jim_FreeNewObj(interp, resObjPtr);
return NULL;
}
c = (char) wideValue;
Jim_AppendString(interp, resO
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -