Hot Door CORE Forum
InternetGET/InternetPOST - Printable Version

+- Hot Door CORE Forum (http://hotdoorcore.com/forum)
+-- Forum: All forums (http://hotdoorcore.com/forum/forumdisplay.php?fid=1)
+--- Forum: General discussion (http://hotdoorcore.com/forum/forumdisplay.php?fid=3)
+--- Thread: InternetGET/InternetPOST (/showthread.php?tid=71)

Pages: 1 2


RE: InternetGET/InternetPOST - Rick Johnson - 10-04-2016

Thanks, Garrett, that worked. It took some experimentation to cast the pointer, but eventually the dynamic_cast method seemed to work best. I can now iterate through the objects and retrieve the iter.key() and its value type, but retrieving the value itself remains elusive and will likely keep me busy for a while. I ran into a lot of memory issues working on this, which brought up a possible problem that hadn't occurred to me before:

If several plugins (mine plus other developers') all do an async POST or GET at startup, will their respective responses be directed back to the proper plugins, or do I need to somehow find a later "safe" time to initiate that?


RE: InternetGET/InternetPOST - Rick Johnson - 10-04-2016

White flag: I thought this would have been intuitive, but even if I find a syntax that builds, it won't run without a memory error. It's not that easy to cast iter.value() to something useful, even if it's only a simple string or number. Trying to cast an std::auto_ptr<PrefData> to an std::auto_ptr<StringPref> typically fails to build when system memory headers refuse to acknowledge the typecast. Am I running down a dead-end alley with that approach?

The header notes make frequent references to "JSON node to get from the top-level" which makes me question the relevance of a multi-level tree structure, at least as far as an iterator can see. Is a record that contains a few strings considered a Dictionary type that should be parsed in a separate operation?

So far, iter.value() has been useless; my fallback has been dict.member(name, data), but I can't be certain no two fields will have the same name, especially if it parses more than one level. E.g., every SQL record will have an ID no., unique within its own table. Is there any syntax that simply pulls a string or number from iter.value()?

I'd really appreciate any help on this. I feel I'm so close to reaching the next level, but just can't make that leap. Thanks!


RE: InternetGET/InternetPOST - garrett - 10-04-2016

(10-04-2016, 06:06 PM)Rick Johnson Wrote: If several plugins (mine plus other developers') all do an async POST or GET at startup, will their respective responses be directed back to the proper plugins, or do I need to somehow find a later "safe" time to initiate that?

Callbacks will always be executed in the correct context. Don't worry about other plugins and whatnot.

(10-04-2016, 06:06 PM)Rick Johnson Wrote: Trying to cast an std::auto_ptr<PrefData> to an std::auto_ptr<StringPref> typically fails to build when system memory headers refuse to acknowledge the typecast.

You cannot directly cast an auto_ptr<SomeType> to an auto_ptr<AnotherType>. The auto_ptr class simply contains a pointer to an object of a given type, and automatically handles the memory for said object. As such, simply cast the raw pointer it contains by acquiring said pointer with auto_ptr::get().

(10-04-2016, 06:06 PM)Rick Johnson Wrote: The header notes make frequent references to "JSON node to get from the top-level" which makes me question the relevance of a multi-level tree structure, at least as far as an iterator can see. Is a record that contains a few strings considered a Dictionary type that should be parsed in a separate operation?

There is no reason that any arbitrary hierarchy can't be used, and the entirety of the JSON string you provide is parsed (you do not need to separately parse sections of it). Container-type subclasses of the PrefData class can contain any other PrefData subclass in as deep of a hierarchy as you'd like. Perhaps you need to review the structure and "types" that JSON supports? And review all the hdi::core:TonguerefData subclasses? Any possible structure/data that can be represented by JSON can be handled by the various PrefData subclasses.

(10-04-2016, 06:06 PM)Rick Johnson Wrote: So far, iter.value() has been useless; my fallback has been dict.member(name, data), but I can't be certain no two fields will have the same name, especially if it parses more than one level. E.g., every SQL record will have an ID no., unique within its own table. Is there any syntax that simply pulls a string or number from iter.value()?

Well, obviously two entries in a dictionary cannot have the same name, so if that's what you're referring to then you need to rethink your dictionary structure. If you mean that you might have multiple dictionaries with identically-named entries contained within an array, then of course only the entry with the name you provide will be accessed in the target dictionary, and not some other dictionary contained within the array.

Lastly, I wonder why you are relying on dictionary member iteration at all. If you're writing the server-side code that generates the JSON, then you're in complete control of the structure and the names of the members in said structure. As such, you should be able to create a structure with stable/known entry names and use hdi::core:Big GrinictionaryPref::member() or hdi::core:Big GrinictionaryPref::get*Member() to get the job done.


RE: InternetGET/InternetPOST - Rick Johnson - 10-06-2016

Thanks a ton, Garrett. Things are now falling into place. Here's a sample of what I've done in my POST success CB:

Code:
    std::string postStr = this->iPOST->content();
    std::string errStr = this->iPOST->error(); // no error
    std::auto_ptr<hdi::core::PrefData> returnedData = hdi::core::PrefData::parse(postStr);
    std::string tempStr("");
    std::string valStr("");
    hdi::core::StringPref strPrf;
    hdi::core::StringPref* strPtr;
    hdi::core::NumberPref* numPtr;
    std::auto_ptr<hdi::core::PrefData> prfPtr;
    bool success(false);

    hdi::core::PrefData::Type typ = returnedData->dataType(); // returns DictionaryType
    hdi::core::DictionaryPref* dict = dynamic_cast<hdi::core::DictionaryPref*>(returnedData->clone());

    for(hdi::core::DictionaryPref::Iterator iter = dict->begin(); !iter.atEnd(); ++iter) {
        tempStr = iter.key();
        typ = iter.value()->dataType();
        switch (typ) {
            case hdi::core::PrefData::StringType:
                strPtr = dynamic_cast<hdi::core::StringPref*>(iter.value()->clone());
                valStr = strPtr->stringValue();
                break;
            case hdi::core::PrefData::NumberType:
                numPtr = dynamic_cast<hdi::core::NumberPref*>(iter.value().clone());
                valNum = numPtr->floatValue();
                break;
            default:
        break;
        }
    free (this->iPOST);
    this->iPOST = NULL;

This worked, although the float value parsed as a string (easily handled, though). It was interesting (or puzzling) that dynamic_cast and ->clone() was the only combination that seemed to work. I had no success with any variation I tried with auto_ptr.get. Alternately, I tried this simpler code:

Code:
    hdi::core::DictionaryPref* dict = dynamic_cast<hdi::core::DictionaryPref*>(returnedData->clone());
    success = dict->member("number", prfPtr);
    typ = prfPtr->dataType();
    success = (dict->getStringMember("number", strPrf));
    valStr = strPrf.stringValue();

This worked, too, as did a hybrid of the two approaches, although I'm sure there's a much better way to code it.

It helps to understand that DictionaryPref functions look only at the top level, which solves the (remote) possibility of duplicate key names.

The reason I'm using an iterator here is that this is where I happen to be as I get more involved in PrefData structures, part of an overall learning process. I can envision situations where its iterator can be very helpful, as well as another way to become familiar with its structure and interface as PrefData and dictionaries will certainly become an important part of my plugins. Thank you so very much for your help, Garrett!