From 258b4616ab6028efea0ea8b85a3d3dd1ff6bf6e0 Mon Sep 17 00:00:00 2001 From: bruceperens Date: Fri, 7 Mar 2014 01:10:18 +0000 Subject: [PATCH] Save 80K text size by using an ad-hoc altrernative to STL containers. Since this is an embedded program, that's significant. git-svn-id: https://svn.code.sf.net/p/freetel/code@1411 01035d8c-6547-0410-b346-abe4f91aad63 --- freedv-server/source/driver_manager.cpp | 180 ++++++++++++------------ freedv-server/source/drivers.h | 45 ++---- 2 files changed, 101 insertions(+), 124 deletions(-) diff --git a/freedv-server/source/driver_manager.cpp b/freedv-server/source/driver_manager.cpp index 0c43da2e..28db8fa4 100644 --- a/freedv-server/source/driver_manager.cpp +++ b/freedv-server/source/driver_manager.cpp @@ -2,14 +2,66 @@ /// Don't use DriverManager and big_main.cpp in space-limited applications. /// The STL templates it uses are too large. -#ifndef NO_INITIALIZERS #include +#include #include "drivers.h" namespace FreeDV { + typedef Base * (*base_creator)(const char *); + + // Ad-hoc list management functions are much smaller, and indeed faster for + // our tiny data sets, than the STL containers. Since this program is + // embedded, it's worth some extra effort to avoid STL containers. + + static std::ostream & + enumerate(std::ostream & stream, const DriverList * list) + { + while ( list->key ) { + stream << list->key << ' '; + list++; + } + return stream; + } + + static FreeDV::Base * + pick(const char * key, const char * parameters, const DriverList * list) + { + while ( list->key ) { + if ( strcmp(key, list->key) == 0 ) { + return (*(list->value))(parameters); + } + list++; + } + return 0; + } + + static void + place(const char * key, FreeDV::Base * (*value)(const char *), DriverList * * const list) + { + DriverList * next; + + if ( list ) { + next = *list; + while ( next->key ) + next++; + const std::size_t length = (next - *list); + + DriverList * n = new DriverList[length + 2]; + memcpy(n, *list, sizeof(*list) * length); + *list = n; + } + else + *list = next = new DriverList[2]; + + next->key = strdup(key); + next->value = value; + ++next; + next->key = 0; + next->value = 0; + } + // Global instance of the driver manager used to register // drivers and to create driver instances. - DriverManager::DriverManager() { } @@ -21,50 +73,32 @@ namespace FreeDV { std::ostream & DriverManager::print(std::ostream & s) const { - s << "AudioInput: "; - for (auto i = audio_input_drivers.begin(); i != audio_input_drivers.end(); i++ ) - s << i->first << " "; - s << std::endl; + s << "Audio Input: "; + enumerate(s, audio_input_drivers) << std::endl; - s << "AudioOutput: "; - for (auto i = audio_output_drivers.begin(); i != audio_output_drivers.end(); i++ ) - s << i->first << " "; - s << std::endl; + s << "Audio Output: "; + enumerate(s, audio_output_drivers) << std::endl; s << "Codec: "; - for (auto i = codecs.begin(); i != codecs.end(); i++ ) - s << i->first << " "; - s << std::endl; + enumerate(s, codecs) << std::endl; s << "Framer: "; - for (auto i = framers.begin(); i != framers.end(); i++ ) - s << i->first << " "; - s << std::endl; + enumerate(s, framers) << std::endl; - s << "KeyingOutput: "; - for (auto i = keying_output_drivers.begin(); i != keying_output_drivers.end(); i++ ) - s << i->first << " "; - s << std::endl; + s << "Keying Output: "; + enumerate(s, keying_output_drivers) << std::endl; s << "Modem: "; - for (auto i = modems.begin(); i != modems.end(); i++ ) - s << i->first << " "; - s << std::endl; + enumerate(s, modems) << std::endl; - s << "PTTInput: "; - for (auto i = ptt_input_drivers.begin(); i != ptt_input_drivers.end(); i++ ) - s << i->first << " "; - s << std::endl; + s << "PTT Input: "; + enumerate(s, ptt_input_drivers) << std::endl; - s << "TextInput: "; - for (auto i = text_input_drivers.begin(); i != text_input_drivers.end(); i++ ) - s << i->first << " "; - s << std::endl; + s << "Text Input: "; + enumerate(s, text_input_drivers) << std::endl; - s << "UserInterface: "; - for (auto i = user_interface_drivers.begin(); i != user_interface_drivers.end(); i++ ) - s << i->first << " "; - s << std::endl; + s << "User Interface: "; + enumerate(s, user_interface_drivers) << std::endl; return s; } @@ -72,149 +106,110 @@ namespace FreeDV { AudioInput * DriverManager::audio_input(const char * driver, const char * parameter) { - AudioInput * (* const creator)(const char * parameter) = audio_input_drivers[driver]; - - if(creator) - return creator(parameter); - else - return 0; + return (AudioInput *)pick(driver, parameter, audio_input_drivers); } AudioOutput * DriverManager::audio_output(const char * driver, const char * parameter) { + return (AudioOutput *)pick(driver, parameter, audio_output_drivers); } Codec * DriverManager::codec(const char * driver, const char * parameter) { - Codec * (* const creator)(const char * parameter) = codecs[driver]; - - if(creator) - return creator(parameter); - else - return 0; + return (Codec *)pick(driver, parameter, codecs); } Framer * DriverManager::framer(const char * driver, const char * parameter) { - Framer * (* const creator)(const char * parameter) = framers[driver]; - - if(creator) - return creator(parameter); - else - return 0; + return (Framer *)pick(driver, parameter, framers); } KeyingOutput * DriverManager::keying_output(const char * driver, const char * parameter) { - KeyingOutput * (* const creator)(const char * parameter) = keying_output_drivers[driver]; - - if(creator) - return creator(parameter); - else - return 0; + return (KeyingOutput *)pick(driver, parameter, keying_output_drivers); } Modem * DriverManager::modem(const char * driver, const char * parameter) { - Modem * (* const creator)(const char * parameter) = modems[driver]; - - if(creator) - return creator(parameter); - else - return 0; + return (Modem *)pick(driver, parameter, modems); } PTTInput * DriverManager::ptt_input(const char * driver, const char * parameter) { - PTTInput * (* const creator)(const char * parameter) = ptt_input_drivers[driver]; - - if(creator) - return creator(parameter); - else - return 0; + return (PTTInput *)pick(driver, parameter, ptt_input_drivers); } TextInput * DriverManager::text_input(const char * driver, const char * parameter) { - TextInput * (* const creator)(const char * parameter) = text_input_drivers[driver]; - - if(creator) - return creator(parameter); - else - return 0; + return (TextInput *)pick(driver, parameter, text_input_drivers); } UserInterface * DriverManager::user_interface(const char * driver, const char * parameter, Interfaces * interfaces) { - UserInterface * (* const creator)(const char * parameters, Interfaces *) = user_interface_drivers[driver]; - - if(creator) - return creator(parameter, interfaces); - else - return 0; + return (UserInterface *)pick(driver, parameter, user_interface_drivers); } void DriverManager::register_audio_input(const char * driver, AudioInput * (*creator)(const char *)) { - audio_input_drivers[driver] = creator; + place(driver, (base_creator)creator, &audio_input_drivers); } void DriverManager::register_audio_output(const char * driver, AudioOutput * (*creator)(const char *)) { - audio_output_drivers[driver] = creator; + place(driver, (base_creator)creator, &audio_output_drivers); } void DriverManager::register_codec(const char * driver, Codec * (*creator)(const char *)) { - codecs[driver] = creator; + place(driver, (base_creator)creator, &codecs); } void DriverManager::register_framer(const char * driver, Framer * (*creator)(const char *)) { - framers[driver] = creator; + place(driver, (base_creator)creator, &framers); } void DriverManager::register_keying_output(const char * driver, KeyingOutput * (*creator)(const char *)) { - keying_output_drivers[driver] = creator; + place(driver, (base_creator)creator, &keying_output_drivers); } void DriverManager::register_modem(const char * driver, Modem * (*creator)(const char *)) { - modems[driver] = creator; + place(driver, (base_creator)creator, &modems); } void DriverManager::register_ptt_input(const char * driver, PTTInput * (*creator)(const char *)) { - ptt_input_drivers[driver] = creator; + place(driver, (base_creator)creator, &ptt_input_drivers); } void DriverManager::register_text_input(const char * driver, TextInput * (*creator)(const char *)) { - text_input_drivers[driver] = creator; + place(driver, (base_creator)creator, &text_input_drivers); } void DriverManager::register_user_interface(const char * driver, UserInterface * (*creator)(const char *, Interfaces *)) { - user_interface_drivers[driver] = creator; + place(driver, (base_creator)creator, &user_interface_drivers); } /// Automatic initializer for the driver manager. @@ -230,4 +225,3 @@ namespace FreeDV { /// Global reference to the driver manager instance. DriverManager & driver_manager = init_driver_manager(); } -#endif diff --git a/freedv-server/source/drivers.h b/freedv-server/source/drivers.h index 37096e08..62ed5e14 100644 --- a/freedv-server/source/drivers.h +++ b/freedv-server/source/drivers.h @@ -710,10 +710,6 @@ namespace FreeDV { } } -#ifndef NO_INITIALIZERS -#include -#include - /// Namespace used for the entire program. namespace FreeDV { /// Utility functions. @@ -725,36 +721,24 @@ namespace FreeDV { a < b ? a : b; } + struct DriverList { + const char * key; + FreeDV::Base * (*value)(const char *); + }; + /// Device driver manager. Allows for registration and enumeration of device /// drivers. Instantiates device drivers on request. class DriverManager { private: - std::map - audio_input_drivers; - - std::map - audio_output_drivers; - - std::map - codecs; - - std::map - framers; - - std::map - keying_output_drivers; - - std::map - modems; - - std::map - ptt_input_drivers; - - std::map - text_input_drivers; - - std::map - user_interface_drivers; + DriverList * audio_input_drivers; + DriverList * audio_output_drivers; + DriverList * codecs; + DriverList * framers; + DriverList * keying_output_drivers; + DriverList * modems; + DriverList * ptt_input_drivers; + DriverList * text_input_drivers; + DriverList * user_interface_drivers; public: @@ -875,5 +859,4 @@ namespace FreeDV { /// Return a reference to the driver manager instance. /// This is a function because it is called in static initializers. extern DriverManager & init_driver_manager(); -#endif } -- 2.25.1