diff src/win32/7zip/7z/CPP/Common/MyXml.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/Common/MyXml.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,209 @@
     1.4 +// MyXml.cpp
     1.5 +
     1.6 +#include "StdAfx.h"
     1.7 +
     1.8 +#include "MyXml.h"
     1.9 +
    1.10 +static bool IsValidChar(char c)
    1.11 +{
    1.12 +  return
    1.13 +    c >= 'a' && c <= 'z' ||
    1.14 +    c >= 'A' && c <= 'Z' ||
    1.15 +    c >= '0' && c <= '9' ||
    1.16 +    c == '-';
    1.17 +}
    1.18 +
    1.19 +static bool IsSpaceChar(char c)
    1.20 +{
    1.21 +  return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A);
    1.22 +}
    1.23 +
    1.24 +#define SKEEP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++;
    1.25 +
    1.26 +static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop)
    1.27 +{
    1.28 +  prop.Name.Empty();
    1.29 +  prop.Value.Empty();
    1.30 +  for (; pos < s.Length(); pos++)
    1.31 +  {
    1.32 +    char c = s[pos];
    1.33 +    if (!IsValidChar(c))
    1.34 +      break;
    1.35 +    prop.Name += c;
    1.36 +  }
    1.37 +  
    1.38 +  if (prop.Name.IsEmpty())
    1.39 +    return false;
    1.40 +
    1.41 +  SKEEP_SPACES(s, pos);
    1.42 +  if (s[pos++] != '=')
    1.43 +    return false;
    1.44 +
    1.45 +  SKEEP_SPACES(s, pos);
    1.46 +  if (s[pos++] != '\"')
    1.47 +    return false;
    1.48 +  
    1.49 +  while (pos < s.Length())
    1.50 +  {
    1.51 +    char c = s[pos++];
    1.52 +    if (c == '\"')
    1.53 +      return true;
    1.54 +    prop.Value += c;
    1.55 +  }
    1.56 +  return false;
    1.57 +}
    1.58 +
    1.59 +int CXmlItem::FindProperty(const AString &propName) const
    1.60 +{
    1.61 +  for (int i = 0; i < Props.Size(); i++)
    1.62 +    if (Props[i].Name == propName)
    1.63 +      return i;
    1.64 +  return -1;
    1.65 +}
    1.66 +
    1.67 +AString CXmlItem::GetPropertyValue(const AString &propName) const
    1.68 +{
    1.69 +  int index = FindProperty(propName);
    1.70 +  if (index >= 0)
    1.71 +    return Props[index].Value;
    1.72 +  return AString();
    1.73 +}
    1.74 +
    1.75 +bool CXmlItem::IsTagged(const AString &tag) const
    1.76 +{
    1.77 +  return (IsTag && Name == tag);
    1.78 +}
    1.79 +
    1.80 +int CXmlItem::FindSubTag(const AString &tag) const
    1.81 +{
    1.82 +  for (int i = 0; i < SubItems.Size(); i++)
    1.83 +    if (SubItems[i].IsTagged(tag))
    1.84 +      return i;
    1.85 +  return -1;
    1.86 +}
    1.87 +
    1.88 +AString CXmlItem::GetSubString() const
    1.89 +{
    1.90 +  if (SubItems.Size() == 1)
    1.91 +  {
    1.92 +    const CXmlItem &item = SubItems[0];
    1.93 +    if (!item.IsTag)
    1.94 +      return item.Name;
    1.95 +  }
    1.96 +  return AString();
    1.97 +}
    1.98 +
    1.99 +AString CXmlItem::GetSubStringForTag(const AString &tag) const
   1.100 +{
   1.101 +  int index = FindSubTag(tag);
   1.102 +  if (index >= 0)
   1.103 +    return SubItems[index].GetSubString();
   1.104 +  return AString();
   1.105 +}
   1.106 +
   1.107 +bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels)
   1.108 +{
   1.109 +  if (numAllowedLevels == 0)
   1.110 +    return false;
   1.111 +  SubItems.Clear();
   1.112 +  AString finishString = "</";
   1.113 +  for (;;)
   1.114 +  {
   1.115 +    SKEEP_SPACES(s, pos);
   1.116 +
   1.117 +    if (s.Mid(pos, finishString.Length()) == finishString)
   1.118 +      return true;
   1.119 +      
   1.120 +    CXmlItem item;
   1.121 +    if (!item.ParseItem(s, pos, numAllowedLevels - 1))
   1.122 +      return false;
   1.123 +    SubItems.Add(item);
   1.124 +  }
   1.125 +}
   1.126 +
   1.127 +bool CXmlItem::ParseItem(const AString &s, int &pos, int numAllowedLevels)
   1.128 +{
   1.129 +  SKEEP_SPACES(s, pos);
   1.130 +
   1.131 +  int pos2 = s.Find('<', pos);
   1.132 +  if (pos2 < 0)
   1.133 +    return false;
   1.134 +  if (pos2 != pos)
   1.135 +  {
   1.136 +    IsTag = false;
   1.137 +    Name += s.Mid(pos, pos2 - pos);
   1.138 +    pos = pos2;
   1.139 +    return true;
   1.140 +  }
   1.141 +  IsTag = true;
   1.142 +
   1.143 +  pos++;
   1.144 +  SKEEP_SPACES(s, pos);
   1.145 +
   1.146 +  for (; pos < s.Length(); pos++)
   1.147 +  {
   1.148 +    char c = s[pos];
   1.149 +    if (!IsValidChar(c))
   1.150 +      break;
   1.151 +    Name += c;
   1.152 +  }
   1.153 +  if (Name.IsEmpty() || pos == s.Length())
   1.154 +    return false;
   1.155 +
   1.156 +  int posTemp = pos;
   1.157 +  for (;;)
   1.158 +  {
   1.159 +    SKEEP_SPACES(s, pos);
   1.160 +    if (s[pos] == '/')
   1.161 +    {
   1.162 +      pos++;
   1.163 +      // SKEEP_SPACES(s, pos);
   1.164 +      return (s[pos++] == '>');
   1.165 +    }
   1.166 +    if (s[pos] == '>')
   1.167 +    {
   1.168 +      if (!ParseItems(s, ++pos, numAllowedLevels))
   1.169 +        return false;
   1.170 +      AString finishString = AString("</") + Name + AString(">");
   1.171 +      if (s.Mid(pos, finishString.Length()) != finishString)
   1.172 +        return false;
   1.173 +      pos += finishString.Length();
   1.174 +      return true;
   1.175 +    }
   1.176 +    if (posTemp == pos)
   1.177 +      return false;
   1.178 +
   1.179 +    CXmlProp prop;
   1.180 +    if (!ReadProperty(s, pos, prop))
   1.181 +      return false;
   1.182 +    Props.Add(prop);
   1.183 +    posTemp = pos;
   1.184 +  }
   1.185 +}
   1.186 +
   1.187 +bool SkeepHeader(const AString &s, int &pos, const AString &startString, const AString &endString)
   1.188 +{
   1.189 +  SKEEP_SPACES(s, pos);
   1.190 +  if (s.Mid(pos, startString.Length()) == startString)
   1.191 +  {
   1.192 +    pos = s.Find(endString, pos);
   1.193 +    if (pos < 0)
   1.194 +      return false;
   1.195 +    pos += endString.Length();
   1.196 +    SKEEP_SPACES(s, pos);
   1.197 +  }
   1.198 +  return true;
   1.199 +}
   1.200 +
   1.201 +bool CXml::Parse(const AString &s)
   1.202 +{
   1.203 +  int pos = 0;
   1.204 +  if (!SkeepHeader(s, pos, "<?xml", "?>"))
   1.205 +    return false;
   1.206 +  if (!SkeepHeader(s, pos, "<!DOCTYPE", ">"))
   1.207 +    return false;
   1.208 +  if (!Root.ParseItem(s, pos, 1000))
   1.209 +    return false;
   1.210 +  SKEEP_SPACES(s, pos);
   1.211 +  return (pos == s.Length() && Root.IsTag);
   1.212 +}