How to determine the length of a String returned by the To_String function of the GNAT Big_Integer package?

Hi;

How to determine the length of a String returned by the To_String function of the GNAT Big_Integer package?

Or how to determine the length of the GNAT Big_Integer directly?

I’m sure that the answer is right in front of my nose, but I don’t see it :frowning:

Thanks,

RBE

Does the ‘Length attribute for strings not do the job? i.e., String’Length (Big_Integers.To_String (Your_Number))

Sorry if this is a stupid answer; I don’t have time to check at the moment that it actually works.

1 Like

Somewhat more efficient is to rename the result of a call on To_String, and then you can check the ’Length and also use the result without re-invoking To_String. E.g.:

 Str : String renames Big_Integers.To_String(X);
 ...
 --  Str'Length gives you the length
 --  Str gives you the actual string
2 Likes

@sttaft What is it that makes it more efficient?

You generally want the string and its length. So Tucker’s verson is more efficient in this sense.

1 Like

In addition, by renaming the result most implementations will avoid making an extra copy of the string returned by the function. So potentially you have both fewer function calls and fewer string copies.

3 Likes

It’s important to remember that Str is a constant.

1 Like

What is the difference between a renamed function result

Str : String renames Big_Integers.To_String(X);

and a constant object declared by that same function?

Str : constant String := Big_Integers.To_String(X);

I never had the idea to rename a function call.

As mentioned, in many implementations, a renaming results in one less copy of the function result, which can be significant if the result is a large object.

In Ada 2022, this can be even more concise:

Str renames Big_Integer.To_String(X);

You can omit the type since all of that information can come from the RHS, if it is unambiguous. See 2022 Ada RM, 8.5.1(2/5,10/5).

EDIT: Never mind, removed incorrect example. I had a wrong understanding of when a renames clause is first executed.

Now I am confused by Tuckers statement as well since I cannot see a scenario where a renames would allow a copy to be optimized away that just using a constant would also not allow the same (at least in theory). Unless this is just a GNAT specific behavior?

Well, no. The semantics of the declaration are described in terms of a copy, but the copy may be optimized away in many cases. Apparently GNAT is pretty good at doing such optimizations, especially for SPARK. See the section on Return Slot Optimization in Rod Chapman’s blog post on SPARKNaCl, for example.

1 Like

Hm, no. It’s not the copy which raises the exception. Thus in neither of your sample codes can you catch the exception.

It’s not the copy that raises the exception but he call to To_String that could. I was under the impression that the renames clause did not immediately make the call to To_String until the renamed object is first used. Based on your response that sounds incorrect though. I think you are saying the renames clause is executed in the declarative region instead of at the first point the object is used?

A copy still has to happen here unless the compiler optimizes out the string variable completely. Just building the variable in place requires at least one copy of raw data to the variable’s location (could be the stack, could be the secondary stack in GNAT, or wherever).

Plus, the renames is an excellent reminder that you’re renaming something. I personally find it an excellent reminder that’s what’s happening (esp. WRT attributes and WRT deeply-nested and/or working-[sub]components), and prefer it to constant.

I have mixed feelings on the short-form: on the plus it is quite “slim & trim”, on the negative the type-info is nice as a reminder in the “oh, this is what I’m working with” manner and provides a really good spot for the compiler to flag when things get mixed up due to editing/changes.