void HtmlParser::parseExtraAttributes(const char* szAttributesText, HtmlNode* pTargetNode, const char* szNamePrefix) { assert(pTargetNode); const char* p = szAttributesText; const char* ps = NULL; MemBuffer mem; bool inQuote1 = false, inQuote2 = false; unsigned char c; while(c = *p) { if(c == '\'') inQuote1 = !inQuote1; else if(c == '\"') inQuote2 = !inQuote2; bool notInQuote = (!inQuote1 && !inQuote2); if(notInQuote && (c == '\"' || c == '\'') && !isspace(p[1])) { //处理属性值引号后面没有空白分隔符的情况:a="v1"b=v2 (这种错误写法不少见,应兼容之) if(ps) { mem.appendPointer(duplicateStrAndUnquote(ps, p - ps + 1)); ps = NULL; } p++; continue; } if(notInQuote && (c == '=' || isspace(c))) { if(ps) { mem.appendPointer(duplicateStrAndUnquote(ps, p - ps)); ps = NULL; } if(c == '=') mem.appendPointer(NULL); } else { if(ps == NULL) ps = p; } p++; } if(ps) mem.appendPointer(duplicateStrAndUnquote(ps, p - ps)); mem.appendPointer(NULL); mem.appendPointer(NULL); char** pp = (char**) mem.getData(); //下面把解析出来的属性值存入pTargetNode->attributes MemBuffer* attributes = pTargetNode->attributes; if(attributes == NULL) { attributes = new MemBuffer(); pTargetNode->attributes = attributes; } for(int i = 0, n = mem.getDataSize() / sizeof(char*) - 2; i < n; i++) { if(!szNamePrefix) { attributes->appendPointer(pp[i]); //attribute name } else { char* newAttributeName = duplicateStr(pp[i], -1, szNamePrefix); attributes->appendPointer(newAttributeName); //attribute name freeDuplicatedStr(pp[i]); } if(pp[i+1] == NULL) { attributes->appendPointer(pp[i+2]); //attribute value i += 2; } else attributes->appendPointer(NULL); //attribute vlalue //标记需free属性名称和属性值文本 //TODO: 将来优化到尽量少复制文本 attributes->appendInt(FLAG_NEED_FREE_NAME | FLAG_NEED_FREE_VALUE); //attribute flags } attributes->shrink(); pTargetNode->attributeCount = attributes->getDataSize() / sizeof(HtmlAttribute); }
static int test_MemBuffer (){ cout << "Go Testing" << __FILE__ << endl; MemBuffer mem; cout << "default capacity:" << mem.capacity () << endl; mem.require (512); cout << "now capacity:" << mem.capacity () << endl; mem.require (513); cout << "now capacity:" << mem.capacity () << endl; cout << "not use=>" << mem.data () << endl; mem.appendData ("hello", 5); cout << "=>" << ( mem.data ()!=NULL?(char*) mem.data (): NULL) << endl; mem.appendData (" world", 6); cout << "=>" << ( mem.data ()!=NULL?(char*) mem.data (): NULL) << endl; cout << "now size:" << mem.size () << " capacity:" << mem.capacity () << endl; mem.shrink (); cout << "now size:" << mem.size () << " capacity:" << mem.capacity () << endl; mem.insertData (6, "code ", 5); cout << "inserted size:" << mem.size () << " capacity:" << mem.capacity () << endl; cout << "=>" << ( mem.data ()!=NULL?(char*) mem.data (): NULL) << endl; mem.deleteData (6, 5); cout << "deleted size:" << mem.size () << " capacity:" << mem.capacity () << endl; cout << "=>" << ( mem.data ()!=NULL?(char*) mem.data (): NULL) << endl; MemBuffer other; other = mem; cout << "other size:" << other.size () << " capacity:" << other.capacity () << endl; cout << "other=>" << ( other.data ()!=NULL?(char*) other.data (): NULL) << endl; size_t rs = other.saveToFile ("/tmp/temp_test"); cout << "write :" << rs << endl; mem.empty (); rs = mem.loadFromFile ("/tmp/temp_test"); cout << "read :" << rs << endl; cout << "read size:" << mem.size () << " capacity:" << mem.capacity () << endl; cout << "=>" << ( mem.data ()!=NULL?(char*) mem.data (): NULL) << endl; unlink ("/tmp/temp_test"); cout << "=============================\n\n" << endl; int i = 1; long l = 1000; char string[] = "hello world"; bool b = true; float f = 2.0f; double d = 100.1; mem.empty (); mem.pushInt ( &i ); mem.pushLong ( &l ); mem.pushString ( string, strlen(string) ); mem.pushBool ( &b ); mem.pushFloat ( &f ); mem.pushDouble ( &d ); cout << "push size:" << mem.size () << " capacity:" << mem.capacity () << endl; other.empty (); other = mem; cout << "double:" << other.popDouble () << endl; cout << "float:" << other.popFloat () << endl; cout << "bool:" << other.popBool () << endl; cout << "stirng:" << other.popString () << endl; cout << "loing:" << other.popLong () << endl; cout << "int:" << other.popInt () << endl; return 0; }