CFLocaleCopyCurrent stale value - c++

At my workplace, our app determines the locale of the user session by using a code that is similar to below (though there are various layers of code it passes through before it reaches here at the time of startup, so the problem is/may not evident by running the code below)
#include <CoreFoundation/CoreFoundation.h>
#include <iostream>
#include <string>
#include <vector>
#include <memory>
// Reference release
struct reference_close
{
void operator()(const void *ref) const
{
CFRelease(static_cast<CFTypeRef>(ref));
}
}; // end of reference_close structure
typedef std::unique_ptr<const void, reference_close> reference_uptr;
std::string get_user_locale()
{
reference_uptr ref_ptr(CFLocaleCopyCurrent());
CFLocaleRef locale_ref(static_cast<CFLocaleRef>(ref_ptr.get()));
if (locale_ref == nullptr)
{
return std::string();
}
const size_t default_size(128);
std::vector<char> buff(default_size);
CFStringRef str_ref(CFLocaleGetIdentifier(locale_ref));
if (str_ref != nullptr)
{
CFIndex len(CFStringGetLength(str_ref) + 1);
if (len > boost::numeric_cast<CFIndex>(default_size))
{
buff.resize(len);
}
buff[0] = 0;
if (!CFStringGetCString(str_ref, &buff[0], len, kCFStringEncodingISOLatin1))
{
return std::string();
}
}
return std::string(&buff[0]);
} // end of get_user_locale()
int main()
{
std::cout << "get_user_locale() : "<<get_user_locale() << std::endl;
return 0;
}
The app has a well defined bundle structure with necessary resources and localization resource directories e.g Contents/Resources/ja.lproj
Lately, we are facing an issue wherein we do the following
1) Change the system language and country in the preferences e.g. change from en_US to ja_JP
2) Reboot the machine
3) Launch the app and see the erroneous output e.g en_JP
4) Re-launch the app to get the correct answer as ja_JP
I have read the documentation of CFLocaleCopyCurrent which states that
Settings you get from this locale do not change as a user's
preferences are changed so that your operations are consistent.
Typically you perform some operations on the returned object and then
release it. Since the returned object may be cached, you do not need
to hold on to it indefinitely.
I also checked the another documentation on lifetime of CFLocale which states that
The object you get back from CFLocaleCopyCurrent does not change when
the user changes their Preferences settings. Moreover, the object
itself may be cached by the runtime system, so successive calls of
CFLocaleCopyCurrent may return the same object, even if a user has
changed preference settings. If you want to ensure that your locale
settings are consistent with user preferences, you must synchronize
preferences and get a new locale object with CFLocaleCopyCurrent.
Given this info, I tried to incorporate CFPreferencesSynchronize and/or CFPreferencesSynchronize in the app code (just before I call the CFLocaleCopyCurrent) to get the most updated locale. But no luck.
Do I need to do anything extra to make sure that I get the most recent/updated value of locale object from the system preferences ?

