getFilename returns an empty string - clang

I have a SourceLocation that I wish to extract its filename from. Apparently, I should be able to do that by using SourceManager's getFilename. However, the result seems to always be an empty string when I process some header files.
I follow the source code and found that the issue is that in the getFilename function, which reads:
/// Return the filename of the file containing a SourceLocation.
StringRef getFilename(SourceLocation SpellingLoc) const {
if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc)))
return F->getName();
return StringRef();
}
The result of getFileID is somehow invalid in a sense that SLocEntry constructed from it will have isFile returning false. This causes getFileEntryForID (which does construct SLocEntry under the hood) to return a null pointer.
I have a workaround, which is:
StringRef myGetFilename(SourceLocation SpellingLoc) const {
std::pair<FileID, unsigned> locInfo = getDecomposedExpansionLoc(SpellingLoc);
if (const FileEntry *F = srcManager.getFileEntryForID(locInfo.first))
return F->getName();
return StringRef();
}
That is, call getDecomposedExpansionLoc first to get a raw FileID and use it in getFileEntryForID instead.
Experimentally, this seems to work well, but this is my first day with clang, so I'm very unsure if it's actually correct. So I have two questions:
Is this a bug in clang?
Is my workaround actually correct?
Thanks!

Ah, so the problem seems to be that getFilename expects a specific kind of SourceLocation, namely "SpellingLoc". So, change:
srcManager.getFilename(loc)
to
srcManager.getFilename(srcManager.getSpellingLoc(loc))
will fix the problem.

Related

ExpandEnvironmentStringsA() String Subscript out of range

