Access locale information - c

What is the most portable way to access locale information?
I'm interested in time locale data, such as month names, day of week names, local time format etc.
Ideally I'd like a POSIX interface, but if it doesn't exist, glibc-specific one will do.
If possible, getting the information about the locale X shouldn't require setting it (using uselocale() or similar).
Calling strftime() many times with all sorts of parameters is considered a hack, not a solution.
If there's nothing better, I'm willing to consider directly parsing glibc's locale files if there's a reliable way to determine their location.

nl_langinfo is a POSIX-standard interface for returning that information and appears to have available all of the things that you're looking for. Sadly, it does require that you call setlocale before calling it. I don't see an interface that lets you query an arbitrary locale without first making it the current locale.

Related

Programmatically changing the decimal separator with C setlocale()

First of all, this must be really solved in C, and with UNIX standard C functions (because of project constraints). So, C++ or alternative libraries are outside the scope of the question.
I know how to set the default user locale with setlocale, as well as setting the standard C/POSIX locales.
However, I'm in a situation where the decimal separator is file-specified, so I want my program to temporally change the decimal separator.
LC_NUMERIC expects a locale name... but I don't want to give it a locale name, but the separator character directly.
How can this be done?
Well, I'm afraid you won't like the solution :)
First of all, since you're operating with setlocale you have to supply a locale name. Therefore there should be a locale with LC_NUMERIC property defined by you in the time of program execution. Therefore you need to define a new locale. You may define it with localedef You may use this doc as a guide for making and using a new locale and this site to get source files which you can use as a template for your custom locale definition.

How to get DateSeparator in C

I wish to get the date separator accordingly to the system's format's settings.
In Delphi I'm using System.SysUtils.TFormatSettings.DateSeparator, is there something like this in C?
The C language and standard library do not provide any such information. This information can be obtained from whatever system you are targeting. How you do that is dependent on which system you target.
While it is true as stated by the other answers that the C standard does not provide this information, posix does. So on any posix compliant system you can use the nl_langinfo api to get locale information.
You will not get the date separator though, but the date format that can be used by strftime to display the correctly formatted date for the locale. You can always parse this to get the date separator if that's what you really need, but for most uses the actual date format will probably be more useful.
Posix support for Windows is flakey, so you probably have to treat it differently, but for pretty much any other platform this should help you.
The C language and standard library do not provide any such
information. This information can be obtained from whatever system you
are targeting.
Thanks for clarification, targets could be both linux and windows. In those cases, how to do what I asked?
You need different functions for different OS.
e.g.
GetDataSeparator()
{
#ifdef _WIN32
Here goes implementation for Windows
#else
May be more preprocessor commands and implementations for Linux/Mac
#endif
}
Not sure if I understood everything correctly.
For Windows you can parse values found in HKCU\Control Panel\International. For Linux this link might be helpful.

Safe cross-platform function to get normalized path

I'd like to have a standard function that will convert relative paths into absolute ones, and if possible I'd like to make it as cross-platform as possible (so I'd like to avoid calling external library functions). This is intended so it's possible to prevent path exploitations.
I am aware that such a function wouldn't be able to detect symbolic links, but I'm ok with that for my application.
I could roll my own code, but there might be some problems with e.g. how a platform handles encoding or variations of the "../" pattern.
Is there something like that already implemented?
There's not a single, universal function you can call, since there's no such function in the C or C++ standard libraries. On Windows, you can use GetFullPathName. On Linux, Mac OS X, and other *Unix-based systems, you can use the realpath(3) function, which as a bonus also resolves symbolic links along the way.
Beware: Any solution to this is only reliable in a single-threaded program. If you're using multiple threads, another can go out and change the working directory out from under you unexpectedly, changing the path name resolution.
I think the closest you're going to get to platform independence are the POSIX libraries. In particular you'll wanna check out unistd.h which unfortunately I don't believe has a 'normalized' path concept. If I remember correctly the standard itself doesn't even know much about directories much less relative ones.
To get better than that I think you'll need to roll your own path goodies.

C locale questions

I have some questions, but I can´t find straight answer anywhere.
So, basically, I know what locale is, I know how to use (set) it, but what I dont know is
how is work behind the scene, and I would very like to know it.
So, when I use functions for IO, lets say for example scanf do float, when I need to decide whether country use decimal point or comma (I am actually from decimal comma country :)),
does scanf function "look" to check the current locale?
But if I doesn´t set it in my code, does it by default creates some standard locale itself, OR does it get it from OS?
For example in the part of code when you get handle to console for stdout stderr and stdin?
By default your program will have the C locale.
When you run setlocale(LC_ALL,""); you will set the locale from the outside environment (or you can set just parts LC_*).
By calling setlocale(LC_ALL,"specific_locale"); you will set the specific locale.
All I/O functions should follow the current locale (standard C I/O functions).
The behind-the-code behaviour depends on the operating system and compiler you are using.

Working with timezones in C

I'm currently migrating some of my code from Cocoa (Apple's Objective-C API) to C, in order to make it available for other operating systems, such as GNU/Linux.
In Cocoa, there were many great things like creating NSTimeZone objects from their string descriptors using timeZoneWithAbbreviation:. This allowed me to use values like "Europe/Paris" to easily create NSTimeZone objects.
Another important method for me was secondsFromGMTForDate: because it automatically considers DST rules for you.
Right now, the closest thing to NSTimeZone I've found for C is the struct timezone (see here). However, I do not see how I can easily get the GMT "offset" in seconds for a specific time and timezone. Neither do I understand how to get timezone structs if you only have a description like "Europe/Paris".
The following is my understanding and may be wrong...
I'm not sure how OS X does it, but on Linux, the standard C timezone functions use the Olson database, which is really quite powerful (since it has a full list of locale descriptions and keeps track of historical time zone rules as well as current rules).
To set a time zone, call tzset. This function is automatically called by other time-related functions, but you can manually specify a different time zone from the system default by setting the TZ environment variable then calling tzset. For example:
int main(int argc, char *argv[]) {
time_t t = time(NULL);
printf("%s\n", ctime(&t));
setenv("TZ", "America/Chicago", 1);
printf("%s\n", ctime(&t));
return 0;
}
Calling tzset also sets the timezone global variable, which you can use to find the GMT offset in seconds for the current time zone.
These functions only let you use one time zone at a time, and although all of this (except for possibly the timezone global variable) should be standard C, platforms other than Linux may not have the full support for lists of locales, daylight savings time changes, etc. If you find that this doesn't meet your needs, then you can try using third-party libraries, such as the code distributed with the [Olson database] or ICU's TimeZone class (also usable from C).
Unfortunately, you are treading into difficult territory. There isn't a good, widely available time zone library not attached to other major projects. You can look at the code that comes with the Olson Database (of time zones), and you can look at ICU (Internationalization Components for Unicode).

Resources