string ParseString(ref int pos) { text.Clear(); int p = pos; bool esc = false; for (;;) { if (p >= length - 1) { throw ParserEx; } int b = this[++p]; if (esc) { text.Add(b == '"' ? '"' : b == '\\' ? '\\' : b == 'b' ? '\b' : b == 'f' ? '\f' : b == 'n' ? '\n' : b == 'r' ? '\r' : b == 't' ? '\t' : (char)0); esc = !esc; } else { if (b == '\\') { esc = !esc; } else if (b == '"') { pos = p; return(text.ToString()); } else { text.Accept(b); } } } }
string ParseName(ref int pos) { text.Clear(); int p = pos; for (;;) { if (p >= length) { return(null); } int b = this[p++]; if (b == '=') { pos = p; return(text.ToString()); } else if (b == '+') { text.Accept(' '); } else if (b == '%') // percent-encoding %xy { if (p >= length) { throw ParserEx; } int x = this[p++]; if (p >= length) { throw ParserEx; } int y = this[p++]; text.Accept(Dv(x) << 4 | Dv(y)); } else { text.Accept(b); } } }
public Form Parse() { // locality for performance byte[] bound_ = this.bound; byte[] buffer_ = this.buffer; int length_ = this.length; // UTF-8 header builder HeaderText hdr = new HeaderText(128); Text text = new Text(128); // keep local for speed int boundlen = bound_.Length; // shall init lately Form frm = null; int p = 0; // skip first bound line whatever for (;;) { if (buffer_[p++] == '\r' && buffer_[p++] == '\n') { break; } } // parse parts for (;;) { string name = null; string filename = null; string ctype = null; // parse headers for (;;) { hdr.Clear(); // parse a header line for (;;) { if (p >= length_ - 2) { throw ParserEx; } byte b; if ((b = buffer_[p++]) == '\r' && buffer_[p++] == '\n') { break; } hdr.Accept(b); // lineup the byte } if (hdr.Count == 0) // if empty line then quit header section { break; } if (name == null && hdr.Check("Content-Disposition")) { name = hdr.SeekParameter("name"); filename = hdr.SeekParameter("filename"); } else if (ctype == null && hdr.Check("Content-Type")) { ctype = hdr.GetVvalue(); } } // get part's content text.Clear(); bool plain = ctype == null || "text/plain".Equals(ctype); int start = p; // mark down content start int idx = 0; // index on bound for (;;) { byte b = buffer_[p++]; if (b == bound_[idx]) { idx++; if (idx >= boundlen) // fully matched the bound accumulatively { if (frm == null) { frm = new Form(true) { Buffer = buffer_ } } ; if (plain) { frm.Add(name, text.ToString()); } else { frm.Add(name, filename, start, p - start - boundlen); } // goto the ending CRLF/-- check break; } } else if (idx > 0) // if fail-match { if (plain) // re-add { for (int i = 0; i < idx; i++) { text.Accept(bound_[i]); } } idx = 0; // reset } else { if (plain) { text.Accept(b); } } } // check if any more part if (buffer_[p++] == '\r' && buffer_[p++] == '\n') { continue; } break; } // parts return(frm ?? Empty); } }
XElem ParseElem(ref int pos, int startchar) { int p = pos; int b; // parse element tag name text.Clear(); text.Accept(startchar); while (IsNameChar(b = this[++p])) { text.Accept(b); // to comprise start tag } string tag = text.ToString(); XElem elem = new XElem(tag); // optionally parse attributes while (IsWs(b)) { while (IsWs(b = this[++p])) { } // skip ws if (IsNameStartChar(b)) { // attribute name text.Clear(); text.Accept(b); while ((b = this[++p]) != '=') { text.Accept(b); } string name = text.ToString(); // attribute value if (this[++p] != '"') { throw ParserEx; // left quote } text.Clear(); while ((b = this[++p]) != '"') // till right quote { if (b == '&') // escape < > & " { int b1 = this[p + 1]; int b2 = this[p + 2]; int b3 = this[p + 3]; if (b1 == 'l' && b2 == 't' && b3 == ';') { b = '<'; p += 3; } else if (b1 == 'g' && b2 == 't' && b3 == ';') { b = '>'; p += 3; } else if (b1 == 'a' && b2 == 'm' && b3 == 'p' && this[p + 4] == ';') { b = '&'; p += 4; } else if (b1 == 'q' && b2 == 'u' && b3 == 'o' && this[p + 4] == 't' && this[p + 5] == ';') { b = '"'; p += 5; } } text.Accept(b); } string value = text.ToString(); elem.AddAttr(name, value); b = this[++p]; // step } } // end of attributes if (b == '>') // a start tag just finished, expecting the ending-tag { for (;;) // child nodes iteration { while (IsWs(b = this[++p])) // skip ws { } if (b == '<') { b = this[++p]; if (b == '/') // the ending tag { // consume text.Clear(); while ((b = this[++p]) != '>') { text.Accept(b); } if (!text.Equals(tag)) { throw ParserEx; } pos = p; // adjust current position return(elem); } else if (b == '!') // CDATA section { if (this[p + 1] == '[' && this[p + 2] == 'C' && this[p + 3] == 'D' && this[p + 4] == 'A' && this[p + 5] == 'T' && this[p + 6] == 'A' && this[p + 7] == '[') { text.Clear(); p += 7; while ((b = this[++p]) != ']' || this[p + 1] != ']' || this[p + 2] != '>') { text.Accept(b); } elem.Text = text.ToString(); p += 2; // skip ]> } } else if (IsNameStartChar(b)) { XElem child = ParseElem(ref p, b); elem.Add(child); } } else // text node { text.Clear(); while ((b = this[p]) != '<') // NOTE from the first char { if (b == '&') // escape < > & " { int b1 = this[p + 1]; int b2 = this[p + 2]; int b3 = this[p + 3]; if (b1 == 'l' && b2 == 't' && b3 == ';') { b = '<'; p += 3; } else if (b1 == 'g' && b2 == 't' && b3 == ';') { b = '>'; p += 3; } else if (b1 == 'a' && b2 == 'm' && b3 == 'p' && this[p + 4] == ';') { b = '&'; p += 4; } else if (b1 == 'q' && b2 == 'u' && b3 == 'o' && this[p + 4] == 't' && this[p + 5] == ';') { b = '"'; p += 5; } } text.Accept(b); ++p; } if (text.Count > 0) { elem.Text = text.ToString(); } // NOTE decrease in position to behave as other child nodes --p; } } // child nodes iteration } if (b == '/' && this[++p] == '>') // empty-element { pos = p; // adjust current position return(elem); } throw ParserEx; }