⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlparser.cpp

📁 俄罗斯人开发的大名鼎鼎的Pocket Pc 阅读器haaliread的源代码,visual c
💻 CPP
📖 第 1 页 / 共 4 页
字号:
      f.str=m_buffer.Get(len);
      memcpy((wchar_t*)f.str,text,len*sizeof(wchar_t));
      f.attr|=LOCAL;
    } else {
      f.len=XML_GetCurrentByteCount(m_parser);
      f.fpos=XML_GetCurrentByteIndex(m_parser);
    }
    m_frags.Add(f);
  }
}

// expat callbacks
void	  XMLParserImp::StartElementCB(void *udata,const wchar_t *name,
				       const wchar_t **attr)
{
  ((XMLParserImp*)udata)->StartElement(name,attr);
}

void	  XMLParserImp::EndElementCB(void *udata,const wchar_t *name) {
  ((XMLParserImp*)udata)->EndElement(name);
}

void	  XMLParserImp::CharDataCB(void *udata,const wchar_t *text,int len) {
  ((XMLParserImp*)udata)->CharData(text,len);
}

void	  XMLParserImp::StartCDataCB(void *udata) {
  ((XMLParserImp*)udata)->m_ps->attr|=CDATA;
}

void	  XMLParserImp::EndCDataCB(void *udata) {
  ((XMLParserImp*)udata)->m_ps->attr&=~CDATA;
}

int XMLParserImp::UnknownEncodingCB(void *data,const wchar_t *name,
				    XML_Encoding *info)
{
  int	cp=Unicode::FindCodePage(Unicode::ToCS(name,wcslen(name)));
  const wchar_t	*tab=NULL;
  if (cp>=0)
    tab=Unicode::GetTable(cp);
  if (!tab)
    return 0;
  info->data=NULL;
  info->convert=NULL;
  info->release=NULL;
  for (int i=0;i<256;++i)
    info->map[i]=tab[i];
  ((XMLParserImp*)data)->m_encoding=cp;
  return 1;
}

bool	  XMLParserImp::ParseFile(int encoding) {
  XML_Memory_Handling_Suite  xmm={ my_malloc, my_realloc, my_free };
  xmm.priv=(void*)m_heap;

  ParseState	    pstate;
  memset(&pstate,0,sizeof(pstate));
  m_ps=&pstate;
  FmtArray	    docstyles;
  docstyles.SetSize(0,64);
  WMap		    docstylemap(m_heap,true);
  pstate.styles=&docstyles;
  pstate.stylemap=&docstylemap;

  SP_State	    spstate;
  m_sps=&spstate;

  const wchar_t	*enc=NULL;
  if (encoding>=0) {
    enc=Unicode::GetCodePageNameW(encoding);
    if (!enc)
      encoding=-1;
  }
  if (!(m_parser=XML_ParserCreate_MM(enc,&xmm,L"|")))
    return false;
  XML_SetElementHandler(m_parser,XMLParserImp::StartElementCB,
    XMLParserImp::EndElementCB);
  XML_SetCharacterDataHandler(m_parser,XMLParserImp::CharDataCB);
  XML_SetCdataSectionHandler(m_parser,StartCDataCB,EndCDataCB);
  XML_SetUnknownEncodingHandler(m_parser,XMLParserImp::UnknownEncodingCB,this);
  XML_SetUserData(m_parser,this);
  m_encoding=-1;
  // now suck in the file
  m_fp->seek(0);
  switch (setjmp(pstate.jout)) {
  case 0:
    for (;;) {
      void    *buf=(char*)XML_GetBuffer(m_parser,RFile::BSZ);
      if (!buf) {
	CTVApp::Barf(_T("XML parser: Out of memory"));
	goto fail;
      }
      int	    nr=m_fp->read(buf,RFile::BSZ);
      if (!XML_ParseBuffer(m_parser,nr,nr<RFile::BSZ)) {
	CTVApp::Barf(
  #ifdef UNICODE
	  _T("XML parse error: %s at line %d, column %d"),
  #else
	  _T("XML parse error: %S at line %d, column %d"),
  #endif
	  XML_ErrorString(XML_GetErrorCode(m_parser)),
	  XML_GetCurrentLineNumber(m_parser),XML_GetCurrentColumnNumber(m_parser)+1);
	goto fail;
      }
      if (nr<RFile::BSZ)
	break;
    }
    break;
  case ERR_NOTFB2:
    CTVApp::Barf(_T("Not a FictionBook2 document"));
    goto fail;
  }
  if (m_docs.GetSize()>0) {
    Document    d;
    d.start=0;
    d.length=m_docs[0].start-1;
    d.name=_T("#Description");
    m_docs.Add(d);
  }
  return true;
fail:
  //XML_ParserFree(m_parser);
  // parser is now destroyed in the XMLParserImp destructor
  return false;
}

XMLParser *XMLParser::MakeParser(Meter *m,CBufFile *fp,Bookmarks *bmk,HANDLE heap) {
  return new XMLParserImp(m,fp,bmk,heap);
}

