The documentation for ICU states that
Starting with ICU 4.4, it is possible to set several data packages,
one per call to this function. udata_open() will look for data in the
multiple data packages in the order in which they were set.
However, I would like udata_open() to look for data in the reverse order, so that as soon as I add a new udata_setCommonData, I can overwrite any previous data with my new data. Obviously if an object which uses data has been instantiated, it will use the old set, but any new data should use the new data. I'm guessing that the answer is somewhere in udata.cpp near doLoadFromCommonData, hopefully it is not too complicated to make this change. In that function, I see
if (!isICUData) {
return NULL;
} else if (pCommonData != NULL) {
++commonDataIndex; /* try the next data package */
} else if ((!checkedExtendedICUData) && extendICUData(subErrorCode)) {
checkedExtendedICUData = TRUE;
/* try this data package slot again: it changed from NULL to non-NULL */
} else {
return NULL;
I suspect I want to start at the top and use --commonDataIndex instead.
Update. I discovered that I can also swap out the contents as long as the pointer is the same and re-run udata_setCommonData. Perhaps this is a good solution that avoids having to modify the ICU code. Just need to allocate the maximum possible size I might encounter - which .. perhaps might be trickier.
Alternatively, a way to unsetCommonData might be good too.
Or, making storing a pointer to a pointer to the data instead of the pointer to the data in
for (i = 0; i < LENGTHOF(gCommonICUDataArray); ++i) {
if (gCommonICUDataArray[i] == NULL) {
gCommonICUDataArray[i] = newCommonData;
ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup);
didUpdate = TRUE;
break;
} else if (gCommonICUDataArray[i]->pHeader == pData->pHeader) {
/* The same data pointer is already in the array. */
break;
}
The only safe (or sane) way to do this is to call u_cleanup() and start over. Otherwise this is not good usage of ICU at all, and highly un-recommended. Sorry.
If you want to dynamically update data, make a feature request, or better yet contribute the code for it.
Related
I have an if statement which needs to check for the existence of a value in a nested Option. The statement currently looks like
if my_vec.get(0).is_some() && my_vec.get(0).unwrap().is_some() {
// My True Case
} else {
// My Else Case
}
I feel like this is an amateurish way of checking if this potential nested value exists. I want to maintain safety when fetching the Option from the array as it may or may not exist, and also when unwrapping the Option itself. I tried using and_then and similar operators but haven't had any luck.
I would check the length first and access it like a regular array instead of using .get(x) unless there is some benefit in doing so (like passing it to something which expects an option).
if my_vec.len() > x && my_vec[x].is_some() {
// etc
}
Another option is to just match the value with an if let x = y or full match statement.
if let Some(Some(_)) = my_vec.get(x) {
// etc
}
The matches! macro can also be used in this situation similarly to the if let when you don't need to take a reference to the data.
if matches!(my_vec.get(x), Some(Some(_))) {
// etc
}
Or the and_then version, but personally it is probably my least favorite since it is longer and gargles the intention.
if my_vec.get(x).and_then(|y| y.as_ref()).is_some() {
// etc
}
You can pick whichever one is your favorite. They all compile down to the same thing (probably, I haven't checked).
So I recently got a hold of RapidXML to use as a way to parse XML in my program, I have mainly been using it as a way to mess around but I have been getting some very weird issues that I'm really struggling to track down. Try and stick with me through this, because I was pretty thorough with trying to fix this issue, but I must be missing something.
First off here's the XML:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<image key="tilemap_roguelikesheet" path="res/media/tilemaps/roguelikesheet.png" />
<image key="tilemap_tiles" path="res/media/tilemaps/tiles.png" />
</resources>
The function the segfault occurs:
void TextureManager::LoadResource(const char* pathToFile)
{
rapidxml::xml_document<>* resource = Resources::LoadResource(pathToFile);
std::string imgName;
std::string imgPath;
if (resource != NULL)
{
rapidxml::xml_node<>* resourcesNode = resource->first_node("resources");
if (resourcesNode != NULL)
{
for (rapidxml::xml_node<>* child = resourcesNode->first_node("image"); child; child = child->next_sibling())
{
//Crash here on the second loop through.
imgName = child->first_attribute("key")->value();
imgPath = child->first_attribute("path")->value();
Astraeus::Log(moduleName, "Image Name: " + imgName);
Astraeus::Log(moduleName, "Image Path: " + imgPath);
TextureManager::AddTexture(imgName, imgPath);
}
}
else
{
Astraeus::Error(moduleName, "Resources node failed to load!");
}
resource->clear();
}
else
{
std::string fileName(pathToFile);
Astraeus::Error(moduleName, fileName + " could not be loaded.");
}
}
So segfault happens on the second loop of the for loop to go through all the nodes, and triggers when it tries to do the imgName assignment. Here's where things get a bit odd. When doing a debug of the program, the initial child nodes breakdown shows it has memory pointers to the next nodes and it's elements/attributes etc. When investigating those nodes, you can see that the values exist and rapidxml has seemingly successfully parsed the file.
However, when the second loop occurs, child is shown to still have the exact same memory pointers, but this time the breakdown in values show they are essentially NULL values, so the program fails and we get the code 139. If you try and look at the previous node, that we have just come from the values are also NULL.
Now say, I comment out the line that calls on the AddTexture function, the node is able to print out all the nodes values no problems at all. (The Log method is essentially just printing to console until I do some more funky stuff with it.) so the problem must lie in the function? Here it is:
void TextureManager::AddTexture(const std::string name, const std::string path)
{
Astraeus::Log(moduleName, "Loading texture: " + path);
if (texturesLookup.find(name) != texturesLookup.end())
{
Astraeus::Error(moduleName, "Texture Key: " + name + " already exists in map!");
}
else
{
texturesLookup.insert(std::make_pair(name, path));
//Texture* texture = new Texture();
/*if (texture->LoadFromFile(path))
{
//textures.insert(std::make_pair(name, texture));
}
else
{
Astraeus::Error(moduleName, "Failed to add texture " + name + " to TextureManager!");
}*/
}
}
Ignoring the fact that strings are passed through and so should not affect the nodes in any way, this function is still a bit iffy. If I comment out everything it can work, but sometimes just crashes out again. Some of the code got commented out because instead of directly adding the key name, plus a memory pointer to a texture, I switched to storing the key and path strings, then I could just load the texture in memory later on as a workaround. This solution worked for a little bit, but sure enough began to segfault all over again.
I can't really reliably replicate or narrow down what causes the issue everytime, so would appreciate any help. Is RapidXML doc somehow going out of scope or something and being deleted?
For the record the class is practically just static along with the map that stores the texture pointers.
Thanks!
So for anybody coming back again in the future here's what was happening.
Yes, it was a scope issue but not for the xml_document as I kept initially thinking. The xml_file variable that was in the resources load function was going out of scope, which meant due to the way RapidXML stores things in memory, as soon as that goes out of scope then it frees up the memory, which led to the next time dynamic allocation happened by a specific function it would screw up the xml document and fill it with garbage data.
So I guess the best idea is to make sure xml_file and xml_document do not go out of scope. I have added some of the suggestions from previous answers, but I will point out those items WERE in the code, before being removed to help with the debug process.
Thanks everybody for the help/advice.
I'm not sure, but I think that Martin Honnen made the point.
If next_sibling() return the pointer to the text node between the two "image" elements, when you write
imgName = child->first_attribute("key")->value();
you obtain that child->first_attribute("key") is a null pointer, so the ->value() is dereferencing a null pointer. Crash!
I suppose you should get the next_sibling("image") element; something like
for (rapidxml::xml_node<>* child = resourcesNode->first_node("image");
child;
child = child->next_sibling("image"))
And to be sure not to use a null pointer, I strongly suggest you to check the attribute pointers (are you really sure that "image" elements ever carry the "key" and the "path" elements?); something like this
if ( child->first_attribute("key") )
imgName = child->first_attribute("key")->value();
else
; // do something
if ( child->first_attribute("path") )
imgPath = child->first_attribute("path")->value();
else
; // do something
p.s.: sorry for my bad English.
This line is setting my teeth on edge...
rapidxml::xml_document<>* resource = Resources::LoadResource(pathToFile);
LoadResource returns a pointer, but you never free it anywhere...?
Are you 100% sure that function isn't returning a pointer to an object that's now gone out of scope. Like this classic bug...
int * buggy()
{
int i= 42;
return &i; // UB
}
As #max66 says. You should use next_sibling("image"). If that's failing, you need to find out why.
I'm trying to create an interface between physical components (Arduinos) and flight simulator in order to control and display simulator events from self-built parts. I have started learning C++ in school, but have never been quite keen on it.
Yet the library I use to communicate with my flight simulator is written in C++ (it's called SimConnect) and so is the SDK of my payware airplane. Therefore I figured it's probably easier to get back into it than creating wrappers or such for another programming language.
Every time I receive new data from the simulator, I pass it into the function ProcessNGXData:
PMDG_NGX_Data* previousData;
bool alreadyProcessed = false;
void ProcessNGXData(PMDG_NGX_Data *data)
{
if (!alreadyProcessed || data->LTS_TaxiSw != previousData->LTS_TaxiSw) {
if (data->LTS_TaxiSw)
printf("Taxi Lights: [ON]\n");
else
printf("Taxi Lights: [OFF]\n");
}
if (!alreadyProcessed) {
alreadyProcessed = true;
}
previousData = data;
}
In other programming languages, this would probably work fine, hence I tried to implement it like this. However, C++ pointers are a slight bit more complicated to me.
The condition data->LTS_TaxiSw != previousData->LTS_TaxiSw never evaluates to true. From my understanding, that is because both data and previousData are pointers to exactly the same structure and thus can never be different.
With my little knowledge and not much understanding of those pointers, how would I do this? Is there a way to copy the structure, so they can differ?
Thanks in advance.
Declare previousData like this:
PMDG_NGX_Data previousData;
(without the asterisk). Now, when you want to 'save' the structure, do this:
previousData = *data;
(right hand side has an asterisk). Note that this assumes that PMDG_NGX_Data is copy-able and a fixed size. If it's an interface or an abstract class, then this won't be possible. Perhaps the API gives you a "Clone" or "Copy" method you can call.
If PMDG_NGX_Data is not too big to copy every ProcessNGXData you can try this:
PMDG_NGX_Data previousData;
bool alreadyProcessed = false;
void ProcessNGXData(PMDG_NGX_Data *data)
{
if (!alreadyProcessed || data->LTS_TaxiSw != previousData.LTS_TaxiSw) {
if (data->LTS_TaxiSw)
printf("Taxi Lights: [ON]\n");
else
printf("Taxi Lights: [OFF]\n");
}
if (!alreadyProcessed) {
alreadyProcessed = true;
}
previousData = *data;
}
If it is too big, you can create a struct that will hold only the fields you need to compare and will be initialized by PMDG_NGX_Data and initialize that struct every ProcessNGXData.
A method is returning a list of persons, which might be empty.
Is it better to return an empty list or just null?
Some might find this as an opinion question, but I want to know what is the best strategy for a new application?
public List<PersonEntity> findByName(List<String> names) {
List<PersonEntity> list = new ArrayList<PersonEntity>();
...JPA-stuff getting that list
return list;
}
Returning null. Is a null easier to handle further on?
public List<PersonEntity> findByName(List<String> names) {
List<PersonEntity> list = null;
...JPA-stuff getting that list
return list;
}
I feel like this may in turn be an opinion question, but I like returning the empty set and avoid having to handle null if it can be.
It all depends on what you do with this list, but lets say once you get the list back you need to iterate through it.
If its the empty set, you try to iterate, it doesn't see anything in the list, your okay.
result = findByName(names);
//...safe to loop through result
If its null, you try to iterate, you get an exception, and therefore need to check null first and add special handling.
result = findByName(names);
if (result != null)
{
//...handle stuff (now it is safe to loop through result)
}
else
{
//..special handling if needed
}
All in all, it depends what you are doing with the data, and if you can get away with not checking for empty set such as in my first example.
I'm sorry if the title isn't very explicit, but I'll try to explain it better. I'm not very familiar with c++ and I'm using openFrameworks for the first time. I'm trying to do something that's probably quite easy, at least in other languages it is, but I'm not being able to do it :(
I have a class Video and inside it I have an object list<ofImage> keyFrames; and several methods to interact with it like the following:
void addKeyFrame(ofImage img) {
if(keyFrames.size() == 0) {
keyFrames.push_front(img);
}
else {
keyFrames.push_back(img);
}
}
list<ofImage> * getKeyFrames() {
list<ofImage> *list = &keyFrames;
return list;
}
void clearKeyFrames() {
keyFrames.clear();
}
In other class I have several Video objects and I have a function that uses addKeyFrame(ofImage img) to fill the list for each object. In the end of that function if I print the list size it is greater than zero.
Inside draw() function I iterate each Video object and I try to draw each image inside their keyFrame list, but the list is always empty and I just filled it with images... I'm using getKeyFrames() function to return a pointer to the list. How can it be empty if I just added objects to it in another function and if I verified that the size was greater than zero? And if I try to debug the application I feel even more lost lol.
Please tell me if you need anymore information and if you know what I'm doing wrong. Thanks!
Ok, A few little things:
1- You shouldn't check for empty lists (or any other STL containers) like this:
if(keyFrames.size() == 0)
This is faster and more "stylish":
if(keyFrames.empty())
2- You've created an unnecessary variable here:
list<ofImage> * getKeyFrames() {
list<ofImage> *list = &keyFrames;
return list;
}
You could do just:
list<ofImage> * getKeyFrames() {
return &keyFrames;
}
3- Pointers are not (most times) the best solution in C++. A reference is the most used substitute, but it would be even better in htis case if you returned an iterator:
list<ofImage>::iterator GetBeginIterator() {
return keyFrames.begin();
}
This way you could use the iterator just like a pointer, increasing it to iterate trough the frames and dereferencing it (with * operator)...