Re: Very Urgent (Please respond by the end of today, my job depends on it :)
Jamie McMullin wrote: Looking into the delimeter, \30, I have come figured out that it is ascii character 24 and is represented as ^X I have never come across this character before, I don't know why it is used and how it corresponds to the keyboard or any C functions. It doesn't matter that you've never seen it before. It doesn't matter how it's used. It doesn't matter how it corresponds to the keyboard. It doesn't matter IF it corresponds to the keyboard. In C, characters are just integers. The octal 30 is just a decimal 24 which is just binary 00011000 or hexadecimal 18. That character might mean one thing in ASCII and another in EBCDIC and something else in some other character set (like the DOS 8-bit character set which has the smiley faces in it). The only thing that's important about that character is that it is the number that it is and you can see that in your data it serves as a delimiter. If you want to find the first occurrence of that in a big list (array, memory region) of characters, you could do this: int find_delimiter_position (Char* str) { const Char delimiter = 24; // or const Char delimiter = 030; if you prefer. int pos = 0; while (str[pos] != delimiter) { pos++; } return pos; } Of course, that will keep going forever and ever until it finds that character, so you might want to add logic to stop after however long is needed. - Logan -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Very Urgent (Please respond by the end of today, my job depends on it :)
I am right at the last stage of the development cycle of a form I am writing for my new job and I have hit a major snag. Database access : What I want to do is simple, I want to access a .pdb database, do a binary search to find a record with the corresponding prodno unique id. I have never accessed a database on a palm before, this all a first for me and I seem to be so close. What I get at this stage is a seemingly valid dbID of like 8552589 or something, a dbP that has the same value as my eventP and formP (I'm not sure if that means I am not connecting right) a recordNumber (or Index) of 1(not desired), and a bunch of completely insane values in my pointer record and basic record. So dbID and dbP seem to be working, while DmFindSortPosition and possibly my method of reading from the record handle are faulty. I really can't pinpoint it! Here is some relevent code: (Not copy and pasted, so ignore simple typos) //My Record Structure typedef struct { char prodno[21]; char upc[21]; char retail[11]; etc. (all char values of correct size) }UPCD; //My Database Access (I am positive I have the correct db name) LocalID dbID = DmFindDatabase(0, Detail-PMOO); DmOpenRef dbP = DmOpenDatabase(0, dbID, dmModeReadOnly); //The Comparison Function for the DmFindSortPosition(I am very unconfident in this function and based it exactly off of an example function I found in two locations on the internet) static int CompareRecordFunc(UPCD *rec1, UPCD *rec2, int unusedInt, SortRecordInfoPtr unused1, SortRecordInfoPtr unused2, int appInfoH) { int result; result = StrCompare(rec1-prodno, rec2-prodno); return result } //The Binary Search UPCD FindRecord; UPCD *Record; StrCopy(FindRecord.prodno ,011); UInt32 recordNumber = DmFindSortPosition(dbP, FindRecord, 0, (DmComparF *) CompareRecordFunc, 0); if (recordNumber 0) { MemHandle recH; recH = DmQueryRecord(dbP, recordNumber - 1); Record = (UPCD *) MemHandleLock(recH); Boolean foundIt = StrCompare(FindRecord.prodno, Record-prodno); MemHandleUnlock(recH); } if (foundIt) { SetFieldText( MainDescriptionField, Record-prodno, 30, true); } //Then close database and that's it. I think the possible problem areas are in the comparison function, making Record = the memhandle, opening the database(somehow, it doesn't error and dbID seems valid. Another issue is packing, I don't understand what packing and unpacking databases means. Do you have to unpack a database to read records from it? That's all I can think of, thank you for any help you give me, this is SO very appreciated. , Jamie -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
iajfoj jgoiejoisjo wrote: static int CompareRecordFunc(UPCD *rec1, UPCD *rec2, int unusedInt, SortRecordInfoPtr unused1, SortRecordInfoPtr unused2, int appInfoH) UInt32 recordNumber = DmFindSortPosition(dbP, FindRecord, 0, (DmComparF *) CompareRecordFunc, 0); I don't know exactly what your problem might be, but I can make a suggestion: by casting the function pointer to a DmComparF*, you are defeating a lot of type checking that makes sure you have the right argument types. So, I would declare CompareRecordFunc() with EXACTLY the same argument types as described in the documentation and then call DmFindSortPosition() without the cast. If you have the argument list right, it should not require a cast. Yes, this means you will have a void* for your two records inside of CompareRecordFunc(), and you will have to cast those back to UPCD* inside that function. But that's OK. In particular, one thing I notice about your CompareRecordFunc() signature is that you are using an int for the third argument and for the last argument. In the documentation, it shows the third as an Int16 and the last as a MemHandle, and the two of those aren't the same size! - Logan -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
RE: Very Urgent (Please respond by the end of today, my job depends on it :)
Perhaps it is not finding the correct record because of the way you are searching. Are the records in the database guaranteed to be sorted by the prodno field? If not, the search will not return the correct number, and I think you would be better off writing your own search function. Just open every record in turn and test to see if it is the correct one until you find it. Jonathan King -Original Message- From: [EMAIL PROTECTED] [mailto:bounce-417579- [EMAIL PROTECTED] On Behalf Of iajfoj jgoiejoisjo Sent: Sunday, March 20, 2005 6:04 PM To: Palm Developer Forum Subject: Very Urgent (Please respond by the end of today, my job depends on it :) I am right at the last stage of the development cycle of a form I am writing for my new job and I have hit a major snag. Database access : What I want to do is simple, I want to access a .pdb database, do a binary search to find a record with the corresponding prodno unique id. I have never accessed a database on a palm before, this all a first for me and I seem to be so close. What I get at this stage is a seemingly valid dbID of like 8552589 or something, a dbP that has the same value as my eventP and formP (I'm not sure if that means I am not connecting right) a recordNumber (or Index) of 1(not desired), and a bunch of completely insane values in my pointer record and basic record. So dbID and dbP seem to be working, while DmFindSortPosition and possibly my method of reading from the record handle are faulty. I really can't pinpoint it! Here is some relevent code: (Not copy and pasted, so ignore simple typos) //My Record Structure typedef struct { char prodno[21]; char upc[21]; char retail[11]; etc. (all char values of correct size) }UPCD; //My Database Access (I am positive I have the correct db name) LocalID dbID = DmFindDatabase(0, Detail-PMOO); DmOpenRef dbP = DmOpenDatabase(0, dbID, dmModeReadOnly); //The Comparison Function for the DmFindSortPosition(I am very unconfident in this function and based it exactly off of an example function I found in two locations on the internet) static int CompareRecordFunc(UPCD *rec1, UPCD *rec2, int unusedInt, SortRecordInfoPtr unused1, SortRecordInfoPtr unused2, int appInfoH) { int result; result = StrCompare(rec1-prodno, rec2-prodno); return result } //The Binary Search UPCD FindRecord; UPCD *Record; StrCopy(FindRecord.prodno ,011); UInt32 recordNumber = DmFindSortPosition(dbP, FindRecord, 0, (DmComparF *) CompareRecordFunc, 0); if (recordNumber 0) { MemHandle recH; recH = DmQueryRecord(dbP, recordNumber - 1); Record = (UPCD *) MemHandleLock(recH); Boolean foundIt = StrCompare(FindRecord.prodno, Record-prodno); MemHandleUnlock(recH); } if (foundIt) { SetFieldText( MainDescriptionField, Record-prodno, 30, true); } //Then close database and that's it. I think the possible problem areas are in the comparison function, making Record = the memhandle, opening the database(somehow, it doesn't error and dbID seems valid. Another issue is packing, I don't understand what packing and unpacking databases means. Do you have to unpack a database to read records from it? That's all I can think of, thank you for any help you give me, this is SO very appreciated. , Jamie -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/ -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
Some new info: Okay I've looked at it a bit more and found something that may help me describe the problem more accurately. The boolean value foundIt that gets StrCompare'd equals 4 and even higher values if I muck around. I'm not sure what that means. I'm not quite sure what you meant, but I can figure it out in due time. The thing is, even if that function isn't working, if I make up hardcoded index values for the DmQueryRecord, they don't appear to work. FindRecord and Record both have values like FindRecord.prodno is 6252/A212FB/4EGSA3 and they all look similar to that, be it retail price, upc or a description string of the product. This seems hopeless : Is there anything I could be missing? I just don't understand. -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
RE: Very Urgent (Please respond by the end of today, my job depends on it :)
I'm not too worried about the search yet, because even if I use hardcoded indexes into DmQueryRecord, I'm still getting random, unintelligible crap. To make matters worse, there are apparatentely over 20,000 records in this database, and if I use index values of anything over 15 the program crashes. I can't do a sequential search like that because of the database size, I have to use a binary search, I'm just hoping I don't have to write one myself, since this function seems to do it for me. I do think my comparison function could be flawed, but I can't be concerned with any of that yet. First I must know for sure that I can read indexes off of this database. -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
RE: Very Urgent (Please respond by the end of today, my job depends on it :)
Okay, so the records I'm getting aren't as random as I thought, although they seem to be far from what is desired, example: prodno, the number on the label's barcode: 7623397\AUTO ADD'\30'17.9 upc code, the upc of the product: 9'\30'11.352'\30'BOX'\30'BOX'\30'0'\30'0. retail, the cost of the product: 000'\30'1.000'\30'0 I don't know, could I attach the file? I know this is probably too much to ask of anyone's time, I've spent so much time on this without asking, I really need some help from someone other than myself and google's mess and absence of palm devlopment support articles. I hope I'm not asking too much out of anyone, I know this would be too much for me. -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
RE: Very Urgent (Please respond by the end of today, my job depends on it :)
At 06:10 PM 3/20/2005, you wrote: I'm not too worried about the search yet, because even if I use hardcoded indexes into DmQueryRecord, I'm still getting random, unintelligible crap. To make matters worse, there are apparatentely over 20,000 records in this database, and if I use index values of anything over 15 the program crashes. I can't do a sequential search like that because of the database size, I have to use a binary search, I'm just hoping I don't have to write one myself, since this function seems to do it for me. You have to write it yourself. The Palm OS implementation is broken for DBs over 16K records, at least on older versions. Writing a binary search isn't difficult. It does require that your database be sorted on the primary key -- if it's not, then a binary search won't work because there is no ordering guarantee that enables the search routine to elminate half of the records with each pass. -- Ben Combee, Senior Software Engineer, palmOne, Inc. Combee on Palm OS weblog: http://palmos.combee.net/ Developer Forum Archives: http://news.palmos.com/read/all_forums/ -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
RE: Very Urgent (Please respond by the end of today, my job depends on it :)
You wouldn't happen to have an example of how to do a binary search in codewarrior, would you? I have found an example of a binary search in codewarrior C, but it's not for accessing records in a database, but for find data in an array. -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
RE: Very Urgent (Please respond by the end of today, my job depends on it :)
At 07:29 PM 3/20/2005, you wrote: You wouldn't happen to have an example of how to do a binary search in codewarrior, would you? I have found an example of a binary search in codewarrior C, but it's not for accessing records in a database, but for find data in an array. Use the code for an array, but instead of indexing into the array, use the index variable as the index value to DmQueryRecord, and change the comparison routine to query both records and do your own comparison. -- Ben Combee, Senior Software Engineer, palmOne, Inc. Combee on Palm OS weblog: http://palmos.combee.net/ Developer Forum Archives: http://news.palmos.com/read/all_forums/ -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
iajfoj jgoiejoisjo wrote: What I get at this stage is a seemingly valid dbID of like 8552589 or something, a dbP that has the same value as my eventP and formP (I'm not sure if that means I am not connecting right) a recordNumber (or Index) of 1(not desired), and a bunch of completely insane values in my pointer record and basic record. This sounds like some part of your program is stepping on your other variables. dbP, eventP, and formP should have the same value at the same time. //My Record Structure typedef struct { char prodno[21]; char upc[21]; char retail[11]; etc. (all char values of correct size) }UPCD; //My Database Access (I am positive I have the correct db name) LocalID dbID = DmFindDatabase(0, Detail-PMOO); DmOpenRef dbP = DmOpenDatabase(0, dbID, dmModeReadOnly); Could you be writing more chars to a member of UPCD than exist in the structure? If so, it would explain how dbP and dbID could be corrupted. I think the possible problem areas are in the comparison function, making Record = the memhandle, opening the database(somehow, it doesn't error and dbID seems valid. You're using MemHandleLock which returns a locked pointer (not a handle) which is what you want. So you are doing this correctly. Another issue is packing, I don't understand what packing and unpacking databases means. Do you have to unpack a database to read records from it? Only if they were packed to begin with. It's a design decision, not something PalmOS inherently does. That is, if you want packing, you need to implement it yourself. For example, if you want to store two ints (foo and bar) in a record: struct { int foo; int bar; } unpackedRecord; You might be able to pack them to save space. Say foo has a max value of 15 and bar a max of 7. You could pack them like so: struct { int foo : 4; int bar : 3; int unused : 1; } packedRecord; So, what used to require 4 bytes, now fits in 1. -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
Cory Pratt wrote: This sounds like some part of your program is stepping on your other variables. dbP, eventP, and formP should have the same value at the same time. That should read: ...should NEVER have the same value... -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
I understand the problems better now: 1) The search function is invalid with databases that large. 2) The database I was given to do this project with IS packed. Although I'm not sure the format or how to unpack it. It would seem that /30 would delimete each record. I've seen examples of how to unpack packed records, but the method doesn't make any sense with the format of the records I have. The method I've seen is: char *s = PackedRecord-key; UnpackedRecord-prodno = s; s += StrLen(s) + 1; UnpackedRecord-desc = s; s += StrLen(s) + 1; UpackedRecord-retail = s; etc. etc. Why this makes no sense at all is that PackedRecord-Key equals something like: '2938012/30AUTO_ADD/30100.20/30' etc. So I don't see how the above method of unpacking will turn that long concatenated string into a bunch of indivdual, accurately un-delimeted records. PBMake was the program used to create the database, so that could be a clue. I am still lost, and I'm hoping I can get an extension, because I didn't have all the correct info going into this and it has taken a long time to look through the chaos and find out what is under the very large and vague problem. ,Jamie -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
From: Jamie McMullin [EMAIL PROTECTED] 2) The database I was given to do this project with IS packed. Although I'm not sure the format or how to unpack it. It would seem that /30 would delimete each record. The method I've seen is: char *s = PackedRecord-key; UnpackedRecord-prodno = s; s += StrLen(s) + 1; Why this makes no sense at all is that PackedRecord-Key equals something like: '2938012/30AUTO_ADD/30100.20/30' etc. So I don't see how the above method of unpacking will turn that long concatenated string into a bunch of indivdual, accurately un-delimeted records. It won't. That logic is intended for records that are packed with each string null-terminated, ie terminated by a character zero. You can then use StrLen to find the number of characters up to the next null-terminator. You can still use this logic, but you would have to write a function to count the number of characters from the pointer to the next /30 and then use that instead of StrLen. All that pack really means is that instead of storing strings padded with spaces to a constant length as in '2938012 AUTO_ADD 100.20 ' '2938013SOME OTHER DATA100.20 ' '2938013THREE 100.20 ' they're terminated and the next field immediately follows them, as in '2938012\0AUTO_ADD\0100.20\0' '2938013\0SOME OTHER DATA\0100.20\0' '2938013\0THREE\0100.20\0' etc. The main advantage to packing is that you don't waste space padding strings out to the same length, the disadvantage is that you can't just dump the record into a C struct and access it immediately - you've got to copy the fields item by item into the structure you want to use. Part of your problem would seem to be the way this database was created, particularly since numeric data seems to have been turned into strings and might need to be converted back into numbers before you can calculate with it. On the other hand if you're just displaying these values it doesn't matter. Chris Tutty -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
Oops! It's \30 not /30 ~_~ -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
Okay here's a thought, how about I go into the database via notepad and change all of the \30s into \0's? I'm sure it is possible, I just don't know what the codes for them are. This does sound like some pretty obscure knowledge, however. -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
To be correct, this needs changing from: From: Chris Tutty [EMAIL PROTECTED] All that pack really means is that instead of storing strings padded with spaces to a constant length as in '2938012 AUTO_ADD 100.20 ' '2938013SOME OTHER DATA100.20 ' '2938013THREE 100.20 ' to All that pack really means is that instead of storing strings padded with spaces to a constant length as in '2938012 AUTO_ADD\0 100.20 ' '2938013SOME OTHER DATA\0100.20 ' '2938013THREE\0 100.20 ' so that the strings are properly null-terminated when copied into a C struct. And they probably wouldn't be space-padded - might be null-padding, might be whatever crap followed the null terminator in the original edit buffer. Chris Tutty -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
Looking into the delimeter, \30, I have come figured out that it is ascii character 24 and is represented as ^X I have never come across this character before, I don't know why it is used and how it corresponds to the keyboard or any C functions. Anyone else have any ideas? -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
I can't find any examples of someone using ASCII Character 24 as a delimiter, unless there is a natural C function that can find the delimiter like StrLen can find the null terminator, or unless there is a safe and quick way to use Replace in Notepad to change all of the ASCII Character 24s into null terminators, I'll have to write my own string function. I am not experienced at all with C, but in Basic I could write this very easily. I would imagine it would work like this: Loop StrLen(String) times { UInt16 CharacterPointer = 0 UInt16 FieldPointer = 0 Look at String[CharacterPointer], if it is anything other than '\', continue. Concatenate String[CharacterPointer] onto a temp string. If it is '\', then if (CharacterPointer+2) is less than StrLen(String), CharacterPointer = CharacterPointer + 2 and then: { Have a FieldPointer value, run a switch on it. If it equals 0, point the temp string into Record-prodno(first field), if it is 1, put it into desc, etc. Then of course, FieldPointer++ }EndIf here CharacterPointer++ } I think pretty much sums up the function I'd need to right, does it sound right? -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
\30 is the escape sequence. To me this looks like the data is stpred as string representation by avoiding \0. I recently ran into a problem when I tried to store binary data as a char array when in my PDP generation tool (to be precise as String in Delphi). The problem I had was that my Binary data was stripped at the place a hex 0 (or \0 in c) occured in my binary array. I'm almost sure they've simply choosen \30 instead of a \0 for a similar reason. Instead of copying the string you can walk through your \30 seperated data struct and collect store the values. I think you can do something like Char* strPos; Char* backslashPos; backslashPos = StrStr(YourBackslash30TerminatedValues, \30); someRecord = (String from your struct to backslashPos) strPos = StrStr(YourBackslash30TerminatedValues, \30); strPos +=3; (...) (repeat this until yur reach the last record) Dirty untested example, but I think you get it. Benjamin Jamie McMullin wrote: Looking into the delimeter, \30, I have come figured out that it is ascii character 24 and is represented as ^X I have never come across this character before, I don't know why it is used and how it corresponds to the keyboard or any C functions. Anyone else have any ideas? -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
From: Jamie McMullin [EMAIL PROTECTED] Okay here's a thought, how about I go into the database via notepad and change all of the \30s into \0's? I'd find a programmer's editor (ultraedit is pretty good) because that's more likely to support special characters in the search and replace. Your only problem then is making sure that you only replace characters in the record data and not in the pdb header. You're better off finding the original data and using a different tool to create the pdb (although you're then going to have to find that and learn how to use it - also not a trivial task in a short time). Or write an unpack function that knows to look for \30. It's really just a variation on char outBuffer[somesize]; char * cpOut = outBuffer; currentPos = 0; // copy up to the \30 while (recordData[currentPos] != '\30') { *cpOut++ = recordData[currentPos++]; } // and terminate the string; *cpOut = '\0'; with appropriate error-checking. No? Chris Tutty -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/
Re: Very Urgent (Please respond by the end of today, my job depends on it :)
Correction for the pseudo code Char* strPos; Char* backslashPos; // strPos is pointer to your data struct strPos = (Char*)(YourBackslash30TerminatedValues); // get pos for first \30 backslashPos = StrStr(YourBackslash30TerminatedValues, \30); // get first record someRecord = (copy string from strPos to backslashPos) // jump to next record strPos = backslashPos; strPos +=2; /* You should now be at the beginning of your second data entry in the char array. Repeat the above steps for all other records */ Hope that helps, and works ;-) Benjamin -- For information on using the Palm Developer Forums, or to unsubscribe, please see http://www.palmos.com/dev/support/forums/