Use [NSLocale autoupdatingCurrentLocale] which will change as the user changes their locale settings, but as NSLocale is an Objective-C class you will need to implement glue code as Objective-C++.
Here is some untested example code, giving you the idea:
Create a file called AppleLocale.mm (unless of course your project is for Apple platforms only so doesn't need the Apple name prefix).
#include <Foundation/Foundation.h>
std::string get_user_locale()
{
NSLocale* locale = [NSLocale autoupdatingCurrentLocale];
return std::string([[locale localeIdentifier] UTF8String]);
}
Note: You'll need a function prototype in some header as well, of course.

Related

How to make code detect if a file exists or not in C++ 17?

I am new to C++ and I want to make my first game. I want to make a simple savegame system for it but I am struggling to make it see if a savegame already exists or not.
What I have for now
#include <iostream>
#include <time.h>
#include <windows.h>
#include <fstream>
using namespace std;
int main()
{
/*command goes here*/ {
cout<<"<System>: Welcome! Please register."<<endl;
cout<<"(TIP: Username and password can be anything. Both will be saved in your savegame [Savegame.txt] and you will be automatically logged in.)"<<endl;
Sleep(2000);
ofstream ("Savegame.txt");
ofstream fout;
fout<<"Username: ";
cin>>name;
cout<<name<<endl;
cout<<endl;
cout<<"Password: ";
cin>>password;
fout<<password<<endl;
}
else
{
cout<<"<System>: Welcome back!"<<endl;
ifstream fin;
fin>>name;
fin>>password;
}
return 0;
}
Please help I am trying to do this for a week :(
You need to #include <filesystem> and then use the appropriate function, e.g.
const bool exists = std::filesystem::exists("myfile.txt");
It might also make sense to narrow the query a bit, as in
const bool exists = std::filesystem::is_regular_file("myfile.txt");
The latter subsumes the existance of the file.
use the exists method:
std::filesystem::exists
example:
const bool exists = std::filesystem::is_regular_file("myfile.txt");
Eventually, if you want to target older versions of C++, you can open the file in read mode, then check if it's open or not.
If it's open, it exists and you have your answer, otherwise it may be non-existent or have some kind of error during opening.
If so, you can try to open it in another mode and verify if it fails again or not, to rule out or verify your guess.
At least, that's what i did before standard version 17 (from C++11 in this example constrained by raw string in path which can be removed simply escaping the path).
e.g.
string path = R"(...<my path>...)";
std::fstream fp;
fp.open(path, std::fstream::in);
if (fp.is_open()) {
// file exists
fp.close();
}
else {
fp.open(path, std::fstream::out);
if (fp.is_open()) {
// file has been created
fp.close();
}
else {
// other error occurred
}
}
As already pointed out, Filesystem Cpp official reference allows you to have the full range of operations available, for this particular instance:
bool exists( const std::filesystem::path& p );
bool exists( const std::filesystem::path& p, std::error_code& ec ) noexcept;
If you use std::filesystem::exists without error code, be careful to catch and eventual std::filesystem::filesystem_error (could happen trying to inspect files in removable devices or if special conditions applies).
bool existing_save = std::filesystem::exists("Savegame.txt");
What i think you may missing is to correctly configure Visual Studio to use the right C++ set, which can be done by clicking menu Project -> "your project name" Properties that will open a window in which you can edit General properties -> C++ Language Standard and set C++17 instead of the default C++14.
You can see what to do in the image below, hoping this could help you:

Ensure key/value of enumerable type never changes between software revs

We have a client/server application where older servers are supported by newer clients. Both support a shared set of icons.
We're representing the icons as an implicit enum that's included in the server and client builds:
enum icons_t { // rev 1.0
ICON_A, // 0
ICON_B, // 1
ICON_C // 2
};
Sometimes we retire icons (weren't being used, or used internally and weren't listed in our API), which led to the following code being committed:
enum icons_t { // rev 2.0
ICON_B, // 0
ICON_C // 1 (now if a rev 1.0 server uses ICON_B, it will get ICON_C instead)
};
I've changed our enum to the following to try and work around this:
// Big scary header about commenting out old icons
enum icons_t { // rev 2.1
// Removed: ICON_A = 0,
ICON_B = 1,
ICON_C = 2
};
Now my worry is a bad merge when multiple people add new icons:
// Big scary header about commenting out old icons
enum icons_t { // rev 30
// Removed: ICON_A = 0,
ICON_B = 1,
ICON_C = 2,
ICON_D = 3,
ICON_E = 3 // Bad merge leaves 2 icons with same value
};
Since it's an enum we don't really have a way to assert if the values aren't unique.
Is there a better data structure to manage this data, or a design change that wouldn't be open to mistakes like this? My thoughts have been going towards a tool to analyze pull requests and block merges if this issue is detected.
I have previously done tests that check out previous builds and scan header files for this type of version-breaking behaviour. You can use diff to generate a report of any changes, grep that for the common pattern, and identify the difference between deleting a fixed-index entry, changing the index of an entry, and deleting or inserting a floating index entry.
The one obvious way to avoid it is to NOT remove the dead indices, but rename them, i.e. ICON_A becomes ICON_A_RETIRED, and its slot is reserved for ever. It is inevitable that someone will change an index, though, so a good unit test would also help. Forcing a boilerplate style means the test is simpler than coping with the generic case.
Another trick might be to accept that the issue will occur, but if it is only a problem for customers, and at each software release/revision, update a base number for the range, release the software and update again, so the dev version is never compatible with the release, eg
#define ICON_RANGE 0x1000
#define ICON_REVISION_BASE ((RELEASENUM+ISDEVFLAG)*ICON_RANGE)
enum icon_t {
iconTMax = ICON_REVISION_BASE+ICON_RANGE,
iconTBase = ICON_REVISION_BASE,
icon_A,
icon_B,
Then, at run-time, any icons not in the current range are easily rejected, or you might provide a special look-up between versions, perhaps generated by trawling your version control revisions. Note that you can only provide backward compatibility this way, not forward compatibility. It would be up to newer code to preemptively back-translate their icon numbers to send to older modules, which may be more effort than it is worth.
This thought just crossed my mind: if we keep a literal at the end for the enum size, our unit tests can use that to assert if we haven't verified each enum literal:
enum icons_t {
ICON_A_DEPRECATED,
ICON_B,
ICON_C,
ICON_COUNT // ALWAYS KEEP THIS LAST
};
Then in testing:
unsigned int verifyCount = 0;
verify(0, ICON_A_DEPRECATED); // verifyCount++, assert 0 was not verified before
verify(1, ICON_B); // verifyCount++, assert 1 was never verified before
assert(ICON_COUNT == verifyCount, "Not all icons verified");
Then our only problem is ensuring tests pass before releasing, which we should be doing anyway.
Since the question has been tagged C++11, this could be better handled with Scoped enumerations.
Read about it here : http://en.cppreference.com/w/cpp/language/enum
Since the same enum file is included in both client and server, then removing any entry would lead to compilation failure in places a missing entry is being used.
All that need to be changed, is your icon_t.
Upgrade it from enum to enum class
enum class icon_t
{
ICON_A,
ICON_B,
};
Now you can't blatantly pass int instead of an icon_t. This reduces your probability to make mistakes drastically.
So the calling side
#include <iostream>
enum class icon_t
{
ICON_A,
ICON_B,
};
void test_icon(icon_t const & icon)
{
if (icon == icon_t::ICON_A)
std::cout << "icon_t::ICON_A";
if (icon == icon_t::ICON_B)
std::cout << "icon_t::ICON_B";
}
int main()
{
auto icon = icon_t::ICON_A;
test_icon(icon); // this is ok
test_icon(1); // Fails at compile time : no known conversion from 'int' to 'const icon_t' for 1st argument
return 0;
}
Moreover, extracting numerical values is allowed from Scoped Enumerators. static_cast to int is allowed. If required.
int n = static_cast<int>(icon); // Would return 0, the index of icon_t::ICON_A

GetEnvironmentVariableA() usage

I am working on a C++ Console Application in Visual Studio 2012 on Windows 7 and I want to get the values of some environment variables from within the application.
Here is what I've tried so far -:
int main()
{
char a[1000];
int s=GetEnvironmentVariableA("HOME",a,1000);
}
However, I am getting the value of s to be 0, indicating that variable "HOME" does not exist.
Also, getenv("HOME") returns NULL too.
So, what is the correct procedure of doing this ?
What this program is telling you, most likely, is that your process environment does not contain a variable named HOME. Note that HOME is not a variable that you would expect to be defined, unless you have taken steps to define it. Either by adding it to the system's environment, or by specifying a bespoke environment when creating the process.
The documentation says the following about the return value:
If the function succeeds, the return value is the number of characters
stored in the buffer pointed to by lpBuffer, not including the
terminating null character.
If lpBuffer is not large enough to hold the data, the return value is
the buffer size, in characters, required to hold the string and its
terminating null character and the contents of lpBuffer are undefined.
If the function fails, the return value is zero. If the specified
environment variable was not found in the environment block,
GetLastError returns ERROR_ENVVAR_NOT_FOUND.
So, if the function returns 0, do as the documentation says. Call GetLastError to find out why the function call failed.
But as I said, with probability very close to 1, the reason will simply be that your process environment has not defined a variable named HOME.
As to how you move forward, most likely you are looking for a location in the user's profile. Exactly how you do this will depend on where in the profile you wish to store/load the file. One of the APIs related to CSIDL or known folder IDs will serve your needs.
Regarding your question,
” So, what is the correct procedure of doing this ?
Windows doesn't have a single HOME standard variable. Instead, in the old days there were HOMEDRIVE and HOMEPATH, and apparently because they didn't know about it, with Windows Explorer in Windows 95, a new variable called USERPROFILE.
[C:\Users\alfps_000]
> set home
HOMEDRIVE=C:
HOMEPATH=\Users\alfps_000
[C:\Users\alfps_000]
> set user
USERDOMAIN=FRIKADELL
USERDOMAIN_ROAMINGPROFILE=FRIKADELL
USERNAME=alfps_000
USERPROFILE=C:\Users\alfps_000
[C:\Users\alfps_000]
> _
The silly triple-oh suffix (as if I were better than double-oh seven) is just what Windows 8.1 saw fit to give me. It's just too much work to cajole Windows into reasonable choices. And so not just with usernames but also with environment variables.
Here's your program rewritten to use the Windows variable that vaguely corresponds to Unix-land HOME, namely USERPROFILE:
#include <iostream>
#include <stdlib.h> // getenv
using namespace std;
auto main() -> int
{
cout
<< "User's profile directory: "
<< "[" << getenv( "USERPROFILE" ) << "]"
<< endl;
}
The Windows environment variables are awkward and not guaranteed, but still usable in scripts and very simple programs like the one above. In more serious C++ code you can instead use the SHGetKnownFolderPath API function. With Visual C++ it can look like this:
#undef UNICODE
#define UNICODE
#include <windows.h>
#include <shlobj.h> // SHGetKnownFolderPath
#include <objbase.h> // CoTaskMemFree
#include <iostream> // std::wcout
#include <memory> // std::unique_ptr
#include <stdexcept> // std::runtime_error, std::exception
#include <stdlib.h> // EXIT_FALURE, EXIT_SUCCESS
using namespace std;
void cotaskmem_free( wchar_t* p ) { CoTaskMemFree( p ); }
auto main() -> int
{
using X = runtime_error;
using String_deallocation = unique_ptr<wchar_t[], void(*)(wchar_t*)>;
try
{
wchar_t* path;
HRESULT const hr = SHGetKnownFolderPath(
FOLDERID_Profile, // REFKNOWNFOLDERID rfid -> %USERPROFILE%
0, // DWORD dwFlags,
0, // HANDLE hToken,
&path // PWSTR *ppszPath
);
if( FAILED( hr ) ) { throw X( "SHGetKnownFolderPath failed" ); }
String_deallocation const path_cleanup( path, cotaskmem_free );
wcout << "User profile directory: [" << path << "]" << endl;
return EXIT_SUCCESS;
}
catch( exception const& x )
{
wcerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
g++ (per version 4.8.2) doesn't yet support API functions from Windows Vista and onward, at least not in general, so if you need to support g++ use some older function.
Note:
It's not unlikely that whatever you intended to access or place in %HOME%, would better be accessed or placed in one of the other special users's directories, also available via SHGetKnownFolderPath.

Segmentation fault when creating custom tcl channel driver

I am trying to create custom tcl channel and use it to get the output of tcl Interpreter. I added the implementation of few function of Tcl_ChannelType but I am getting segfault.
#include <tcl.h>
#include <iostream>
int driverBlockModeProc(ClientData instanceData, int mode) {
std::cout << "driverBlockModeProc\n";
return 0;
}
int driverCloseProc(ClientData instanceData, Tcl_Interp *interp) {
std::cout << "driverCloseProc\n";
return 0;
}
int driverInputProc(ClientData instanceData, char* buf, int bufSize, int *errorCodePtr) {
std::cout << "driverInputProc\n";
return 0;
}
int driverOutputProc(ClientData instanceData, const char* buf, int toWrite, int *errorCodePtr) {
std::cout << "driverOutputProc\n";
return 0;
}
int main() {
Tcl_ChannelType *typePtr = new Tcl_ChannelType;
typePtr->blockModeProc = driverBlockModeProc;
typePtr->outputProc = driverOutputProc;
typePtr->closeProc = driverCloseProc;
typePtr->inputProc = driverInputProc;
typePtr->seekProc = NULL;
typePtr->setOptionProc = NULL;
typePtr->getOptionProc = NULL;
typePtr->watchProc = NULL;
typePtr->getHandleProc = NULL;
typePtr->close2Proc = NULL;
typePtr->blockModeProc = NULL;
typePtr->flushProc = NULL;
typePtr->handlerProc = NULL;
typePtr->wideSeekProc = NULL;
typePtr->threadActionProc = NULL;
ClientData data = new char[200];
Tcl_CreateChannel(typePtr, "im_chanel", data, TCL_WRITABLE | TCL_READABLE);
}
I cant debug the segfault because its source are not available. I think the segfault is because a function is called which is NULL. I only need to use the channel to get the output of interpreter. Which functions I needn't implement here and is it right direction to solve the problem.
You're advised to download the source to Tcl when working at this level. I'm not sure what version you're using, but all official distributions of the source going back a very long way are on the SourceForge file distribution system; pick the exact match for the version you've got.
Creating a custom channel driver is not easy. There's a significant amount of complexity involved, and it isn't especially well-documented what “methods” within the channel driver type are mandatory and what are optional. (They're not C++ methods in a class — Tcl is pure C code for reasons too long to go into here — but they function in a conceptually similar way.)
If we look at the documentation for Tcl_CreateChannel, we see (quite a long way down that page) a definition of the channel type structure. The channel type structure should be statically allocated (Tcl's implementation assumes very strongly that it never changes location) and the following fields must be set to something meaningful:
typeName — This is the name of the channel type, useful for debugging!
version — This is the version of the channel type; you should set it to the latest version supported by your target source level. (You're recommended to use at least TCL_CHANNEL_VERSION_2 or things get rather more complex.)
closeProc or close2Proc — Channels must be closeable, but you have two choices for ways to do it. Bidirectional channels ought to use the close2Proc, but aren't strictly required to.
inputProc — Only needed if you're reading; take care to handle this correctly.
outputProc — Only needed if you're writing; take care to handle this correctly.
watchProc — Called to tell the channel driver to install itself into the event system so as to receive suitable events (as instructed by the supplied bitmask). Channels that don't have backing OS handles use timer events, or simply never actually generate events (in which case they'll never become readable or writable from the perspective of fileevent).
Looking at your code, I see that you're missing a watchProc. I know it's hard to see (not many people write channel drivers, to be honest, so the documentation isn't very hard “tested”) but it's really necessary.

C++ MySQL++ Delete query statement brain killer question

I'm relatively new to the MySQL++ connector in C++, and have an really annoying issue with it already!
I've managed to get stored procedures working, however i'm having issues with the delete statements. I've looked high and low and have found no documentation with examples.
First I thought maybe the code needs to free the query/connection results after calling the stored procedure, but of course MySQL++ doesn't have a free_result method... or does it?
Anyways, here's what I've got:
#include <iostream>
#include <stdio.h>
#include <queue>
#include <deque>
#include <sys/stat.h>
#include <mysql++/mysql++.h>
#include <boost/thread/thread.hpp>
#include "RepositoryQueue.h"
using namespace boost;
using namespace mysqlpp;
class RepositoryChecker
{
private:
bool _isRunning;
Connection _con;
public:
RepositoryChecker()
{
try
{
this->_con = Connection(false);
this->_con.set_option(new MultiStatementsOption(true));
this->_con.set_option(new ReconnectOption(true));
this->_con.connect("**", "***", "***", "***");
this->ChangeRunningState(true);
}
catch(const Exception& e)
{
this->ChangeRunningState(false);
}
}
/**
* Thread method which runs and creates the repositories
*/
void CheckRepositoryQueues()
{
//while(this->IsRunning())
//{
std::queue<RepositoryQueue> queues = this->GetQueue();
if(queues.size() > 0)
{
while(!queues.empty())
{
RepositoryQueue &q = queues.front();
char cmd[256];
sprintf(cmd, "svnadmin create /home/svn/%s/%s/%s", q.GetPublicStatus().c_str(),
q.GetUsername().c_str(), q.GetRepositoryName().c_str());
if(this->DeleteQueuedRepository(q.GetQueueId()))
{
printf("query deleted?\n");
}
printf("Repository created!\n");
queues.pop();
}
}
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
//}
}
protected:
/**
* Gets the latest queue of repositories from the database
* and returns them inside a cool queue defined with the
* RepositoryQueue class.
*/
std::queue<RepositoryQueue> GetQueue()
{
std::queue<RepositoryQueue> queues;
Query query = this->_con.query("CALL sp_GetRepositoryQueue();");
StoreQueryResult result = query.store();
RepositoryQueue rQ;
if(result.num_rows() > 0)
{
for(unsigned int i = 0;i < result.num_rows(); ++i)
{
rQ = RepositoryQueue((unsigned int)result[i][0],
(unsigned int)result[i][1],
(String)result[i][2],
(String)result[i][3],
(String)result[i][4],
(bool)result[i][5]);
queues.push(rQ);
}
}
return queues;
}
/**
* Allows the thread to be shut off.
*/
void ChangeRunningState(bool isRunning)
{
this->_isRunning = isRunning;
}
/**
* Returns the running value of the active thread.
*/
bool IsRunning()
{
return this->_isRunning;
}
/**
* Deletes the repository from the mysql queue table. This is
* only called once it has been created.
*/
bool DeleteQueuedRepository(unsigned int id)
{
char cmd[256];
sprintf(cmd, "DELETE FROM RepositoryQueue WHERE Id = %d LIMIT 1;", id);
Query query = this->_con.query(cmd);
return (query.exec());
}
};
I've removed all the other methods as they're not needed...
Basically it's the DeleteQueuedRepository method which isn't working, the GetQueue works fine.
PS: This is on a Linux OS (Ubuntu server)
Many thanks,
Shaun
MySQL++ doesn't have a free_result method... or does it?
It doesn't need one. When the result object goes out of scope at the end of GetQueue(), all memory associated with it is automatically freed.
this->_con = Connection(false);
Three problems here:
When you create the RepositoryChecker object, you already have created a Connection object. If you need to pass different parameters to its constructor, you'd do that in the initialization list of the RepositoryChecker constructor, not in its body. Read your C++ book.
What you've done here instead is a) create a default Connection object, then b) create a different Connection object with exceptions turned off, then c) overwrite the first with the second. If that works, it's highly inefficient. MySQL++ Connection objects have had problems with their copy ctors in the past, so if you're using an old version of the library, it could explain your problems.
You're telling the Connection object (and every object it creates, even indirectly, which means pretty much everything in MySQL++) you don't want it to throw exceptions, but then you wrap it in a big try block. Pick one.
I'd suggest using exceptions — the default in MySQL++ — given the way your code is currently structured. If there is a query error way down in DeleteQueuedRepository(), there's no way to see what happened because you'd just pass false up to the caller, which is ignored because there is no else clause on the call. If you do this, log the e.what() message in your catch block. You're just throwing that information away right now.
There are several places where you're using constructs that look more like Python (or perhaps JavaScript) than C++. This makes me wonder if your problem isn't damage caused by some other misuse of C++.
On this line in particular, you're using the this pointer explicitly, for which there is no need in C++. This code does exactly the same thing:
_con = Connection(false);
Though again, the line should be replaced entirely, using the RepositoryChecker ctor initializer list instead.
Moving on...
sprintf(cmd, "DELETE FROM RepositoryQueue WHERE Id = %d LIMIT 1;", id);
As others have commented, you'd be better off using the Query stream interface:
Query q = _con.query();
q << "DELETE FROM RepositoryQueue WHERE Id = " << id << " LIMIT 1";
This has several advantages:
Fixes the type safety problem implied by the one who suggested changing your %d to %u. C++ IOStreams take care of that for you.
Automatic quoting of data inserted into the stream, if needed. (Which it isn't, in this case.)
Prevents any possibility of running off the end of the buffer. You could use the nonportable snprintf() instead here, but why?
If you're really happy with printf(), there's the template query interface instead.
boost::this_thread::sleep(boost::posix_time::milliseconds(500));
Have you read the threads chapter in the user manual? You don't get thread safety for free in MySQL++. Your problem could be due to memory corruption.
Warren Young, MySQL++ Maintainer
Try changing "%d" to "%u" in sprintf.