tagz.cpp
资源名称:tcpmp.rar [点击查看]
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:16k
源码类别:
Windows CE
开发平台:
C/C++
- #include <string.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include "tagz.h"
- #ifdef TAGZ_UNICODE
- #define _TX(X) L##X
- #define t_strdup wcsdup
- #define t_strlen wcslen
- #define t_strnicmp wcsnicmp
- #define t_atoi(x) wcstol(x,0,10)
- #define t_stricmp wcsicmp
- #define t_strstr wcsstr
- #define sprintf swprintf
- #else
- #define _TX(X) X
- #define t_strdup strdup
- #define t_strlen strlen
- #define t_strnicmp strnicmp
- #define t_atoi atoi
- #define t_stricmp stricmp
- #define t_strstr strstr
- #endif
- #define TABSIZE(x) (sizeof(x)/sizeof(x[0]))
- class T_String
- {
- private:
- T_CHAR * data;
- UINT size,used;
- public:
- T_String() {data=0;size=0;used=0;}
- void AddChar(T_CHAR c)
- {
- if (!data)
- {
- data=(T_CHAR*)malloc((size=512)*sizeof(T_CHAR));
- used=0;
- }
- else if (size==used)
- {
- size<<=1;
- data=(T_CHAR*)realloc((char*)data,size*sizeof(T_CHAR));
- }
- if (data) data[used++]=c;
- }
- void AddInt(int i)
- {
- T_CHAR foo[16];
- sprintf(foo,_TX("%i"),i);
- AddString(foo);
- }
- void AddString(const T_CHAR * z)
- {
- while(*z) {AddChar(*z);z++;}
- }
- void AddString(T_String & s)
- {
- AddString(s.Peek());
- }
- ~T_String()
- {
- if (data) free(data);
- }
- T_CHAR * GetBuf()
- {
- if (!data) return ::t_strdup(_TX(""));
- T_CHAR * r=(T_CHAR*)realloc(data,(used+1)*sizeof(T_CHAR));
- r[used]=0;
- data=0;
- return r;
- }
- T_CHAR operator[](UINT i)
- {
- if (!data || i>=used) return 0;
- else return data[i];
- }
- UINT Len() {return data ? used : 0;}
- void Reset()
- {
- if (data) {free(data);data=0;}
- }
- const T_CHAR * Peek()
- {
- AddChar(0);
- used--;
- return data;
- }
- T_CHAR * strdup()
- {
- return ::t_strdup(Peek());
- }
- };
- static int separator(T_CHAR x)
- {
- if (!x || x==' ') return 1;
- if (x==''' || x=='_') return 0;
- #ifdef TAGZ_UNICODE
- return !iswalnum(x);
- #else
- return !isalnum(x);
- #endif
- }
- static int sepcmp(T_CHAR* src,T_CHAR* val)
- {
- UINT l=t_strlen(val);
- return !t_strnicmp(src,val,l) && separator(src[l]);
- }
- static char roman_num[]=
- {
- 'I','V','X','L','C','D','M'
- };
- static int is_roman(T_CHAR * ptr)/* could be more smart i think */
- {
- if (ptr[0]==']' && ptr[1]=='[' && separator(ptr[2])) return 1;
- while(!separator(*ptr))
- {
- UINT n;
- bool found=0;
- for(n=0;n<TABSIZE(roman_num);n++)
- {
- if (*ptr==roman_num[n]) {found=1;break;}
- }
- if (!found) return 0;
- ptr++;
- }
- return 1;
- }
- static int need_full(T_CHAR* ptr)
- {
- if (is_roman(ptr)) return 1;
- if (sepcmp(ptr,_TX("RPG"))) return 1;
- while(!separator(*ptr))
- {
- if (*ptr<'0' || *ptr>'9') return 0;
- ptr++;
- }
- return 1;
- }
- typedef bool (*TEXTFUNC)(UINT n_src,T_CHAR **src,UINT*,T_String &out);
- #define MAKEFUNC(X) static bool X(UINT n_src,T_CHAR ** src,UINT *found_src,T_String &out)
- MAKEFUNC(If)
- {
- if (n_src!=3) return false;
- out.AddString(src[found_src[0] ? 1 : 2]);
- return true;
- }
- MAKEFUNC(If2)
- {
- if (n_src!=2) return false;
- out.AddString(src[found_src[0] ? 0 : 1]);
- return true;
- }
- MAKEFUNC(Iflonger)
- {
- if (n_src!=4) return false;
- out.AddString(src[(int)t_strlen(src[0])>t_atoi(src[1]) ? 2 : 3]);
- return true;
- }
- MAKEFUNC(Ifgreater)
- {
- if (n_src!=4) return false;
- out.AddString(src[t_atoi(src[0])>t_atoi(src[1]) ? 2 : 3]);
- return true;
- }
- MAKEFUNC(Upper)
- {
- if (n_src!=1) return false;
- T_CHAR * s=src[0];
- while(*s)
- out.AddChar(toupper(*(s++)));
- return true;
- }
- MAKEFUNC(Lower)
- {
- if (n_src!=1) return false;
- T_CHAR * s=src[0];
- while(*s)
- out.AddChar(tolower(*(s++)));
- return true;
- }
- MAKEFUNC(Pad)
- {
- if (n_src<2 || n_src>3) return false;
- T_CHAR *fill=_TX(" ");
- if (n_src==3 && src[2][0])
- fill = src[2];
- int num = t_atoi(src[1]);
- T_CHAR *p = src[0];
- while (*p) { out.AddChar(*(p++)); num--; }
- UINT fl = t_strlen(fill);
- while (num>0)
- out.AddChar(fill[(--num)%fl]);
- return true;
- }
- MAKEFUNC(Cut)
- {
- if (n_src!=2) return false;
- UINT num = t_atoi(src[1]);
- T_CHAR *p = src[0];
- while (*p && num>0) {out.AddChar(*(p++));num--;}
- return true;
- }
- MAKEFUNC(PadCut)
- {
- if (n_src<2 || n_src>3) return false;
- T_CHAR *fill = _TX(" ");
- if (n_src==3 && src[2][0])
- fill = src[2];
- int num = t_atoi(src[1]);
- T_CHAR *p = src[0];
- while(*p && num>0) {out.AddChar(*(p++));num--;}
- UINT fl=t_strlen(fill);
- while (num>0)
- out.AddChar(fill[(--num)%fl]);
- return true;
- }
- /* abbr(string) */
- /* abbr(string,len) */
- MAKEFUNC(Abbr)
- {
- if (n_src==0 || n_src>2) return false;
- if (n_src==2 && (int)t_strlen(src[0])<t_atoi(src[1]))
- {
- out.AddString(src[0]);
- return true;
- }
- T_CHAR * meta=src[0];
- bool w=0, r=0;
- while(*meta)
- {
- bool an=!separator(*meta) || *meta==']' || *meta=='[';
- if (w && !an)
- w=0;
- else if (!w && an)
- {
- w=1;
- r=need_full(meta)?1:0;
- out.AddChar(*meta);
- }
- else if (w && r)
- out.AddChar(*meta);
- meta++;
- }
- return true;
- }
- MAKEFUNC(Caps)
- {
- if (n_src!=1) return false;
- T_CHAR* sp=src[0];
- int sep = 1;
- while(*sp)
- {
- T_CHAR c=*(sp++);
- int s = separator(c);
- if (!s && sep)
- c=toupper(c);
- else if (!sep) c=tolower(c);
- sep=s;
- out.AddChar(c);
- }
- return true;
- }
- MAKEFUNC(Caps2)
- {
- if (n_src!=1) return false;
- T_CHAR* sp=src[0];
- int sep=1;
- while(*sp)
- {
- T_CHAR c=*(sp++);
- int s = separator(c);
- if (!s && sep)
- c=toupper(c);
- sep=s;
- out.AddChar(c);
- }
- return true;
- }
- MAKEFUNC(Longest)
- {
- T_CHAR *ptr=0;
- UINT n, m=0;
- for(n=0;n<n_src;n++)
- {
- UINT l=t_strlen(src[n]);
- if (l>m) {m=l;ptr=src[n];}
- }
- if (ptr) out.AddString(ptr);
- return true;
- }
- MAKEFUNC(Shortest)
- {
- T_CHAR * ptr=0;
- UINT n,m=(UINT)(-1);
- for(n=0;n<n_src;n++)
- {
- UINT l=t_strlen(src[n]);
- if (l<m) {m=l;ptr=src[n];}
- }
- if (ptr) out.AddString(ptr);
- return true;
- }
- MAKEFUNC(Num)
- {
- if (n_src!=2) return false;
- T_CHAR tmp[16];
- T_CHAR tmp1[16];
- sprintf(tmp1,_TX("%%0%uu"),t_atoi(src[1]));
- sprintf(tmp,tmp1,t_atoi(src[0]));
- out.AddString(tmp);
- return true;
- }
- MAKEFUNC(Hex)
- {
- if (n_src!=2) return false;
- T_CHAR tmp[16];
- T_CHAR tmp1[16];
- sprintf(tmp1,_TX("%%0%ux"),t_atoi(src[1]));
- sprintf(tmp,tmp1,t_atoi(src[0]));
- out.AddString(tmp);
- return true;
- }
- MAKEFUNC(StrChr)
- {
- if (n_src!=2) return false;
- T_CHAR * p=src[0];
- T_CHAR s=src[1][0];
- while (*p && *p!=s) p++;
- if (*p==s)
- out.AddInt(1+p-src[0]);
- else out.AddChar('0');
- return true;
- }
- MAKEFUNC(StrRChr)
- {
- if (n_src!=2) return false;
- T_CHAR * p=src[0],*p1=0;
- T_CHAR s=src[1][0];
- while(*p)
- {
- if (*p==s) p1=p;
- p++;
- }
- if (p1)
- out.AddInt(1+p1-src[0]);
- else out.AddChar('0');
- return true;
- }
- MAKEFUNC(StrStr)
- {
- if (n_src!=2) return false;
- T_CHAR * p = t_strstr(src[0],src[1]);
- if (p)
- out.AddInt(1+p-src[0]);
- else out.AddChar('0');
- return true;
- }
- /* substr(string, index) */
- /* substr(string, index, length) */
- MAKEFUNC(SubStr)
- {
- if (n_src<2 || n_src>3) return false;
- int n1 = t_atoi(src[1]), n2;
- if (n_src == 3)
- n2 = t_atoi(src[2]);
- else n2 = n1;
- if (n1 < 1) n1=1;
- if (n2 >= n1)
- {
- n1--;
- n2--;
- while(n1<=n2 && src[0][n1])
- out.AddChar(src[0][n1++]);
- }
- return true;
- }
- MAKEFUNC(Len)
- {
- if (n_src!=1) return false;
- out.AddInt(t_strlen(src[0]));
- return true;
- }
- MAKEFUNC(Add)
- {
- UINT n;
- int s=0;
- for (n=0;n<n_src;n++)
- s+=t_atoi(src[n]);
- out.AddInt(s);
- return true;
- }
- MAKEFUNC(Sub)
- {
- if (n_src==0) return false;
- UINT n;
- int s=t_atoi(src[0]);
- for (n=1;n<n_src;n++)
- s-=t_atoi(src[n]);
- out.AddInt(s);
- return true;
- }
- MAKEFUNC(Mul)
- {
- UINT n;
- int s=1;
- for(n=0;n<n_src;n++)
- s*=t_atoi(src[n]);
- out.AddInt(s);
- return true;
- }
- MAKEFUNC(Div)
- {
- if (n_src==0) return false;
- UINT n;
- int s=t_atoi(src[0]);
- for(n=1;n<n_src;n++)
- {
- int t=t_atoi(src[n]);
- if (t) s/=t;
- else t=0;
- }
- out.AddInt(s);
- return true;
- }
- MAKEFUNC(Mod)
- {
- if (n_src==0) return false;
- UINT n;
- int s=t_atoi(src[0]);
- for(n=1;n<n_src;n++)
- {
- int t=t_atoi(src[n]);
- if (t) s%=t;
- else t=0;
- }
- out.AddInt(s);
- return true;
- }
- MAKEFUNC(Max)
- {
- if (!n_src) return false;
- int m = t_atoi(src[0]);
- UINT n;
- for (n=1; n<n_src; n++)
- {
- int t = t_atoi(src[n]);
- if (t > m) m = t;
- }
- out.AddInt(m);
- return true;
- }
- MAKEFUNC(Min)
- {
- if (!n_src) return false;
- int m=t_atoi(src[0]);
- UINT n;
- for(n=1;n<n_src;n++)
- {
- int t=t_atoi(src[n]);
- if (t<m) m=t;
- }
- out.AddInt(m);
- return true;
- }
- /* replace(string, what_to_replace, replacement) */
- MAKEFUNC(Replace)
- {
- if (n_src!=3) return false;
- T_CHAR *p = src[0];
- while (*p)
- {
- UINT n=0;
- while (src[1][n] && p[n]==src[1][n]) n++;
- if (!src[1][n])
- {
- out.AddString(src[2]);
- p += n;
- }
- else out.AddChar(*p++);
- }
- return true;
- }
- struct
- {
- TEXTFUNC func;
- const T_CHAR * name;
- }
- FUNCS[] =
- {
- If,_TX("if"),
- If2,_TX("if2"),
- Upper,_TX("upper"),
- Lower,_TX("lower"),
- Pad,_TX("pad"),
- Cut,_TX("cut"),
- PadCut,_TX("padcut"),
- Abbr,_TX("abbr"),
- Caps,_TX("caps"),
- Caps2,_TX("caps2"),
- Longest,_TX("longest"),
- Shortest,_TX("shortest"),
- Iflonger,_TX("iflonger"),
- Ifgreater,_TX("ifgreater"),
- Num,_TX("num"),Num,_TX("dec"),
- Hex,_TX("hex"),
- StrChr,_TX("strchr"),
- StrChr,_TX("strlchr"),
- StrRChr,_TX("strrchr"),
- StrStr,_TX("strstr"),
- SubStr,_TX("substr"),
- Len,_TX("len"),
- Add,_TX("add"),
- Sub,_TX("sub"),
- Mul,_TX("mul"),
- Div,_TX("div"),
- Mod,_TX("mod"),
- Min,_TX("min"),
- Max,_TX("max"),
- Replace,_TX("replace"),
- };
- class FMT
- {
- private:
- T_String str;
- T_CHAR * spec;
- TAGFUNC f;
- TAGFREEFUNC ff;
- void * fp;
- T_CHAR * org_spec;
- int found;
- void Error(T_CHAR *e=0)
- {
- str.Reset();
- str.AddString(e ? e : _TX("[SYNTAX ERROR IN FORMATTING STRING]"));
- found++; /* force displaying */
- }
- T_CHAR * _FMT(T_CHAR * s,UINT *f=0)
- {
- FMT fmt(this,s);
- T_CHAR * c=(T_CHAR*)fmt;
- if (f) *f=fmt.found;
- found+=fmt.found;
- return c;
- }
- static bool skipshit(T_CHAR** _p,T_CHAR *bl)
- {
- T_CHAR * p=*_p;
- int bc1=0,bc2=0;
- while(*p)
- {
- if (!bc1 && !bc2 && bl)
- {
- T_CHAR *z=bl;
- while(*z)
- {
- if (*z==*p) break;
- z++;
- }
- if (*z) break;
- }
- if (*p==''')
- {
- p++;
- while(*p && *p!=''') p++;
- if (!*p) return 0;
- }
- else if (*p=='(') bc1++;
- else if (*p==')')
- {
- if (--bc1<0) return 0;
- }
- else if (*p=='[') bc2++;
- else if (*p==']')
- {
- if (--bc2<0) return 0;
- }
- p++;
- }
- *_p=p;
- return *p && !bc1 && !bc2;
- }
- void run()
- {
- if (!spec) {Error();return;}
- while(*spec)
- {
- if (*spec=='%')
- {
- spec++;
- if (*spec=='%') {str.AddChar('%');spec++;continue;}
- T_CHAR* s1=spec+1;
- while(*s1 && *s1!='%') s1++;
- if (!*s1) {Error();break;}
- *s1=0;
- T_CHAR * tag=f(spec,fp);
- *s1='%';
- /*if (!tag) tag=tag_unknown; */
- if (tag && tag[0])
- {
- found++;
- str.AddString(tag);
- }
- else
- {
- str.AddString(_TX("?"));
- }
- if (tag && ff) ff(tag,fp);
- spec=s1+1;
- }
- else if (*spec=='$')
- {
- spec++;
- if (*spec=='$') {str.AddChar('$');spec++;continue;}
- T_CHAR * s1=spec+1;
- while(*s1 && *s1!='(') s1++;
- if (!*s1) {Error();break;}
- T_CHAR * s2=s1+1;
- if (!skipshit(&s2,_TX(")"))) {Error();break;}
- if (!*s2) {Error();break;};
- T_CHAR * p=s1+1;
- T_CHAR* temp[64];
- UINT temp_f[64];
- UINT nt=0;
- T_CHAR * p1=s1+1;
- while(p<=s2 && nt<64)
- {
- if (!skipshit(&p,_TX(",)"))) {Error();return;}
- if (p>s2 || (*p!=',' && *p!=')')) {Error(_TX("internal error"));return;}
- T_CHAR bk=*p;
- *p=0;
- temp[nt]=_FMT(p1,&temp_f[nt]);
- nt++;
- *p=bk;;
- p1=p+1;
- p++;
- }
- *s1=0;
- UINT n;
- for (n=0; n<TABSIZE(FUNCS); n++)
- if (!t_stricmp(spec, FUNCS[n].name))
- break;
- *s1='(';
- if (n != TABSIZE(FUNCS))
- {
- if (!FUNCS[n].func(nt, temp, temp_f, str))
- {
- Error(_TX("[INVALID $"));
- str.AddString(FUNCS[n].name);
- str.AddString(_TX(" SYNTAX]"));
- return;
- }
- }
- else
- {
- Error(_TX("[UNKNOWN FUNCTION]"));
- return;
- }
- for(n=0;n<nt;n++) free(temp[n]);
- spec=s2+1;
- }
- else if (*spec==''')
- {
- spec++;
- if (*spec==''') {str.AddChar(''');spec++;continue;}
- T_CHAR * s1=spec+1;
- while(*s1 && *s1!=''') s1++;
- if (!*s1) {Error();break;}
- *s1=0;
- str.AddString(spec);
- *s1=''';
- spec=s1+1;
- }
- else if (*spec=='[')
- {
- spec++;
- T_CHAR * s1=spec;
- UINT bc=0;
- if (!skipshit(&s1,_TX("]"))) {Error();break;}
- T_CHAR bk=*s1;
- *s1=0;
- FMT fmt(this,spec);
- fmt.run();
- if (fmt.found)
- {
- str.AddString(fmt.str);
- found+=fmt.found;
- }
- *s1=bk;
- spec=s1+1;
- }
- else if (*spec == ']') {Error();break;}
- else
- {
- str.AddChar(*spec);
- spec++;
- }
- }
- }
- FMT(FMT* base,T_CHAR * _spec)
- {
- found=0;
- org_spec=0;
- f=base->f;
- ff=base->ff;
- fp=base->fp;
- spec=_spec;
- }
- public:
- FMT(const T_CHAR * p_spec,TAGFUNC _f,TAGFREEFUNC _ff,void * _fp)
- {
- found=0;
- org_spec=spec=t_strdup(p_spec);
- f=_f;
- ff=_ff;
- fp=_fp;
- }
- operator T_CHAR*()
- {
- run();
- return str.GetBuf();
- }
- ~FMT()
- {
- if (org_spec) free(org_spec);
- }
- };
- extern "C"
- {
- UINT tagz_format(const T_CHAR * spec,TAGFUNC f,TAGFREEFUNC ff,void *fp,T_CHAR* out,UINT max)
- {
- T_CHAR * zz=tagz_format_r(spec,f,ff,fp);
- UINT r=0;
- while(r<max-1 && zz[r])
- {
- out[r]=zz[r];
- r++;
- }
- out[r]=0;
- free(zz);
- return r;
- }
- T_CHAR * tagz_format_r(const T_CHAR* spec,TAGFUNC f,TAGFREEFUNC ff,void * fp)
- {
- return FMT(spec,f,ff,fp);
- }
- const char tagz_manual[]="Syntax reference: n"
- "n"
- "* %tagname% - inserts field named <tagname>, eg. "%artist%"n"
- "* $abbr(x) - inserts abbreviation of x, eg. "$abbr(%album%)" - will convert album name of "Final Fantasy VI" to "FFVI"n"
- "* $abbr(x,y) - inserts abbreviation of x if x is longer than y characters; otherwise inserts full value of x, eg. "$abbr(%album%,10)"n"
- "* $lower(x), $upper(x) - converts x to in lower/uppercase, eg. "$upper(%title%)"n"
- "* $num(x,y) - displays x number and pads with zeros up to y characters (useful for track numbers), eg. $num(%tracknumber%,2)n"
- "* $caps(x) - converts first letter in every word of x to uppercase, and all other letters to lowercase, eg. "blah BLAH" -> "Blah Blah"n"
- "* $caps2(x) - similar to $caps, but leaves uppercase letters as they are, eg. "blah BLAH" -> "Blah BLAH"n"
- "* $if(A,B,C) - if A contains at least one valid tag, displays B, otherwise displays C; eg. "$if(%artist%,%artist%,unknown artist)" will display artist name if present; otherwise will display "unknown artist"; note that "$if(A,A,)" is equivalent to "[A]" (see below)n"
- "* $if2(A,B) - equals to $if(A,A,B)n"
- "* $longest(A,B,C,....) - compares lengths of output strings produced by A,B,C... and displays the longest one, eg. "$longest(%title%,%comment%)" will display either title if it's longer than comment; otherwise it will display commentn"
- "* $pad(x,y) - pads x with spaces up to y charactersn"
- "* $cut(x,y) - truncates x to y charactersn"
- "* $padcut(x,y) - pads x to y characters and truncates to y if longern"
- "* [ .... ] - displays contents of brackets only if at least one of fields referenced inside has been found, eg. "%artist% - [%album% / ]%title%" will hide [] block if album field is not presentn"
- "* ' (single quotation mark) - outputs raw text without parsing, eg, 'blah$blah%blah[][]' will output the contained string and ignore all reserved characters (%,$,[,]) in it; you can use this feature to insert square brackets for an example.n"
- "n"
- "eg. "[%artist% - ][$abbr(%album%,10)[ %tracknumber%] / ]%title%[ %streamtitle%]"n";
- }