Optimizing simple xHTML parser I'm writing a simple xHTML parser which parses a data without nested tags.

Example input code will look like:

&lt;h2&gt;Header&lt;/h2&gt; 
&lt;p&gt; atsatat &lt;/p&gt; 
&lt;h2&gt;asdsaad&lt;/2&gt;&lt;p&gt;s32532235&lt;/p&gt;


I've wrote the following code:

#include &lt;node.h&gt;
#include &lt;vector&gt;
#include &lt;string&gt;
#include &lt;sstream&gt;
#include &lt;iostream&gt;

using namespace v8;

enum Tags {
    Closing = 0,
    Paragraph,
    Heading
};

int tagDetect(char *ptr){
    if (*ptr == '/') {
        return Tags::Closing;
    }

    if (*ptr == 'p') {
        return Tags::Paragraph;
    }

    if (*(ptr + 1) == '2' || *(ptr + 1) == '3')
        return Tags::Heading;

    return -1;
}

Handle&lt;Value&gt; Callback(const Arguments&amp; args) {
    HandleScope scope;

    if (!args[0]-&gt;IsString() || !args[1]-&gt;IsFunction()) {
        return ThrowException(Exception::TypeError(
            String::New("Invalid arguments! First parameter must be [string], second must be a callback [function].")));
    }

    Local&lt;Function&gt; callback = Local&lt;Function&gt;::Cast(args[1]);
    String::Utf8Value param1(args[0]-&gt;ToString());
    std::string input = std::string(*param1);

    static Persistent&lt;String&gt; data_symbol = NODE_PSYMBOL("data");
    static Persistent&lt;String&gt; tag_symbol = NODE_PSYMBOL("tag");

    std::string::size_type pos = 0, closePos = 0;

    int openPos;
    int tagID, lastTag, id = 0, lastAppended = 0, clearStartPos;

    Local&lt;Array&gt; nodes = Array::New();
    Local&lt;Object&gt; node_obj;

    while ((pos = input.find('&lt;', pos)) != std::string::npos) {
        pos++;
        switch (tagID = tagDetect(&amp;input[pos])) {
        case Tags::Closing:
            tagID = tagDetect(&amp;input[pos + 1]);
            if (tagID == lastTag &amp;&amp; (pos - openPos &gt; 10 || lastTag != Tags::Paragraph)) {
                /* Concat tags */
                if (lastAppended == lastTag) {
                    if (lastTag == Tags::Heading) { /* Dont concat heading tags */
                        continue;
                    }

                    node_obj = nodes-&gt;Get(id - 1)-&gt;ToObject();
                    node_obj-&gt;Set(data_symbol, String::Concat(node_obj-&gt;Get(data_symbol)-&gt;ToString(), String::New(input.substr(openPos + (lastTag &gt; 1 ? 3 : 2), pos - openPos - (lastTag &gt; 1 ? 3 : 2) - 1).c_str())));
                    continue;
                }

                node_obj = Object::New();
                node_obj-&gt;Set(data_symbol, String::New(input.substr(openPos + (lastTag &gt; 1 ? 3 : 2), pos - openPos - (lastTag &gt; 1 ? 3 : 2) - 1).c_str()));
                node_obj-&gt;Set(tag_symbol, Integer::New(lastTag));
                nodes-&gt;Set(id, node_obj);
                id++;
                lastAppended = lastTag;
                continue;
            }

            /* Clear useless tags */
            input.erase(pos - 1, input.find('&gt;', pos - 1) - pos + 2);
            break;
        case Tags::Paragraph:
        case Tags::Heading:
            openPos = pos;
            lastTag = tagID;
            break;
        default:

            /* Clear useless tags */
            input.erase(pos - 1, input.find('&gt;', pos - 1) - pos + 2);
            break;
        }
    }


    /* Remove last element from array if its heading */

    if (lastTag == Tags::Heading) {
        nodes-&gt;Delete(id - 1);
    }

    const unsigned argc = 2;
    Local&lt;Value&gt; argv[argc] = {
        Local&lt;Value&gt;::New(Null()),
        nodes
    };

    callback-&gt;Call(Context::GetCurrent()-&gt;Global(), argc, argv);

    return Undefined();
}

void RegisterModule(Handle&lt;Object&gt; target) {
    target-&gt;Set(String::NewSymbol("parse"),
        FunctionTemplate::New(Callback)-&gt;GetFunction());
}

NODE_MODULE(smartparser, RegisterModule);


I'm using this as Native NodeJS module. Since I'm really new in the C++ world, any tips on how to optimize/improve my code will be greatly appreciated.
Although optional, you can keep your #includes organized (alphabetically, for instance) so that it's easier to locate an individual one or to determine if you've already included a particular one.
You've included &lt;sstream&gt;, but I don't see any use of stringstreams.  If you're not utilizing this library, then remove it.
Avoid using namespace X in global scope as it will expose it to the entire program or file, which can break code in cases such as name-clashing (using the same name for something in which something doesn't belong to the namespace).  It could also make it difficult for readers to tell what is part of a particular namespace (I cannot tell what belongs to v8, so I'm having a bit more trouble reviewing this).  If you insist on keeping a using, then keep it local, such as in a function.
For this enum:

enum Tags {
    Closing = 0,
    Paragraph,
    Heading
};


You don't need to explicitly set it to 0.  This is already the default starting value for enums.
You don't need a char* here:

int tagDetect(char *ptr){


Looking at the calling code, you're passing in an std::string.  You should just pass this object by itself.  Also, because it's not being modified, pass it by const&amp; to avoid a needless copy and any accidental modification:

int tagDetect(std::string const&amp; str){


In C++ in general, you should avoid passing raw pointers to functions as you cannot keep track of ownership with them (C++11 smart pointers helps with that for when points are necessary).  But in this case, you shouldn't need to deal with pointers.

With this change, you will need to modify the function code (I'll use different names for clarity):

This is accessing the first character:

if (*ptr == 'p')


so use front():

if (str.front() == 'p')


This is accessing the second one:

*(ptr + 1)


so you can use indices to make it more clear (while they are technically the same thing; yours is doing pointer arithmetic):

str[1]

I'd keep these on separate lines for readability:

int tagID, lastTag, id = 0, lastAppended = 0, clearStartPos;


They aren't entirely related to each other, and there could be some maintenance issues since some are declared and the others initialized.

int tagID;
int lastTag;
int id = 0;
int lastAppended = 0;
int clearStartPos;


You should also have these declared/initialized as close to their scope as possible.  This will help determine if any variable is no longer used (keeping around unused variables will clutter the code).  But if you cannot put them any closer, then do have each one on separate lines.