Commit c0d46b86 authored by jan.koester's avatar jan.koester
Browse files

test

parent 63a2f2b4
Loading
Loading
Loading
Loading
+22 −54
Original line number Diff line number Diff line
@@ -238,30 +238,25 @@ void libhtmlpp::HtmlString::_buildtreenode(
    libhtmlpp::DocElements *lastel,
    std::unique_ptr<Element> &html)
{
    // FIX 1: Relax initial check. If firstel is non-null, lastel=nullptr is valid (end of list).
    if (!firstel) {
        HTMLException excp;
        excp[HTMLException::Error] << "No start Element!";
        throw excp;
    }
    // If lastel is nullptr, it represents the end of the entire list. We don't check it here.

    struct Frame {
        DocElements *open;           // The DocElement node of the opening tag (e.g., <div>)
        DocElements *close;          // The DocElement node of the closing tag (e.g., </div>)
        const DocElements *outer_end; // The end bound of the parent's span
        DocElements *open;
        DocElements *close;
        const DocElements *outer_end;
        Element *outer_prev_el;
    };
    std::stack<Frame> stack;

    DocElements *start = firstel;
    const DocElements *end = lastel; // end will be nullptr for the root call
    const DocElements *end = lastel;

    Element *prev_el_in_tree = nullptr;

    // parent_el is unused and can be removed, but we'll leave it for now.
    // HtmlElement *parent_el = nullptr;

    auto skip_empty = [](DocElements *cur, const DocElements *stop) -> DocElements* {
        while (cur && cur != stop && (!cur->element)) {
            cur = cur->nextel.get();
@@ -269,7 +264,6 @@ void libhtmlpp::HtmlString::_buildtreenode(
        return cur;
    };

    // FIX 2: Cleaned and non-redundant find_terminator logic
    auto find_terminator = [&skip_empty](DocElements *open, const DocElements *bound) -> DocElements* {
        if (!open || !open->element || open->terminator ||
            open->element->getType() != HtmlEl)
@@ -279,7 +273,6 @@ void libhtmlpp::HtmlString::_buildtreenode(
        int nest = 0;
        DocElements *cur = open->nextel.get();

        // 1. Search for the terminator up to the boundary
        while (cur && cur != bound) {
            cur = skip_empty(cur, bound);

@@ -300,8 +293,6 @@ void libhtmlpp::HtmlString::_buildtreenode(
            cur = cur->nextel.get();
        }

        // 2. Mandatory container check (Only one check here, only runs if search failed)
        // If the loop finished without finding the terminator, and the tag is mandatory, throw.
        for (size_t i = 0; ContainerTypes[i]; ++i) {
            if (tag == ContainerTypes[i]) {
                HTMLException e;
@@ -313,45 +304,26 @@ void libhtmlpp::HtmlString::_buildtreenode(
        return nullptr;
    };

    // --- Main Iterative Traversal Loop ---
    for (;;) {
        start = skip_empty(start, end);

        // A. END OF CURRENT SCOPE CHECK (Base case/Return from recursion)
        if (!start || start == end) {

            // Final return for the root scope
            if (stack.empty()) {
                // If the root element (firstel->element) was never moved into a sibling chain
                // because it was the only element, move it now.
                // In a well-formed HTML (like <html>...</html>), the <html> opener
                // is the firstel. Its element is moved here only if it wasn't moved
                // into a sibling chain previously (which shouldn't happen).
                // The root element must be the *first* element in the list.
                // We move it only if its unique_ptr hasn't been moved yet.
                if (firstel->element) {
                    html = std::move(firstel->element);
                }
                return;
            }

            // Restore parent scope (pop from stack)
            Frame fr = stack.top(); stack.pop();
            HtmlElement *opener_el = static_cast<HtmlElement*>(fr.open->element.get());

            // CRITICAL STEP: Set parent's _childElement
            // The element at fr.open->nextel must be the first child of the completed child span.
            if (fr.open->nextel) {
                // If element is still here, it was the first child and its unique_ptr was not moved in Case C.
                if (fr.open->nextel->element) {
                    opener_el->_childElement = std::move(fr.open->nextel->element);
                }
                // If it's empty, it means the ownership was transferred to a sibling in Case C,
                // which is correct for multi-child containers.
            }

            // RESTORE STATE: The parent container (opener_el) itself is the last element
            // of its sibling chain so far. And restore the parent's previous sibling.
            prev_el_in_tree = opener_el;

            if (fr.outer_prev_el) {
@@ -562,10 +534,6 @@ void libhtmlpp::HtmlString::_buildTree() {
    }

    _buildtreenode(firstEl.get(),nullptr,_rootEl);

    HtmlString test;
    print(*_rootEl,test,true);
    std::cout  << "test" << test.c_str() << "test" << std::endl;
}

void libhtmlpp::HtmlString::_serialelize(std::vector<char> in, libhtmlpp::HtmlElement *out) {
@@ -745,29 +713,27 @@ void libhtmlpp::HtmlElement::insertChild(const Element& el){

void libhtmlpp::HtmlElement::appendChild(const libhtmlpp::Element* el){
    if(_childElement){
        Element *curel=_childElement.get(),*prev=nullptr;
        do{
            prev=curel;
            curel=curel->nextElement();
        }while(curel);
        Element *prev=nullptr;

        std::unique_ptr<Element> addel;
        for(Element *curel=_childElement.get(); curel; curel=curel->nextElement()){
            prev=curel;
        }

        switch(el->getType()){
            case HtmlEl:
                addel=std::make_unique<HtmlElement>();
                prev->_nextElement=std::make_unique<HtmlElement>();
                break;
            case TextEl:
                addel=std::make_unique<TextElement>();
                prev->_nextElement=std::make_unique<TextElement>();
                break;
            case CommentEl:
                addel=std::make_unique<CommentElement>();
                prev->_nextElement=std::make_unique<CommentElement>();
                break;
            case ScriptEL:
                addel=std::make_unique<ScriptElement>();
                prev->_nextElement=std::make_unique<ScriptElement>();
                break;
            case SvgEL:
                addel=std::make_unique<SvgElement>();
                prev->_nextElement=std::make_unique<SvgElement>();
                break;
            default:
                HTMLException ex;
@@ -775,11 +741,10 @@ void libhtmlpp::HtmlElement::appendChild(const libhtmlpp::Element* el){
                throw ex;
        }

        _copy(curel,el);
        _copy(prev->_nextElement.get(),el);

        if(prev){
            prev->_nextElement=std::move(addel);
            curel->_prevElement=prev;
        if(prev->_nextElement){
            prev->_nextElement->_prevElement=prev;
        }
    }else{
        insertChild(el);
@@ -861,7 +826,8 @@ void libhtmlpp::HtmlElement::remove(libhtmlpp::Element* el){
namespace libhtmlpp {

    void _copy(libhtmlpp::Element *dest,const libhtmlpp::Element *src){
        const libhtmlpp::Element* prev=dest->prevElement();

        const libhtmlpp::Element* prev=nullptr;

        struct cpyel {
            cpyel(){
@@ -884,6 +850,7 @@ namespace libhtmlpp {
        std::stack<cpyel> cpylist;

        NEWEL:

        if(src->getType()==HtmlEl && dest->getType()==HtmlEl){
            ((libhtmlpp::HtmlElement*)dest)->_TagName=(((libhtmlpp::HtmlElement*)src)->_TagName);
            for(libhtmlpp::HtmlElement::Attributes *cattr=((libhtmlpp::HtmlElement*)src)->_firstAttr.get(); cattr; cattr=cattr->_nextAttr.get()){
@@ -1008,6 +975,7 @@ namespace libhtmlpp {
            cpylist.pop();
            goto NEWEL;
        }
        return;
    }
};