Save 80K text size by using an ad-hoc altrernative to STL containers. Since
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 7 Mar 2014 01:10:18 +0000 (01:10 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Fri, 7 Mar 2014 01:10:18 +0000 (01:10 +0000)
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
freedv-server/source/drivers.h

index 0c43da2e570322ea49692c9016ddc876a1d3f9fb..28db8fa4146755f235a150ed6cc8f6c88c6cf8bb 100644 (file)
@@ -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 <iostream>
+#include <string.h>
 #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
index 37096e0818106ef2c934a6147b36d22d6a7d5569..62ed5e14321acb3005a1c81bdd89e45935465325 100644 (file)
@@ -710,10 +710,6 @@ namespace FreeDV {
   }
 }
 
-#ifndef NO_INITIALIZERS
-#include <map>
-#include <string>
-
 /// 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<std::string, AudioInput *(*)(const char *)>
-                       audio_input_drivers;
-
-    std::map<std::string, AudioOutput *(*)(const char *)>
-                       audio_output_drivers;
-
-    std::map<std::string, Codec *(*)(const char *)>
-                       codecs;
-
-    std::map<std::string, Framer *(*)(const char *)>
-                       framers;
-
-    std::map<std::string, KeyingOutput *(*)(const char *)>
-                       keying_output_drivers;
-
-    std::map<std::string, Modem *(*)(const char *)>
-                       modems;
-
-    std::map<std::string, PTTInput *(*)(const char *)>
-                       ptt_input_drivers;
-
-    std::map<std::string, TextInput *(*)(const char *)>
-                       text_input_drivers;
-
-    std::map<std::string, UserInterface *(*)(const char *, Interfaces *)>
-                       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
 }