For the fixed size item list, I was referring more to there being less than 14000 items than there being more (older revisions, RT3/RT4). I would probably have it either be a config option or specified by a module (maybe have support for different revisions be loaded as modules, which can take care of setting protocol de/encoders and anything else).
Supporting modules on Windows isn’t too hard.
[code=c]HMODULE mod;
int (*fn)();
mod = LoadLibrary(full_module_name); /* you might need to specify LoadLibraryA explicitly depending on encoding /
if (mod == NULL) {
/ oh no… */
}
fn = (int (()())) GetProcAddress(mod, “module_init”); /* same as above with GetProcAddressA /
/ … */[/code]
For finding modules in a directory
[code=c]WIN32_FIND_DATA ffd;
HANDLE fh;
const char search_path = "modules/.dll";
fh = FindFirstFile(search_path, &ffd);
if (fh == INVALID_HANDLE_VALUE) {
/* oh no… */
}
do {
/* would be good to make this check a bit safer/robust /
/ we filter for *.dll anyway, but for the sake of example… /
if (strstr(ffd.cFileName, “.dll”) != NULL) {
/ load it up */
}
} while (FindNextFile(fh, &ffd) != 0);
FindClose(fh);[/code]
In regards to the static path size, 2000 is much more reasonable, but I was getting at using something like MAX_PATH on Windows. I did just look into it though, and apparently MAX_PATH on Windows is pretty much pointless, and consistency among unix-like systems is pretty bad (some define PATH_MAX and FILENAME_MAX, others may not define them and you need to use pathconf or fpathconf to find it, however it can potentially return a ridiculously huge value or -1, indicating that it isn’t bounded). So at that, I would go for 2048 and call it a day.
strlcat is what I was referring to. I didn’t know it isn’t included in glibc, I’ve been using BSD-like systems for a while now.
You have a few options here.
[ul][li]Do something like this (from a BSD strcat manpage):[/li][/ul]
[code]SECURITY CONSIDERATIONS
The strcat() function is easily misused in a manner which enables malicious users to arbitrarily change a running program’s functionality through a buffer overflow attack. (See the
FSA.)
Avoid using strcat(). Instead, use strncat() or strlcat() and ensure that no more characters are copied to the destination buffer than it can hold.
Note that strncat() can also be problematic. It may be a security concern for a string to be truncated at all. Since the truncated string will not be as long as the original, it may
refer to a completely different resource and usage of the truncated resource could result in very incorrect behavior. Example:
void
foo(const char *arbitrary_string)
{
char onstack[8] = "";
#if defined(BAD)
/*
* This first strcat is bad behavior. Do not use strcat!
*/
(void)strcat(onstack, arbitrary_string); /* BAD! */
#elif defined(BETTER)
/*
* The following two lines demonstrate better use of
* strncat().
*/
(void)strncat(onstack, arbitrary_string,
sizeof(onstack) - strlen(onstack) - 1);
#elif defined(BEST)
/*
* These lines are even more robust due to testing for
* truncation.
*/
if (strlen(arbitrary_string) + 1 >
sizeof(onstack) - strlen(onstack))
err(1, "onstack would be truncated");
(void)strncat(onstack, arbitrary_string,
sizeof(onstack) - strlen(onstack) - 1);
#endif
}
[/code]
[ul][li]Do some compile time checking or use autoconf (config.h, I wouldn’t really go for that), and do something accordingly (If strlcat is present, go ahead and use it. If not, implement strlcat using the code above or use strlcat.c with some appropriate modifications).[/li]
[li]Don’t bother checking for existing functions and just implement strlcat as mystrlcat or something.[/li][/ul]
I’m not really sure what I would do to make the writing code better either. You could try your best to create a pseudo-DSL with macros, but that could get ugly fast.
[code=c]#define P_C(v) ((char) (v))
#define P_S(v) ((char) ((v) >> 8)), ((char) ((v) & 0xff))
#define P_I(v) ((char) ((v) >> 24)), ((char) ((v) >> 16)),
((char) ((v) >> 8)), ((char) ((v) & 0xff))
#define P_END -1
/*
not sure how i would terminate data. a magic number would be simple, but potentially break with certain packets.
instead of using a char array, maybe use a short array where positive values are simply the unsigned value of the actual byte, and -1 can be a marker for the end of the array.
*/
int c_write(struct circular_buffer buf, char… data) {
/ do stuff */
}
void construct_mypacket(struct circular_buffer buf, int foo, short bar) {
/ let’s just pretend c_write uses a short array with -1 as a marker */
c_write(buf, P_C(123), P_C(0), P_S(bar), P_I(0xdeadbeef), P_I(foo), P_END);
}[/code]
Well, it’s not much of a DSL, is it?
Ultimately it may just be better to suck it up and use your current API, and if it really becomes a nuisance, make nifty Lua bindings for packet construction.
This so hard.
On another note, you should’ve used C++ if you wanted this to be open-source for the community to use. It’s just a more common, widely used, and versatile language than C nowadays.[/quote]
Yes, Java not having function pointers is actually a pain in the ass. Sorry most people don’t like as much boilerplate as you do.
What a crock of shit. C is still more common/used than C++ is, though the adoption rate is probably less. What makes C++ more versatile than C? Some features of C++ would be nice, like exceptions and templates, but much of it isn’t really deal breaking (yes, OOP included, sorry).