I have a Function which checks to see if IIS is installed and gets the installation path.
int IsIISInstalled(string &pathname)
{
DWORD returnvalue;
long keyres = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\InetStp\\", 0, KEY_READ, &miva);
if (keyres == ERROR_SUCCESS)
{
char szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError;
nError = RegQueryValueExA(miva, "InstallPath", NULL, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (nError == ERROR_SUCCESS)
{
char retBuffer[512];
DWORD nsize = sizeof(retBuffer);
returnvalue = ExpandEnvironmentStringsA(szBuffer, retBuffer, nsize);
pathname = retBuffer;
}
}
if (!pathname.empty())
return 1;
else
return 0;
}
When i attach to my executable and debug this there is a return value from ExpandEnvironmentStringsA
in retBuffer showing the installation path. returnvalue shows 28 as is the TCHARS that was put in the buffer. Once i step into the next line setting the string pathname to the retBuffer it fails giving me a string subscript out of range. I understand what that error means, i have done it plenty of times. What is odd to me is if i specify a new string var in the function:
string fakeresult;
and set fakeresult to retBuffer:
fakeresult = retBuffer;
just as i am in the code above it passes through just fine with no errors. I am calling the function with this code.
string iis_path, miva_path;
int disable;
char *full_path;
//getMivaLocation(miva_path);
bool good2go;
int iisinstalled, empressaReturn, miaReturn;
iisinstalled = IsIISInstalled(iis_path);
Does this have to do with the fact i am passing pathname by reference to the function?
If that is the case why?
How could i fix this to be able to return my data?
I am not a well educated c++ coder i am learning a lot of this as i go and have learned much from you guys. Hoping someone has an idea on this as i do not wish to spend much more time researching to no avail. Thanks.
After stepping into further i found that the pathname is being set as it should. It is immediately crashing on the next call to another functions so my debugging was incorrect. Now i have scoped further hopefully i can fix this. Also for my own note, the reason why it would not crash when i set fakestring instead of pathname was due to the fact i was passing pathname in the function call that is crashing. With no value it is not setting something out of its scope.

Handling possible nil date from array of objects from db which may return a date

I'm new to objective c and have been given an existing, outsourced codebase so I apologise if I am missing something very obvious!
I have a Goal data model which I have added a date to:
When making a request to the db for an array of goals, the following is returned:
As you can see, one of the array elements returns an extra KVP which is the date type I added to the xcdatamodel previously. This date refers to the date in which the goal was completed.
When iterating over this array in a for loop and checking whether the date KVP is not nil, NULL is returned for the object in which the date exists for:
([[self.goalArray objectAtIndex:i] valueForKey:#"date"] != nil) ?
[[self.goalArray objectAtIndex:i] valueForKey:#"date"] : [NSNull null]
However, the other values in the object using the same above expression with their keys return their expected values:
It's worth noting that in order to get the app to run, I change the date xcdatamodel to a string value as opposed to date for testing purposes.
I have also added this to the Goal model:
#synthesize date;
...
-(NSDate*) date {
return date;
}
-(void) setDate:(NSDate*)DateTime {
date = DateTime;
}
Is there something obvious I'm missing as I am at a wits end?
Again I apologise if this is a bad question I cannot find any clues as to how to handle objects which may or may not return a certain KVP
You should probably use objectForKey:, that's a NSDictionary function. The valueForKey: basically works on any class and returns a value and/or function result based on the key you pass it.
I can imagine something funky happening when asking for the date.
Your code should probably look somewhat like the following:
NSDictionary *goalInfo = self.goalArray[i];
//goalInfo[#"date"] - This is the short, and more readable version of 'objectForKey:'
if (goalInfo && goalInfo[#"date"]) {
return goalInfo[#"date"];
}
else {
return [NSNull null];
}

can I switch NSString

I want to switch NSString in XmlParser because if there are 15 or more web-service then every time the loop check for correct element in IF..ELSE.That I don't want to make processor busy..
I have searched a lot and found using enum I can switch NSString but no luck ..
I have tried each possibilities,but some where i am making mistake.
Please help to solve this big problem for me.
Here I have declare my enum:
Here in "elementName" I am getting Exact value as declared in enum:
But instead of 1, I am getting wrong value Like 202896536:
You cant do it by creating enum. You must need to compare the string.
if([elementName isEqualToString:#"UserLoginComplexType"])
//Do something...
You can not cast a string to ENUM value, you will need to parse it, ENUM values are integers not strings.
You will have to use an if statement.
You could use a helper method:
WebServiceList.h
typedef NS_ENUM(NSUInteger, WebServiceList) {
WebServiceListNone = 0,
UserLoginComplexType = 1,
RegisterUserResult = 2,
RecoverPasswordResult = 3,
....
};
FOUNDATION_EXTERN WebServiceList WebServiceListForString(NSString *string);
WebServiceList.m
WebServiceList WebServiceListForString(NSString *string) {
WebServiceList list = WebServiceListNone;
if (![type isKindOfClass:[NSString class]]) {
return CallRecordTypeNone;
}
else if ([string isEqualToString:#"UserLoginComplexType"] {
list = UserLoginComplexType;
}
else if ([string isEqualToString:#"UserLoginComplexType"]) {
list = UserLoginComplexType;
}
else .....
return list;
}
As seen in your commented codes, you're parsing a XML and saving in a NSMutableArray named arrProductList in App Delegate.
After finishing the parsing of XML, the variable should contain the data in array. You should look into the variable & fetch the corresponding value. Since you didn't post any further details about parsing / XML structure, I'm unable to write some codes related to result fetching.
For easy readability and to avoid lots of if-else statements, I like to do mine as a dictionary:
(also makes it easy to update in the future when you add more to your enum)
NSString* elementName = ...;
// Default value
WebServiceList value = UserLoginComplexType;
NSDictionary* stringToEnum = #{#"UserLoginComplexType":#(UserLoginComplexType),
#"RegisterUserResult":#(RegisterUserResult),
#"RecoverPasswordResult":#(RecoverPasswordResult)};
NSNumber* enumValue = stringToEnum[elementName];
if(enumValue != nil)
value = (WebServiceList)enumValue.integerValue;

Display NSMutableArray objects as text in UITextView

Hey I am trying to display objects from NSMutableArray as text in UITextView and I am getting a problem:
Invalid operands to binary expression ('void' and 'NSString *')
Any suggestions how can it be done?
Here is the Code:
for (id obj in Mview.arrayTape)
viewTape.text = Mview.arrayTape.removeLastObject + #"/n" + viewTape.text;
viewTape is an UITextView , arrayTape is the NSMutableArray passed from another view
Any help would be much appreciated.
removeLastObject returns nothing (void) and you are appending it result to make a new string:
viewTape.text = Mview.arrayTape.removeLastObject + #"/n" +
viewTape.text;
Try this instead: (untested)
for (NSString* obj in Mview.arrayTape)
{
viewTape.text = [viewTape.text stringByAppendingFormat:#"%#\n", obj];
}
Assuming obj is a type of NSString, if it is not use its corresponding string representation.
EDIT
Another approach. not yet offered by other solutions, no need to use for loop
viewTape.text = [Mview.arrayTape componentsJoinedBy:#"\n"]
Mview.arrayTape.removeLastObject has the return type void i.e. it does not have a return value. And you cannot concatenate nothing with a string because void does not have a type (or class).
I guess what you want is this:
viewTape.text = [NSString stringWithFormat:#"%#\n%#",(NSString *)Mview.arrayTape.lastObject,viewTape.text];
You can remove the last object afterwards if intended:
[Mview.arrayTape removeLastObject];
It is because this method removeLastObject do not returns anything, look here. You should get the last object and get the string value add it (append it) to text in text view and the remove if required

libxml x path expression not interpreted

I've got the following xml text
<?xml version="1.0" encoding="UTF-8"?>
<projects type="array">
<project>
<created-on type="date">2012-01-17</created-on>
<id type="integer">8860795</id>
<last-changed-on type="datetime">2012-01-17T01:37:25Z</last-changed-on>
</project>
</projects>
So there is just one project. But I want to count the projects. In an online xpath evaluator my expression works fine and 1 is returned. But not in my libxml method. I use the following xpath expresseion:
count(/projects/project)
and the following objective c method for evaluation of the expression:
-(NSString*) getValueForXPathExpression:(NSString*) xPathExp_ andXMLDoc:(NSData*) xml
{
xmlDoc* doc = xmlParseMemory( [xml bytes], [xml length]);
const unsigned char* xPathExp = (const unsigned char*) [xPathExp_cStringUsingEncoding:NSUTF8StringEncoding];
xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( xPathExp, xpathCtx);
xmlNodeSetPtr nodeSetPtr = xpathObj->nodesetval;
NSString* value;
if( nodeSetPtr != 0 ) {
xmlNode* node = nodeSetPtr->nodeMax > 0 ? nodeSetPtr->nodeTab[0] : 0;
if( node != 0 && [[self stringFromCString:node->name] isEqualToString:#"text"] )
value = [self stringFromCString:node->content];
else
value = [NSString stringWithFormat:#"Node for xpath Exp: %# does not exist or is not of type text.", xPathExp_];
} else
value = [NSString stringWithFormat:#"nodeSetPtr for %# is null.", xPathExp_];
//XML-Parser aufräumen
xmlFreeDoc(doc);
xmlCleanupParser();
return value;
}
The return value is
nodeSetPtr for count(/projects/project) is null
What am I doing wrong here?
Edit: I checked that xpathCtx and xpathObj are not null but xpathObj->nodesetval is.
Edit2: Okay I found out. Count returns a number and not a string, therefore xpathObj->nodesetval is null but xpathObj->floatval is 1, the value I wanted. Actually quite logical since there can't be any nodeset :)
Have you checked the value of "doc" to make sure it is not NULL before trying to set up an XPath context? It looks to me like the xmlParseMemory function is expecting a null-terminated buffer, and I don't believe your [xml bytes] will provide that. Also, you don't show how your NSData containing the XML is created so it's impossible to see if you've got it encoded in a way that xmlParseMemory can handle it.
Assuming that the document is successfully being parsed, the next thing I would check is the type of the value returned from the Xpath evaluation. In this case, look at xpathObj->type. Unless the type is a nodeset (XPATH_NODESET), then getting the xpathObj->nodesetval isn't going to help you. I suspect the result type is XPATH_NUMBER, and that xpathObj->floatValue will return the correct count value of 1.
Based on the logic you have after the evaluation, it looks like you might want more than just the count though. You might just want to use an XPath of /projects/project and loop through the node set that gets returned

Resources