📄 int_str.c
字号:
/*..........................................................................*//* *//* L a s t W a v e K e r n e l 3 . 0 *//* *//* Copyright (C) 1998-2003 Emmanuel Bacry. *//* email : lastwave@cmap.polytechnique.fr *//* *//*..........................................................................*//* *//* This program is a free software, you can redistribute it and/or *//* modify it under the terms of the GNU General Public License as *//* published by the Free Software Foundation; either version 2 of the *//* License, or (at your option) any later version *//* *//* This program is distributed in the hope that it will be useful, *//* but WITHOUT ANY WARRANTY; without even the implied warranty of *//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *//* GNU General Public License for more details. *//* *//* You should have received a copy of the GNU General Public License *//* along with this program (in a file named COPYRIGHT); *//* if not, write to the Free Software Foundation, Inc., *//* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* *//*..........................................................................*//***************************************************************** * * The String content * *****************************************************************/ #include "lastwave.h"#include <stdarg.h>#include "signals.h"#include "images.h"#include "int_fsilist.h" /* Type of a string */char *strType = "&string";/* Types used only for specifying procedure arguments types */char *listType = "&list";char *wordType = "&word";char *wordlistType = "&wordlist";char *valType = "&val";char *valobjType = "&valobj";/* * Answers to the different print messages */#define StrShortPrintLength 10#define StrPrintLength 200 void PrintStrContent(STRVALUE sc){ Printf("'%s'\n",sc->str);}static void _PrintStr(char *strOut, char *str,int length){ int n; char c; if (strlen(str)<length) sprintf(strOut,"'%s'",str); else { n = MIN(strlen(str),length-2); c = str[n]; str[n] = '\0'; sprintf(strOut,"'%s...'",str); str[n] = c; }}char *ToStrStrContent(STRVALUE sc, char flagShort){ static char str[StrPrintLength]; if (flagShort) _PrintStr(str,sc->str,StrShortPrintLength); else _PrintStr(str,sc->str,StrPrintLength); return(str);}void PrintInfoStrContent(STRVALUE sc){ Printf(" length = %d\n",strlen(sc->str));}/* * The different extract options */static char *extractOptionsStr[] = {"*nolimit","*bperiodic","*bmirror","*bmirror1","*list",NULL};enum { FSIOptStrNoLimit = FSIOption1, FSIOptStrBPer = FSIOption2, FSIOptStrBMir = FSIOption3, FSIOptStrBMir1 = FSIOption4, FSIOptStrList = FSIOption5}; /* * The function that manages setting a string using explicit parameters */char *SetStr_(char **strLeft,FSIList *fsiList, LWFLOAT flt, VALUE val,char *equal, char *fieldName){ FSI_DECL; int _j,j,k,_iold; char *strRight,*str,*type; int lRight,lLeft,length; LISTV lv; static STRVALUE sc1 = NULL; static STRVALUE sc2 = NULL; /* Get the type of the right value */ if (val == NULL) type = numType; else { type = GetTypeValue(val); if (type == numType) flt = CastValue(val,NUMVALUE)->f; } /************************* * * Case right value is a LWFLOAT * * s *= 3 * *************************/ if (type == numType) { if (*equal != '*') { SetErrorf("The '<string> %s <number>' syntax is not adequate",equal); return(NULL); } if (fsiList != NULL) { SetErrorf("The '%s' syntax is not adequate on a string[range]",equal); return(NULL); } if (flt != (int) flt) { SetErrorf("Right handside of assignement should be an integer"); return(NULL); } if (sc1 == NULL) { sc1 = NewNullStrValue(); sc2 = NewNullStrValue(); } sc1->str = *strLeft; InitStrValue(sc2); MultStrValue(sc1, (int) flt,sc2); Free(*strLeft); *strLeft = sc2->str; sc1->str = NULL; sc2->str = NULL; return(strType); } /************************* * * Case right value is a string * *************************/ if (type == strType) { /* Get the right handside string and its length */ strRight = CastValue(val,STRVALUE)->str; lRight = strlen(strRight); /* Get left handside length */ lLeft = strlen(*strLeft); /* * Case simple assignement 'strLeft... op strRight' */ /* 'strLeft op strRight' or 'strLeft[] op strRight' */ if (fsiList == NULL || fsiList->nx == 0) { if (*equal == '=') { /* 'strLeft = strRight' or 'strLeft[] = strRight' */ if (lLeft >= lRight) strcpy(*strLeft,strRight); else { Free(*strLeft); *strLeft = CharAlloc(MAX(lRight,MinStringSize)+1); strcpy(*strLeft,strRight); } } else if (*equal == '+') { /* 'strLeft += strRight' or 'strLeft[] += strRight' */ str = CharAlloc(MAX(lRight+lLeft,MinStringSize)+1); strcpy(str,*strLeft); strcpy(str+lLeft,strRight); Free(*strLeft); *strLeft = str; } else { SetErrorf("The '%s' syntax is not adequate",equal); return(NULL); } return(strType); } if (*equal != ':' && *equal != '=') { SetErrorf("The '%s' syntax is not adequate for operating on strings",equal); return(NULL); } /* * Case of an extraction strLeft[1:3,7]=strRight (i.e., SAME SIZE) */ if (*equal == '=') { if (lRight != fsiList->nx) { SetErrorf("String lengths do not match"); return(NULL); } _j = 0; FSI_FOR_START(fsiList); (*strLeft)[_i] = strRight[_j++]; FSI_FOR_END; return(strType); } /* * Case of an extraction s[1:3,7] := "ab" (i.e., NOT SAME SIZE) */ /* In the case s[1,2,6,9] := "a" it is particularly simple */ if (fsiList->nx == fsiList->size && lRight == 1) { FSI_FOR_START(fsiList); (*strLeft)[_i]= *strRight; FSI_FOR_END; return(strType); } /* We first need to compute the new length */ length = strlen(*strLeft) - fsiList->nx + fsiList->nx*lRight; str = CharAlloc(MAX(length,MinStringSize)+1); /* Then we perform the set */ j = 0; /* Index in the *strLeft string */ k = 0; /* Index in the str string */ _iold = -1; FSI_FOR_START(fsiList); /* We check the fsiList is sorted */ if (_i <= _iold) { SetErrorf("Sorry, this operation with non sorted indexes is not implemented"); Free(str); return(NULL); } _iold = _i; strncpy(str+k,*strLeft+j,_i-j); k+=_i-j; strcpy(str+k,strRight); k+=lRight; j=_i+1; FSI_FOR_END; strcat(str+k,*strLeft+j); Free(*strLeft); *strLeft = str; return(strType); } /************************* * * Case val is a listv * * *************************/ else if (type == listvType) { lv = CastValue(val,LISTV); if (fsiList == NULL) { SetErrorf("Syntax 'string = listv' not valid"); return(NULL); } /* Must be of the type s[1:3,4,2:4] = {"a" "bb" "c"} or s[1:3,4,2:4] := {"a"} */ if (*equal == '=' && lv->length != fsiList->size) { SetErrorf("Length of extraction list should be the same as length of &listv"); return(NULL); } if (*equal == ':' && lv->length != 1) { SetErrorf("Length of right handside &listv should be 1"); return(NULL); } /* We first need to compute the length of the listv */ lRight = 0; for (j=0;j<lv->length;j++) { if (lv->values[j] == NULL || GetTypeValue(lv->values[j]) != strType) { SetErrorf("The &listv should contain only &string elements"); return(NULL); } lRight += strlen(CastValue(lv->values[j],STRVALUE)->str); } if (*equal ==':') lRight*=fsiList->size; /* Then we go */ lRight += strlen(*strLeft)-fsiList->nx; str = CharAlloc(MAX(lRight,MinStringSize)+1); /* Then we perform the set */ j = 0; /* Index in the *strLeft string */ k = 0; /* Index in the str string */ _iold = -1; FSI_FOR_START1(fsiList); if (*equal == ':') strRight = CastValue(lv->values[0],STRVALUE)->str; else strRight = CastValue(lv->values[_n],STRVALUE)->str; switch(fsi->type) { case FSIFloat : _j = (int) fsi->val.f; if (_j<=_iold) { SetErrorf("Sorry, this operation with non sorted indexes is not implemented"); Free(str); return(NULL); } _iold = _j; strncpy(str+k,*strLeft+j,_j-j); k+=_j-j; strcpy(str+k,strRight); k+=strlen(strRight); j=_j+1; break; case FSIRange : _j = (int) fsi->val.r->first; if (_j<=_iold) { SetErrorf("Sorry, this operation with non sorted indexes is not implemented"); Free(str); return(NULL); } if (fsi->val.r->step != 1) { SetErrorf("Sorry, only ranges with a step of 1 are valid indexes for this operation"); Free(str); return(NULL); } _iold = _j+fsi->val.r->size-1; strncpy(str+k,*strLeft+j,_j-j); k+=_j-j; strcpy(str+k,strRight); k+=strlen(strRight); j=_j+fsi->val.r->size; break; case FSISignal : SetErrorf("Sorry, only ranges or numbers are valid indexes for this operation"); Free(str); return(NULL); } FSI_FOR_END1; strcat(str+k,*strLeft+j); Free(*strLeft); *strLeft = str; return(strType); } else { if (fieldName == NULL) SetErrorf("Cannot assign '%s' to string",GetTypeValue(val)); else SetErrorf("Cannot assign field '%s' with non string argument (type is '%s')",GetTypeValue(val)); return(NULL); }}/* * Basic routine to deal with setting a string field (with eventual extraction) */void *SetStrField(char **pstr, void **arg){ char *field = NULL; FSIList *fsiList = ARG_S_GetFsiList(arg); char *type = ARG_S_GetRightType(arg); LWFLOAT flt = ARG_S_GetRightFloat(arg); VALUE val = ARG_S_GetRightValue(arg); char *equal = ARG_S_GetEqual(arg); char **pstrRes = ARG_S_GetResPStr(arg); if (SetStr_(pstr,fsiList,flt,val,equal,field) == NULL) return(NULL); *pstrRes = *pstr; return(strType);}/* * Routine to deal with setting of strings */static char *doc = "{[*opt,...] [:]= (<string> | <listv>)} {Get/Set characters}"; static void *SetExtractStrV(VALUE val,void **arg){ char *field; FSIList *fsiList; char *type; LWFLOAT flt; char *equal; char **pstrRes; VALUE val1; STRVALUE sc; /* Doc */ if (val == NULL) return(doc); sc = (STRVALUE) val; field = ARG_S_GetField(arg); fsiList = ARG_S_GetFsiList(arg); type = ARG_S_GetRightType(arg); flt = ARG_S_GetRightFloat(arg); val1 = ARG_S_GetRightValue(arg); equal = ARG_S_GetEqual(arg); pstrRes = ARG_S_GetResPStr(arg); if (SetStr_(&(sc->str),fsiList,flt,val1,equal,field) == NULL) return(NULL); *pstrRes = sc->str; if (sc->list) { DeleteList(sc->list); sc->list = NULL; } return(strType);}/* * Basic routine to deal with getting a string field */static void *GetStrFieldExtract_(char *str, void **arg,STRVALUE sc){ char **list; int max,sizeList; FSI_DECL; BorderType bt; char *str1,*str2,*str0; FSIList *fsiList; LWFLOAT *pFlt; char **pStr; char **list1,**list2; VALUE *pValue; fsiList = ARG_G_GetFsiList(arg); pFlt = ARG_G_GetResPFloat(arg); pStr = ARG_G_GetResPStr(arg); pValue = ARG_G_GetResPValue(arg); /* case of no extraction and no field */ if (fsiList == NULL) { *pStr = str; return(strType); } /* case of an empty extraction */ if (fsiList != NULL && fsiList->nx == 0) { *pValue = (VALUE) TNewStrValue(); return(strType); } if (fsiList->options & FSIOptStrBPer) bt = BorderPer; else if (fsiList->options & FSIOptStrBMir) bt = BorderMir; else if (fsiList->options & FSIOptStrBMir1) bt = BorderMir1; else bt = BorderNone; /* * Case the '*list' option is off */ if (!(fsiList->options & FSIOptStrList)) { /* Allocation of the result */ if (!(fsiList->options & (FSIOptStrBPer | FSIOptStrBMir | FSIOptStrBMir1))) *pStr = StrValueStrAlloc(fsiList->nx1); else *pStr = StrValueStrAlloc(fsiList->nx); /* Get the max size */ max = strlen(str); /* The loop in the case of *nolimit */ if (fsiList->options & FSIOptStrNoLimit) { FSI_FOR_START1(fsiList); if (fsi->type == FSIRange && fsi->val.r->step == 1) { if (RangeFirst(fsi->val.r) >= max || RangeLast(fsi->val.r) < 0) continue; memcpy((*pStr)+_k,str+(int) (MAX(RangeFirst(fsi->val.r),0)),((int) (MIN(RangeLast(fsi->val.r),max-1)-MAX(RangeFirst(fsi->val.r),0)+1))*sizeof(char)); _k+= (int) (MIN(RangeLast(fsi->val.r),max-1)-MAX(RangeFirst(fsi->val.r),0)+1); } else { FSI_FOR_START2(fsiList); if (_i<0 || _i > max-1) continue; (*pStr)[_k] = str[_i]; FSI_FOR_END2; } FSI_FOR_END1; } /* The loop in the generic case */ else { /* ????? AMELIORATION : utiliser memcpy pour les effets de bords aussi */ FSI_FOR_START1(fsiList); if (fsi->type == FSIRange && fsi->val.r->step == 1 && RangeFirst(fsi->val.r) >= 0 && RangeLast(fsi->val.r) < max) { memcpy((*pStr)+_k,str+(int) (RangeFirst(fsi->val.r)),((int) (RangeLast(fsi->val.r)-RangeFirst(fsi->val.r)+1))*sizeof(char)); _k+= (int) (MIN(RangeLast(fsi->val.r),max-1)-MAX(RangeFirst(fsi->val.r),0)+1); } else { FSI_FOR_START2(fsiList); switch (bt) { case BorderPer : (*pStr)[_k] = str[BPER(_i,max)]; break; case BorderMir : (*pStr)[_k] = str[BMIR(_i,max)]; break; case BorderMir1 : (*pStr)[_k] = str[BMIR1(_i,max)]; break; default : (*pStr)[_k] = str[_i]; } FSI_FOR_END2; } FSI_FOR_END1; } (*pStr)[_k] = '\0'; /* We want to return a STRVALUE so that we do not need to temp the string */ *pValue = (VALUE) NewNullStrValue(); ((STRVALUE) *pValue)->str = *pStr; TempValue(*pValue); *pStr = NULL; return(strType); } /* * Case the '*list' option is on */ else { /* Get the list and its size */ if (sc == NULL) { SetErrorf("*list option not yet implemented in this case... sorry!"); return(NULL); } list = GetListFromStrValue(sc); if (list == NULL) return(NULL); max = GetListSize(list);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -