As Fraser says, you can't access the internal string, but you do have the
option to create your own externally:

    pn_data_t *data = ...;

    pn_string_t *str = pn_string(NULL);
    pn_inspect(data, str);
    const char *result = pn_string_get(str);
    ... // use result
    pn_free(str); // you can also use pn_incref(str)/pn_decref(str) to
share a single pn_string_t if you want.
                       // pn_free() just asserts that pn_refcount(str) is
one and then pn_decref()s it

This won't tell you in advance how much space you need, but it will
dynamically grow the buffer inside the pn_string_t for you.

--Rafael


On Sat, Feb 14, 2015 at 2:40 AM, Fraser Adams <[email protected]
> wrote:

> Hello Mikhail,
> I'm not an expert on pn_data_format and TBH I've never used it in pure C
> code, only to write other language bindings. I don't know if it's possible
> to find out beforehand. My guess is probably not - the python binding
> (which is fairly canonical) looks like this:
>
>
>   def format(self):
>     sz = 16
>     while True:
>       err, result = pn_data_format(self._data, sz)
>       if err == PN_OVERFLOW:
>         sz *= 2
>         continue
>       else:
>         self._check(err)
>         return result
>
>
> And I borrowed that pattern when I did the JavaScript binding, which looks
> like this:
>
>
> /**
>  * Format the encoded AMQP Data into a string representation and return it.
>  * @method format
>  * @memberof! proton.Data#
>  * @returns {string} a formatted string representation of the encoded Data.
>  */
> _Data_['format'] = function() {
>     var sp = Runtime.stackSave();
>     var sizeptr = allocate(4, 'i32', ALLOC_STACK);
>
>     var size = 1024; // Pass by reference variable - need to use setValue
> to initialise it.
>     while (true) {
>         setValue(sizeptr, size, 'i32'); // Set pass by reference variable.
>         var bytes = _malloc(size);   // Allocate storage from emscripten
> heap.
>         var err = _pn_data_format(this._data, bytes, sizeptr);
>         var size = getValue(sizeptr, 'i32'); // Dereference the real size
> value;
>
>         if (err === Module['Error']['OVERFLOW']) {
>             _free(bytes);
>             size *= 2;
>         } else {
>             var string = Pointer_stringify(bytes, size);
>             _free(bytes);
>             // Tidy up the memory that we allocated on emscripten's stack.
>             Runtime.stackRestore(sp);
>             this._check(err)
>             return string;
>         }
>     }
> };
>
>
>
> So basically the "pattern" is to allocate some storage and call
> pn_data_format passing in the allocated storage and the size of the
> allocated storage - the latter is a pass by reference parameter.
>
> You need to check the error condition and if it's PN_OVERFLOW you need to
> free your original storage and try again with a bigger block - usual
> pattern is to double the size.
>
>
> I don't *think* there's any way to know a priori how much storage you are
> going to need because it's the call to pn_data_format that is actually
> "deserialising" the internal pn_data_t values into a pretty formatted form,
> so it doesn't actually know how big it's going to be until it has tried. In
> other words even if you could get the pointer data->str its value isn't
> useful until pn_data_format is actually being called - I think it's the
> private method pni_data_inspectify that starts that all off - if you look
> at the codec.c code you'll see:
>
> int pn_data_format(pn_data_t *data, char *bytes, size_t *size)
> {
>   int err = pni_data_inspectify(data);
>   if (err) return err;
>   if (pn_string_size(data->str) >= *size) {
>     return PN_OVERFLOW;
>   } else {
>     pn_string_put(data->str, bytes);
>     *size = pn_string_size(data->str);
>     return 0;
>   }
> }
>
>
> and
>
> static int pni_data_inspectify(pn_data_t *data)
> {
>   int err = pn_string_set(data->str, "");
>   if (err) return err;
>   return pn_data_inspect(data, data->str);
> }
>
> so inspectify initialises the internal string then calls inspect (which in
> turn calls pni_data_traverse which, as its name suggests crawls the
> internal data graph deserialising into the internal string).
>
> Having looked at the code I'm now pretty sure that it's not possible to do
> what you'd like and the only option is to check PN_OVERFLOW and realloc as
> necessary.
>
> Hope that helps,
> Frase
>
>
> On 13/02/15 21:22, Michael Ivanov wrote:
>
>> Hallo,
>>
>> I am trying to use proton routine for data formatting.
>> pn_data_format checks suire of provided buffer and in case it is not
>> enough just refuses to copy anything at all.
>>
>> Is it possible to find out how much does it need beforehand?
>>
>> Ideally would be if one had the possibility to get the pointer to this
>> internal string (data->str) which already holds the string representation
>> of data. Does this option exist?
>>
>> Best regards,
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>

Reply via email to