I'm trying to add fuzzy search to an iOS App I have built using an existing C++ implementation of double_metaphone by Maurice Aubrey http://aspell.net/metaphone/. I've renamed his main class double_metaphone.mm, set it to File Type C++ Source and got the project to build.
However I am getting a EXC_BAD_ACCESS
error after I call the DoubleMetaphone
method. Most of my App uses ARC and I see a number of memory management things in the double_metaphone.mm class. That said I am most suspicious of how I'm trying to get my answer back from the method. Here is the relevant part of double_metaphone.h (I enclose the method declaration in extern "C" as per Calling C++ method from Objective C).
void
DoubleMetaphone(const char *str,
char **codes);
Here are relavant parts of the method implementation in double_metaphone.mm
void
DoubleMetaphone(const char *str, char **codes)
{
int length;
metastring *original;
metastring *primary;
metastring *secondary;
int current;
int last;
current = 0;
/* we need the real length and last prior to padding */
length = strlen(str);
last = length - 1;
original = NewMetaString(str);
/* Pad original so we can index beyond end */
MetaphAdd(original, " ");
primary = NewMetaString("");
secondary = NewMetaString("");
primary->free_string_on_destroy = 0;
secondary->free_string_on_destroy = 0;
MakeUpper(original);
/* skip these when at start of word */
if (StringAt(original, 0, 2, "GN", "KN", "PN", "WR", "PS", ""))
current += 1;
/* Initial 'X' is pronounced 'Z' e.g. 'Xavier' */
if (GetAt(original, 0) == 'X')
{
MetaphAdd(primary, "S"); /* 'Z' maps to 'S' */
MetaphAdd(secondary, "S");
current += 1;
}
/* main loop */
while ((primary->length < 4) || (secondary->length < 4))
{
if (current >= length)
break;
switch (GetAt(original, current))
.....
a whole bunch of cases for each possible characters with if statements to pick out the different fuzzy codings and adding letters to primary and secondary as they are identified.
.....
if (primary->length > 4)
SetAt(primary, 4, '\0');
if (secondary->length > 4)
SetAt(secondary, 4, '\0');
*codes = primary->str;
*++codes = secondary->str;
DestroyMetaString(original);
DestroyMetaString(primary);
DestroyMetaString(secondary);
}
Finally here is the snippet of my code that calls this method. I import the double_metaphone.h and then in a method do the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Filtered Word";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Word *word = [self.fetchedResultsController objectAtIndexPath:indexPath];
char *codes;
NSString *wordForMetaphone = [NSString stringWithString:word.spelling];
DoubleMetaphone([wordForMetaphone UTF8String], &codes);
NSLog(@"doubleMetaphone code = %s", codes);
cell.textLabel.text = word.spelling;
return cell;
}
The log messages seems to execute with no issue, but the cell.textLable.text = word.spelling
triggers the EXC_BAD_ACCESS
error. When I step through the code I can't po word.spelling either - I'm thinking that the C++ code is blowing up my pointers/memory. But I really don't know where to start to fix it.
Notes: Initially I just passed in [word.spelling UTF*String]
but that encountered the same memory issue.
word.spelling == @"a"
the first time through the code.
When I comment out my 4 lines of code the app runs fine.
I'm also not confident I'm setting up char *codes and referencing it correctly so I'm thinking that might be contributing to the issue - shouldn't that be an array of primary and secondary?
I did change the definition of the DoubleMetaphone method from
DoubleMetaphone(char *str, char **codes)
because of a "deprecated conversion from string constant to 'char*' " warning see C++ deprecated conversion from string constant to 'char*'. There are a couple of other methods in the C++ class that I also had to switch to const char* I'm hoping that isn't part of the problem?
Please help!