void	  XMLParserImp::ParseStylesheet(const wchar_t *text,int len) {
  wchar_t   ch;
  while (len--) {
    ch=*text++;
    switch (m_sps->state) {
    case SP_State::START:
      if (!iswspace(ch)) {
	m_sps->NAdd(ch);
	m_sps->state=SP_State::NAME;
      }
      break;
    case SP_State::NAME:
      if (!iswspace(ch))
	m_sps->NAdd(ch);
      else
	m_sps->state=SP_State::FLAGS;
      break;
    case SP_State::FLAGS:
flags:
      switch (ch) {
      case L'b':
	m_sps->format.bold=1;
	break;
      case L'B':
	m_sps->format.bold=0;
	break;
      case L'i':
	m_sps->format.italic=1;
	break;
      case L'I':
	m_sps->format.italic=0;
	break;
      case L'u':
	m_sps->format.underline=1;
	break;
      case L'U':
	m_sps->format.underline=0;
	break;
      case L'r':
	m_sps->format.align=Paragraph::right;
	break;
      case L'c':
	m_sps->format.align=Paragraph::center;
	break;
      case L'j':
	m_sps->format.align=Paragraph::justify;
	break;
      case L'l':
	m_sps->format.align=0;
	break;
      case L'h':
	m_sps->state=SP_State::COLOR;
	m_sps->num=0; m_sps->sign=false;
	break;
      case L'L':
	m_sps->state=SP_State::LM;
	m_sps->num=0; m_sps->sign=false;
	break;
      case L'R':
	m_sps->state=SP_State::RM;
	m_sps->num=0; m_sps->sign=false;
	break;
      case L'F':
	m_sps->state=SP_State::FM;
	m_sps->num=0; m_sps->sign=false;
	break;
      case L'S':
	m_sps->state=SP_State::SIZE;
	m_sps->num=0; m_sps->sign=false;
	break;
      case L';':
	m_sps->stylename[m_sps->stylenameptr]=L'\0';
	m_ps->stylemap->AddCopy(m_sps->stylename,(void*)m_ps->styles->GetSize());
	m_ps->styles->Add(m_sps->format);
	m_sps->Init();
	break;
      }
      break;
    case SP_State::FM:
    case SP_State::LM:
    case SP_State::RM:
    case SP_State::SIZE:
    case SP_State::COLOR:
      if (iswdigit(ch)) {
	m_sps->num=m_sps->num*10+ch-L'0';
      } else if (ch=='-') 
	m_sps->sign=1;
      else { // end of spec
	int   val=m_sps->num;
	if (m_sps->sign)
	  val=-val;
	switch (m_sps->state) {
	case SP_State::FM:
	  val=RClamp(val,-100,100);
	  m_sps->format.findent=val;
	  break;
	case SP_State::LM:
	  val=RClamp(val,-100,100);
	  m_sps->format.lindent=val;
	  break;
	case SP_State::RM:
	  val=RClamp(val,-100,100);
	  m_sps->format.rindent=val;
	  break;
	case SP_State::COLOR:
	  val=RClamp(val,0,7);
	  m_sps->format.color=val;
	  break;
	case SP_State::SIZE:
	  val=RClamp(val,-100,100);
	  m_sps->format.fsz=val;
	  break;
	}
	m_sps->state=SP_State::FLAGS;
	goto flags;
      }
      break;
    }
  }
}

void XMLParser::SaveStyles() {
  for (int i=0;i<g_eformat.GetSize();++i)
    if (g_eformat[i].name.GetLength() && g_eformat[i].name[0]!=_T('*')) {
      CString	str;
      str.Format(_T("%d,%d,%d,%d,%d,%d,%d,%d,%d"),
	g_eformat[i].fsz,
	g_eformat[i].bold,
	g_eformat[i].italic,
	g_eformat[i].underline,
	g_eformat[i].color,
	g_eformat[i].align,
	g_eformat[i].lindent,
	g_eformat[i].rindent,
	g_eformat[i].findent);
      AfxGetApp()->WriteProfileString(_T("Styles"),g_eformat[i].name,str);
    }
}


static void AddElement(const wchar_t *name,int namelen,int id) {
  wchar_t   buf[128];
  wcscpy(buf,FB_NS);
  buf[FB_NS_LEN]=L'|';
  if (namelen>sizeof(buf)/sizeof(wchar_t)-2-FB_NS_LEN)
    namelen=sizeof(buf)/sizeof(wchar_t)-2-FB_NS_LEN;
  wcsncpy(buf+FB_NS_LEN+1,name,namelen);
  buf[FB_NS_LEN+1+namelen]=L'\0';
  g_elements->AddCopy(buf,(void*)id);
  g_elements->AddCopy(buf+FB_NS_LEN,(void*)id);
  g_elements->AddCopy(buf+FB_NS_LEN+1,(void*)id);
}

static inline int FLAG(wchar_t x) {
  return x==L'+' ? 1 : x==L'-' ? 0 : XMLParser::ElemFmt::NOCHG;
}

