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]
>
>