On Wed, April 2, 2008 2:36 am, Phil Dibowitz wrote: > Stephen Warren wrote: >> In congruity, I have some code to identify the action to take for a >> specific EzHex/EZUp file, without relying on any facet of the filename. > > I'm curious as to what you use to figure it out... there are some tells > like firmware has '<TYPE>Firmware_Main</TYPE>' ... but not all > of them are so straight forward - did you just pick a unique option > from each file?
Yes, pretty much. The algorithm will be the same as the current Python code in congruity, with the addition of validating that there really is an INFORMATION tag, and "IR learn" detection, which congruity didn't have. I can post more details (e.g. a patch to just add the libconcord function) when I'm back home and have access to the code, since that part is already working, except for IR learn. > Looks good to me. Obviously we'll have to read in the file significantly > earlier inside of concordance. I don't think that's a problem, but > exactly where is interesting. We could do it in parse_options *if* we > happen to be in auto_mode (where we currently do the filename matching > stuff), but then we have to know if we've read it in or not and read it > in later as necessary. That's sub-optimal. Yes, I hacked it in place of the file name munging code in concordance.c for testing, but certainly wouldn't advocate checking that change in. Your code flow suggestions sound good. > In fact, we could even use the appropriate MODE_* defines as the > filetype defines if we want (obviously we wouldn't use them all, just > MODE_WRITE_* and MODE_LEARN_IR). Well, we'd need to be careful that application operation mode definitions don't creep into libconcord.h, so (from memory of the code) I imagine that we'd end up with libconcord.h only defining the file types, and concordance.c having a switch to map them. > So as I've worked on the XS perl wrappers (finally got everything working > tonight I think, now I'm just cleaning stuff up), >From my limited knowledge of XS, I jokingly suggest it would have been easier to port Python's ctypes module to Perl and use that instead, rather than suffering XS:-) [Actually, all joking aside, I'm sure the Perl community would love a ctypes module, but that's a whole other project]. > I've been thinking about the API, and I'm starting to think more and > more that all our uint8_t* and uint32_t* stuff really should just be a > void* blob which is internally a structure with the uint8_t* and the > size inside of it. Not only do I think of that array as a opaque blob > to the user, but I don't want our API/ABI to have to change when we > make it into an mmap pointer or some other thing. Well, on all platforms, mmap (or the equivalent) will always map the file to some memory location, so we can always have a pointer and size. What is different, is that we may need extra information to manage the mapping. Equally, I do believe we want the client app to be able to access (read) the raw file data (or parsed binary data etc.) directly, if for no other reason than e.g. writing an app that uses libconcord to load/parse a file, then the app can hexdump/disassemble/... the binary data, or something like that. So, what I would suggest is this: APIs use a public structure: struct Data { uint8_t *data; uint32_t data_size; }; and we pass "Data*" to in-to/out-from APIs (no doubt we'd pick a better name). However, internally, we would allocate something like: struct DataInternal { Data public; // Internal only information follow #if defined(WIN32) HANDLE h; // or whatever, for Win32 #else int fd; // Unix mmap fd handle, or whatever #endif }; Then, our APIs work like this: int func1(Data **data) { DataInternal *dataint = (DataInternal *)malloc(sizeof(DataInternal)); *data = (Data*)dataint; dataint->member = whatever; ... } int func2(Data *data) { DataInternal *dataint = (DataInternal *)data; ... } This allows us to hide arbitrary hidden/internal information in the same "handle" that the client app sees, whilst still allowing the app simple access to what it might care about. We can always expand DataInt (outside the Data part) to add new internal information without breaking binary compatibility. We can even expand Data by simply adding fields, although this will obviously break client binary compatibility. Alternatively, we could do this: struct Data { uint8_t *data; uint32_t data_size; void *priv; }; ... and allocate a separate priv structure and point the public structure at it. I like this a little less because: a) We have to make 2 allocations b) The client can see the priv member, which it doesn't care about. c) The client could screw with the priv member, and point it somewhere else. Actually, I'd also like to consider the case of an app that internally creates an "EZHex" file in memory and passes this into libconcord. I guess to support this, all we would need to add is an API like create_Data_struct_from_memory_region, that remembers it doesn't need to free the memory buffer, just the Data structure. Similarly, apps might want to construct raw binary config-updates or firmware blobs, and pass these into the write_*_to_remote functions. So, we shouldn't preclude that. Perhaps the file IO functions should handle Data to allow for mmaping in the future, but the remote interaction functions should either still take in/size, *or* be documented to only use the public portions of struct Data, so and app can create its own. ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace _______________________________________________ concordance-devel mailing list concordance-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/concordance-devel