Help in porting my AppleScriptObjC handler to plain ObjectiveC

Dear friends,

I have a new project I am working on, I will control a thermal printer that receives on its serial port characters or decimals to perform its tasks, printing an invoice.

These printers are used in every store in Brazil, and software today is only MS Windows based. Even the Brazilian Apple Stores must have an MS Windows computer to be able to invoice.

In order to make sure the sent characters are valid I need to perform a XOR calculation in between the first decimal representation of the first char and the second char, the result submitted to the next decimal and so forth.

The final result is appended the end of the character set.

I am able to do this now, using ASOC, but since it goes into a loop, it is very slow…

I desire to port this routine to plain Objective C, since I believe it will be faster.

I have a sample project I have placed at:

http://www.idanfe.com/dl/coersionAndXOR.zip

I appreciate if you take a look at the source code, and specially note that the button “Convert (1)” is functional using ASOC, but the button “Convert (2)” which uses plain objective C for a similar routine is not doing the full conversion, I stopped at the method:

-(NSMutableArray* )calculateVerifyingDigit:(NSMutableArray*)theInputedArray

Which is unfinished, and I do not know how to finish.

Please let me know if I did not make myself clear.

Thanks for your attention,

Bernardo

This is out of my comfort zone, but I think you’re after something like this:

		NSString *string = @"abcdefghi";
		unichar XOR;
		NSUInteger len = [string length];
		NSRange range = NSMakeRange(0,len);
		unichar *buffer = calloc(len, sizeof(unichar));
		[string getCharacters:buffer range:range];
		XOR = buffer[0];
		for (int i = 1; i < len; i++) {
			XOR ^= buffer[i];
		}
		NSLog(@"%d %@", XOR, [[NSString alloc] initWithCharacters:&XOR length:1]);
		free(buffer);

One catch is that that’s all Unicode, whereas you may be after ASCII only, but I think it will be fine in that case as long as the input is all ASCII-compatible characters.

Anyway, it’s something to get you started…

It worked my friend.

Thanks again!

You are great!

Hello Shane,

I seem to be in more trouble.

It seems that higher DECIMALs, like 201 and 255, breaks the code.

I have to add 3 chars before the string and 1 char after the string and then apply the verifying digit.

Would you please take another look at the project at this link?

http://www.idanfe.com/dl/coersionAndXOR.zip

I’d guess that the process is only meant for ASCII characters, which mean 0-127. If that’s so, you may have to try to convert them. But it’s all just guesswork – what you really need is some specification of what needs to be done.

Dear Shane,

would you please take a look at this code?


-(NSString*)insertSoldItem:(NSString*)inputedString
{
    //NSLog(@"inputedString = %@",inputedString);

    int length = [inputedString length];
    NSLog(@"length = %d",length);

    int finalLength =  length + 5;

    NSLog(@"finalLength = %d",finalLength);

    char someChar[58];//finalLength];


    for (NSUInteger i = 0; i < sizeof(someChar); i++) {
    
        NSLog(@"someChar[i] (before everything) CHAR == '%c'", someChar[i]);
        // NSLog(@"someChar[i] HEX == '%x'", someChar[i]);
        // NSLog(@"someChar[i] HEX2 == '%X'", someChar[i]);
    }

    someChar[0] = 28;
    someChar[1] = 70;
    someChar[2] = 201;
    int pos = 3;

    for (NSUInteger i = 0; i < sizeof(someChar); i++) {
    
        NSLog(@"someChar[i] (before loop) CHAR == '%c'", someChar[i]);
        // NSLog(@"someChar[i] HEX == '%x'", someChar[i]);
        // NSLog(@"someChar[i] HEX2 == '%X'", someChar[i]);
    }

    for (NSUInteger i=0;i<length;i++){
        NSString *ichar  = [NSString stringWithFormat:@"%c", [inputedString characterAtIndex:i]];
        NSLog(@"iChar = '%@'",ichar);
        char* tempChar = [ichar UTF8String];
        someChar[i+3] = *tempChar ;
        pos++;
    }


    for (NSUInteger i = 0; i < sizeof(someChar); i++) {
    
        NSLog(@"someChar[i] CHAR == '%c'", someChar[i]);
        // NSLog(@"someChar[i] HEX == '%x'", someChar[i]);
        // NSLog(@"someChar[i] HEX2 == '%X'", someChar[i]);
    }

    someChar[pos] = 255;
    pos++;

    char XOR = 0;

    for (NSUInteger i=0;i<finalLength;i++) {	// loop de cálculo do checksum
        NSLog(@"acumulated xor = '%c'",XOR);
        XOR ^= someChar[i];
        NSLog(@"doing XOR on '%c'",someChar[i]);
        NSLog(@"results = %c",XOR);
        //NSLog(@"looping %ld",i);
    }
    NSLog(@"Verifying digit: %c", XOR);
    someChar[pos] = XOR;
    int sz;
    sz = (sizeof someChar) / (sizeof someChar[0]);
    NSLog(@"someChar count = %i",sz);

    NSString *response;
    
    response = [self.terminalClass dumpCharsToPrinter:someChar length:sz ] ;
    
    NSLog(@"response HERE XXXXXX = %@",response);
 
    return response;
     
}

Please note: This code is working!

But notice the line “char someChar[58];//finalLength];”