static void ParseXMLSettings(const wchar_t *fmt,DWORD sz) {
  const wchar_t  *p=fmt;
  const wchar_t  *e=fmt+sz;
  const wchar_t  *le;
  wchar_t	 *q;

  if (p<e && *p==0xFEFF)
    ++p;
  while (p<e) {
    for (le=p;le<e && *le!=L'\r' && *le!=L'\n';++le) ;
    // process line here
    if (p!=le && *p!=L'#' && *p!=L' ' && *p!=L'\t') {
      XMLParser::ElemFmt	fe;
      wchar_t			*name=NULL;
      int			size;
      wchar_t			bold,italic,underline;
      int			color;
      wchar_t			align;
      int			leftm,rightm,firstm;
      wchar_t			*action=NULL,*elements=NULL;
      int			fields;
      if (Scan::xscanf(p,le-p,L"%S %-100,100,127d "
			L"%c %c %c %0,8,127d %c %-100,100,127d "
			L"%-100,100,127d %-100,100,127d %S %S",NULL,&fields,
			&name,&size,&bold,&italic,&underline,
			&color,&align,&leftm,&rightm,&firstm,
			&action,&elements)==0 && fields==12)
      {
	for (q=name;*q;++q)
	  if (*q==L'_')
	    *q=L' ';
	fe.name=name;
	fe.fsz=size;
	fe.bold=FLAG(bold);
	fe.italic=FLAG(italic);
	fe.underline=FLAG(underline);
	fe.color=color;
	switch (align) {
	case 'R':
	  fe.align=Paragraph::right;
	  break;
	case 'C':
	  fe.align=Paragraph::center;
	  break;
	case 'J':
	  fe.align=Paragraph::justify;
	  break;
	default:
	  fe.align=XMLParser::ElemFmt::NOCHG;
	  break;
	}
	fe.lindent=leftm;
	fe.rindent=rightm;
	fe.findent=firstm;
	fe.flags=0;
	for (q=action;*q;++q) {
	  const TCHAR *fp=XMLParser::ElemFmt::flag_names;
	  for (int flags=1;*fp;flags<<=1,++fp)
	    if (*fp==*q) {
	      fe.flags|=flags;
	      break;
	    }
	}
	for (p=elements;*p;) {
	  const wchar_t *q; // XXX
	  for (q=p;*q && *q!=L',';++q) ;
	  if (q!=p)
	    AddElement(p,q-p,g_eformat.GetSize());
	  p=q;
	  if (*p==L',')
	    ++p;
	}
	// ok, insert it now
	g_eformat.Add(fe);
      }
      delete[] name;
      delete[] action;
      delete[] elements;
    }
    // skip end of line
    for (p=le;p<e && (*p=='\r' || *p=='\n');++p) ;
  }
}

void XMLParser::LoadStyles() {
  ElemFmt ef;
  // delete all elements
  g_eformat.RemoveAll();
  delete g_elements;
  g_elements=new WMap(GetProcessHeap(),true);
  // always initialize a default element
  ef.Clear();
  g_eformat.Add(ef);
  // read parser settings from a resource
  HMODULE hMod=AfxGetResourceHandle();
  HRSRC	  hRes=FindResource(hMod,_T("xml_elements"),RT_RCDATA);
  if (hRes) {
    DWORD   rsize=SizeofResource(hMod,hRes);
    HGLOBAL hGlob=LoadResource(hMod,hRes);
    if (hGlob) {
      void  *res=LockResource(hGlob);
      if (res) {
	ParseXMLSettings((const wchar_t *)res,rsize/sizeof(wchar_t));
	UnlockResource(hGlob);
      }
      FreeResource(hGlob);
    }
  }
  // adjust formatting from registry
  for (int fnum=0;fnum<g_eformat.GetSize();++fnum)
    if (g_eformat[fnum].name.GetLength()>0 && g_eformat[fnum].name[0]!=_T('*')) {
      CString	str=AfxGetApp()->GetProfileString(_T("Styles"),g_eformat[fnum].name);
      int	f,b,i,c,a,li,ri,fi,u;
      if (_stscanf(str,_T("%d,%d,%d,%d,%d,%d,%d,%d,%d"),&f,&b,&i,&u,&c,&a,&li,&ri,&fi)==9) {
	g_eformat[fnum].fsz=f;
	g_eformat[fnum].bold=b;
	g_eformat[fnum].italic=i;
	g_eformat[fnum].underline=u;
	g_eformat[fnum].color=c;
	g_eformat[fnum].align=a;
	g_eformat[fnum].lindent=li;
	g_eformat[fnum].rindent=ri;
	g_eformat[fnum].findent=fi;
      }
    }
}

XMLParser::FmtArray&  XMLParser::GetXMLStyles() {
  return g_eformat;
}

void	XMLParser::ElemFmt::Clear() {
    fsz=NOCHG;
    bold=NOCHG;
    italic=NOCHG;
    color=NOCHG;
    align=NOCHG;
    underline=NOCHG;
    flags=0;
    lindent=NOCHG;
    rindent=NOCHG;
    findent=NOCHG;
    name.Empty();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -