fmt : format a float/double without format string - fmt

I would like to format a single double/float to a string/wstring with fmt.
something like
std::string s = fmt:format_??(my_float);
Since the formats I use are kind of fixed, is there a way to use the library without having to use the format string, but directly feeding the settings?
I noticed there are format_int and format_float that uses a settings struct,which may be suitable, but these are inside the detail namespace and also it's not so clear how to initialize the input parameters.
My (unbenchmarked) guess is that avoiding the format string would result in a faster conversion.
Any idea or experience in this regard?
Thanks!

is there a way to use the library without having to use the format string, but directly feeding the settings?
No but if the format is known at compile time you can use format string compilation which completely eliminates the runtime overhead of handling a format string, however small. For example:
std::string s = fmt::format(FMT_COMPILE("{}"), 42);
is the fastest method of converting a number into an std::string (there is also fmt::to_string which is equivalent): https://www.zverovich.net/2020/06/13/fast-int-to-string-revisited.html.

Related

Twincat3 ST variables conversion

I have some complicated array of structures and I want to write it into CSV file. So I need "variable to string" conversion.
Beckhoff as always doesn't care about documentation and their INT_TO_STRING function doesn't work (UNEXPECTED INT_TO_STRING TOKEN when I try to write INT_TO_STRING(20) ).
Moreover their string functions works correctly with only 255 chars.
So I need one of following:
working functions or function blocks or library which allows to convert different types to string
something like sprintf without limitations
some functions to convert between number and ascii char (0x55 is letter 'U') in both directions.
btw. Beckhoff gives us some weird CSV example code, but without data conversion (array has already strings in cells).
Thanks in advance!
I tried to use:
INT_TO_STRING() BYTE_TO_STRING() WHATEVER_TO_STRING()
but it is not working. And there is no clue how many arguments it should have or anything. There is no documentation in Beckhoff information System.

How can I store a format string template outside of my source code?

When translating, messages can be in different languages and have format parameters. I want to be able to do this where the template can be stored in a file:
static PATTERN: &'static str = r"Hello {inner};";
/// in some implementation
fn any_method(&self) -> String {
format!(PATTERN, inner = "world");
}
That's not possible. Format strings must be actual literal strings.
The next best approach would be some kind of dynamic string format library. Or, failing that, you could always use str::replace if your needs aren't too complex.
This is definitely possible and trivial to do using the include_str macro that has been available in the standard library since version 1.0.0. The following example was tested with rustc 1.58.1:
Contents of src/main.rs:
println!(include_str!("src/hello-world.tmpl"), "world");
Contents of src/hello-world.tmpl
Hello {inner}
This works because include_str injects the contents of the template file as a string literal before println, format, and friends have a chance to evaluate their arguments. This approach only works when the format template you want to include is available during macro expansion - like it is in your example. If it's not, then you should consider other options like the ones suggested by #DK.
As an added bonus: You can also define format strings in source code locations other than the site where they are used by defining them as macros.

Convert string with commas into integer in Freemarker

I have a string with commas in between. How should I convert this string into an integer. I tried using
x?number
but that gives me the following error
Exceptionfreemarker.core.NonNumericalException
e.g. The string is "453,000". I need to convert this to 453000.
Is there any other way of doing this?
There's no function built in for parsing numbers with national formats. ?number only deals with computer format, because when numbers are transferred as strings (which should be already rare), that's what used to be used. So in principle x should be already a number when it gets to FreeMarker, or at least it should use computer format. If that's not possible, you will need a custom function (or method) for that.

Types for strings escaped/encoded differently

Recently I am dealing with escaping/encoding issues. I have a bunch of APIs that receive and return Strings encoded/escaped differently. In order to clean up the mess I'd like to introduce new types XmlEscapedString, HtmlEscapedString, UrlEncodedString, etc. and use them instead of Strings.
The problem is that the compiler cannot check the encoding/escaping and I'll have runtime errors.
I can also provide "conversion" functions that escape/encode input as necessary. Does it make sense ?
The compiler can enforce that you pass the types through your encoding/decoding functions; this should be enough, provided you get things right at the boundaries (if you have a correctly encoded XmlEscapedString and convert it to a UrlEncodedString, the result is always going to be correctly encoded, no?). You could use constructors or conversion methods that check the escaping initially, though you might pay a performance penalty for doing so.
(Theoretically it might be possible to check a string's escaping at compile time using type-level programming, but this would be exceedingly difficult and only work on literals anyway, when it sounds like the problem is Strings coming in from other APIs).
My own compromise position would probably be to use tagged types (using Scalaz tags) and have the conversion from untagged String to tagged string perform the checking, i.e.:
import scalaz._, Scalaz._
sealed trait XmlEscaped
def xmlEscape(rawString: String): String ## XmlEscaped = {
//perform escaping, guaranteed to return a correctly-escaped String
Tag[String, XmlEscaped](escapedString)
}
def castToXmlEscaped(escapedStringFromJavaApi: String) = {
require(...) //confirm that string is properly escaped
Tag[String, XmlEscaped](escapedStringFromJavaApi)
}
def someMethodThatRequiresAnEscapedString(string: String ## XmlEscaped)
Then we use castToXmlEscaped for Strings that are already supposed to be XML-escaped, so we check there, but we only have to check once; the rest of the time we pass it around as a String ## XmlEscaped, and the compiler will enforce that we never pass a non-escaped string to a method that expects one.

How do I PInvoke a multi-byte ANSI string?

I'm working on a PInvoke wrapper for a library that does not support Unicode strings, but does support multi-byte ANSI strings. While investigating FxCop reports on the library, I noticed that the string marshaling being used had some interesting side effects. The PInvoke method was using "best fit" mapping to create a single-byte ANSI string. For illustration, this is what one method looked like:
[DllImport("thedll.dll", CharSet=CharSet.Ansi)]
public static extern int CreateNewResource(string resourceName);
The result of calling this function with a string that contains non-ASCII characters is that Windows finds a "close" character, generally this looks like it ends up being "???". If we pretend that 'a' is a non-ASCII character, then passing "cat" as a parameter would create a resource named "c?t".
If I follow the guidelines in the FxCop rule, I end up with something like this:
[DllImport("thedll.dll", CharSet=CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true)]
public static extern int CreateNewResource([MarshalAs(UnmanagedType.LPStr)] string resourceName);
This introduces a change in behavior; now when a character cannot be mapped an exception is thrown. This concerns me because this is a breaking change, so I'd like to try and marshal the strings as multi-byte ANSI but I cannot see a way to do so. UnmanagedType.LPStr is specified to be a single-byte ANSI string, LPTStr will be Unicode or ANSI depending on the system, and LPWStr is not what the library expects.
How would I tell PInvoke to marshal the string as a multibyte string? I see there's a WideCharToMultiByte() API function, could I change the signature to expect an IntPtr to a string I create in unmanaged memory? It seems like this still has many of the problems that the current implementation has (it still might have to drop or substitute characters), so I'm not sure if this is an improvement. Is there another method of marshaling that I'm missing?
ANSI is multi-byte, and ANSI strings are encoded according to the codepage currently enabled on the system. WideCharToMultiByte works the same way as P/Invoke.
Maybe what you're after is conversion to UTF-8. Although WideCharToMultiByte supports this, I don't think P/Invoke does, since it's not possible to adopt UTF-8 as the system-wide ANSI code page. At this point you'd be looking at passing the string as an IntPtr instead, although if you're doing that, you may as well use the managed Encoding class to do the conversion, rather than WideCharToMultiByte.
Here is the best way I've found to accomplish this. Instead of marshalling as a string, marshal as a byte[]. Put the responsibility on the caller of the pinvoke function API to convert to a byte array in the most appropriate fashion. Most likely by using one of the Text.Encoding classes.
If you end up having to call WideCharToMultiByte manually, I would get rid of the p/invoke and manually marshal this using WideCharToMultiByte in a C++/CLI wrapper function. Managed C++ is much better at these interop scenarios than C# is.
Though, if this is the only p/invoke you have, it's probably not worth it.

Resources