I am attempting to pass the final count of the character set, but it only works if I hard code with a 58.

Although the finalLength = 58, when I insert the variable, instead of the hardcoded 58, it doesn’t work. I think it should.

when using the variable finalLength and logging the immediately after its creation I see a bunch of characters I did not input, like:

Log:

2012-07-11 01:41:03.810 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.811 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.811 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.811 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.827 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.827 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.828 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.828 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.828 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.829 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.829 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.831 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.831 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.832 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.832 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.832 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.856 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.857 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.857 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.858 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.859 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.860 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.860 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.861 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.861 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.862 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.863 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.863 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.864 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘0’
2012-07-11 01:41:03.864 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.865 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.866 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.867 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘“’
2012-07-11 01:41:03.869 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘ž’
2012-07-11 01:41:03.869 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘h’
2012-07-11 01:41:03.870 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘g’
2012-07-11 01:41:03.871 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘ˇ’
2012-07-11 01:41:03.874 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.875 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.875 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.876 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.876 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘š’
2012-07-11 01:41:03.877 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘h’
2012-07-11 01:41:03.878 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘g’
2012-07-11 01:41:03.879 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘ˇ’
2012-07-11 01:41:03.879 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.880 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.881 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.882 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘∞’
2012-07-11 01:41:03.882 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘°’
2012-07-11 01:41:03.883 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘h’
2012-07-11 01:41:03.884 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘g’
2012-07-11 01:41:03.885 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘ˇ’
2012-07-11 01:41:03.885 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.886 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.887 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘’
2012-07-11 01:41:03.888 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘ı’
2012-07-11 01:41:03.888 iCupom Fiscal[2803:403] someChar[i] (before everything) CHAR == ‘⁄’

These chars I did not insert.

What am I missing?

Thanks!

I hate C, so you’re probably asking the wrong person. But I suspect that when you use a literal number, the compiler knows how much clear memory to allocate, but when you use a variable, it’s allocated on the fly, and may therefore have contained something else beforehand. Your real problem, I think, is that you don’t set any value for the last two items in the array. You can’t rely on their contents if you don’t set them.

PLease don’t say that! You know I love C:)

There are many ways to create memory but what you’re seeing is memory that isn’t cleared. This is just normal behavior and in some cases you want this. If you don’t want this:

It’s all yours… :wink:

C for Civil war.

If you set the compiler to ANSI C memset will be used instead of bzero. This problem will be solved for you in strings.h; no sweat

DJ, I have a question for a C-lover under a new post :slight_smile:

Dear Bazzie,

Can you guide me?

I am lost in your response.

Is this a build setting in xCode?

Thanks.

No Fiz is right. If you want to use the code for multiple platforms (like recompiling it in visual studio for windows) you should use memset. But my point was more that it doesn’t matter as long as you’re using XNU or other BSD system where the code would run. As long as you want ‘initialised’ strings where every item in the array is zero you can use calloc as well. bzero/memset is more often used for buffers so you don’t need to worry about the string terminator and to avoid a bug like buffer overflow.

But you can ask what you want and I will try to help you further, don’t know if I have the right answer for you :smiley:

Thanks Bazzie,

This is the problem:

This the meaningful part of the method:


-(NSString*)insertSoldItem:(NSString*)inputedString
{
    //NSLog(@"inputedString = %@",inputedString);
    
    int length = [inputedString length];
    NSLog(@"length = %d",length);
    
    int finalLength =  length + 5;
    
    NSLog(@"finalLength = %d",finalLength);
    
    char someChar[58];//  I wanted to use the variable finalLength instead of the hardcoded 58!

If I use the barcoded 58, it works fine! (but I need to get the length of the strings on the fly, since they vary.)

I log the variable finalLength, and I have 58!, but it doesn’t work, I think I have a different data type than C expects…

When I use 58, and log the variable someChar right after is creation, I see they are empty. Good!

But when I use finalLength, and log the variable someChar right after its creation, I have all these weird chars inside, it is not empty!

Please let me know if I made myself understood.

thanks,

The difference is just dynamic arrays vs static arrays. They are different and therefore they behave different. Don’t think of this is as if there is something wrong. See it like renting a storage box in a storage building/complex. At the moment you get the key (kernel give you memory) you need to clean the room first before you can use it unless you pay extra (performance costs) that the room is cleaned before you get the key (calloc).

Here is a small example code how (I guess) you would like the code to work

As you can see there is a lot of overhead but is more often used than you thing (except for the printing parts of course). This is often used for sockets (server-client communications), buffers and binary data. But if it’s only used for a string then all the zeroing of the memory isn’t needed. We can immediately start copying data into the allocated memory and only need to add an string terminator at the end of the string. like in the code above (the last while loop) the string value is the same while the remaining data can be anything without any problem. This method (below) is more used for text processing because it is faster.

Dear Bazzie,

Thanks, many thanks for your kind explanation.

So, all I had to was this?



char someChar[finalLength];
    
    for (NSUInteger i=0;i<finalLength;i++){
        someChar[i] = 0; //null char?
    }

I think that the memory has previous chars that were written to it, just like a hard disk has when you “think” you deleted a file. You only delete the reference to it, you don’t write new data inside.

Am I correct?

Excactly, I couldn’t say it with better words. I’m glad I could help.