192 lines
4.2 KiB
C
Executable File
192 lines
4.2 KiB
C
Executable File
/*****************************************************************************
|
|
*
|
|
* This program is 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; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* $Id: parser2.c 271 2005-08-09 08:31:35Z picard $
|
|
*
|
|
* The Core Pocket Media Player
|
|
* Copyright (c) 2004-2005 Gabor Kovacs
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "common.h"
|
|
|
|
void ParserDataFeed(parser* p,const void* Ptr,size_t Len)
|
|
{
|
|
BufferWrite(&p->Buffer,Ptr,Len,4096);
|
|
}
|
|
|
|
void ParserStream(parser* p, stream* Stream)
|
|
{
|
|
p->Stream = Stream;
|
|
if (Stream)
|
|
{
|
|
if (!p->Buffer.Data)
|
|
{
|
|
BufferAlloc(&p->Buffer,4096,1);
|
|
BufferStream(&p->Buffer,p->Stream);
|
|
}
|
|
}
|
|
else
|
|
BufferClear(&p->Buffer);
|
|
}
|
|
|
|
const uint8_t* ParserPeek(parser* p, size_t Len)
|
|
{
|
|
if (p->Buffer.WritePos < p->Buffer.ReadPos+(int)Len) //buffer!
|
|
{
|
|
BufferStream(&p->Buffer,p->Stream);
|
|
if (p->Buffer.WritePos < p->Buffer.ReadPos+(int)Len) //buffer!
|
|
return NULL;
|
|
}
|
|
return p->Buffer.Data + p->Buffer.ReadPos;
|
|
}
|
|
|
|
static void SkipSpace(parser* p)
|
|
{
|
|
const uint8_t* i;
|
|
while ((i = ParserPeek(p,1))!=NULL)
|
|
{
|
|
if (!IsSpace(*i) && *i!=10 && *i!=13)
|
|
break;
|
|
++p->Buffer.ReadPos;
|
|
}
|
|
}
|
|
|
|
static bool_t SkipAfter(parser* p, char ch)
|
|
{
|
|
const char* i;
|
|
while ((i = (const char*)ParserPeek(p,1))!=NULL)
|
|
{
|
|
++p->Buffer.ReadPos;
|
|
if (*i == ch)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool_t ParserIsToken(parser* p, const tchar_t* Token)
|
|
{
|
|
size_t n = tcslen(Token);
|
|
tchar_t* Tmp = alloca(sizeof(tchar_t)*(n+1));
|
|
const char* i;
|
|
|
|
SkipSpace(p);
|
|
if ((i=(const char*)ParserPeek(p,n))!=NULL)
|
|
{
|
|
GetAsciiToken(Tmp,n+1,i,n);
|
|
if (tcsicmp(Tmp,Token)==0)
|
|
{
|
|
p->Buffer.ReadPos += n;
|
|
return 1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int Read(parser* p, tchar_t* Out, int OutLen, const char* Delimiter, bool_t Keep)
|
|
{
|
|
char* s = alloca(OutLen);
|
|
int n=0;
|
|
|
|
while (ParserPeek(p,1))
|
|
{
|
|
char ch = p->Buffer.Data[p->Buffer.ReadPos++];
|
|
if (strchr(Delimiter,ch))
|
|
{
|
|
if (Keep)
|
|
--p->Buffer.ReadPos;
|
|
goto readok;
|
|
}
|
|
else
|
|
if (ch!=13 && ++n<OutLen)
|
|
s[n-1] = ch;
|
|
}
|
|
if (!n)
|
|
return -1;
|
|
|
|
readok:
|
|
if (OutLen>0)
|
|
{
|
|
s[min(n,OutLen-1)]=0;
|
|
StrToTcs(Out,OutLen,s);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
bool_t ParserLine(parser* p, tchar_t* Out, size_t OutLen)
|
|
{
|
|
return Read(p,Out,OutLen,"\n",0)>=0;
|
|
}
|
|
|
|
bool_t ParserIsElement(parser* p, tchar_t* Name, size_t NameLen)
|
|
{
|
|
if (!SkipAfter(p,'<'))
|
|
return 0;
|
|
if (ParserIsToken(p,T("/")) && NameLen>0)
|
|
{
|
|
*(Name++) = '/';
|
|
--NameLen;
|
|
}
|
|
return Read(p,Name,NameLen," \t\n/>",1)>0;
|
|
}
|
|
|
|
void ParserElementSkip(parser *p)
|
|
{
|
|
while (ParserIsAttrib(p,NULL,0))
|
|
ParserAttribSkip(p);
|
|
}
|
|
|
|
bool_t ParserElementContent(parser* p, tchar_t* Out, size_t OutLen)
|
|
{
|
|
ParserElementSkip(p);
|
|
return Read(p,Out,OutLen,"<",1)>=0;
|
|
}
|
|
|
|
bool_t ParserIsAttrib(parser* p, tchar_t* Name, size_t NameLen)
|
|
{
|
|
SkipSpace(p);
|
|
if (ParserIsToken(p,T(">")) || ParserIsToken(p,T("/>")))
|
|
return 0;
|
|
return Read(p,Name,NameLen,"= \t\n/>",1)>0;
|
|
}
|
|
|
|
int ParserAttribInt(parser* p)
|
|
{
|
|
tchar_t Token[MAXTOKEN];
|
|
if (!ParserAttribString(p,Token,MAXTOKEN))
|
|
return 0;
|
|
if (Token[0]=='0' && Token[1]=='x')
|
|
return StringToInt(Token+2,1);
|
|
else
|
|
return StringToInt(Token,0);
|
|
}
|
|
|
|
bool_t ParserAttribString(parser* p, tchar_t* Out, size_t OutLen)
|
|
{
|
|
if (!ParserIsToken(p,T("=")))
|
|
return 0;
|
|
SkipSpace(p);
|
|
if (ParserIsToken(p,T("\"")))
|
|
return Read(p,Out,OutLen,"\"",0)>=0;
|
|
else
|
|
return Read(p,Out,OutLen," \t\n/>",1)>=0;
|
|
}
|
|
|
|
void ParserAttribSkip(parser* p)
|
|
{
|
|
ParserAttribString(p,NULL,0);
|
|
}
|