]> git.mxchange.org Git - flightgear.git/blobdiff - src/Navaids/positioned.cxx
Merge branch 'maint2' into next
[flightgear.git] / src / Navaids / positioned.cxx
index 37445073976cb4b0c7576d709ff13e169b492668..b01418a17367a1814dea1b8cbd5427f80192d2e7 100644 (file)
@@ -30,6 +30,7 @@
 #include <iostream>
 
 #include <simgear/math/sg_geodesy.hxx>
+#include <simgear/timing/timestamp.hxx>
 
 #include "positioned.hxx"
 
@@ -339,6 +340,15 @@ spatialGetClosest(const SGGeod& aPos, unsigned int aN, double aCutoffNm, FGPosit
 
 //////////////////////////////////////////////////////////////////////////////
 
+class OrderByName
+{
+public:
+  bool operator()(FGPositioned* a, FGPositioned* b) const
+  {
+    return a->name() < b->name();
+  }
+};
+
 /**
  * A special purpose helper (imported by FGAirport::searchNamesAndIdents) to
  * implement the AirportList dialog. It's unfortunate that it needs to reside
@@ -348,17 +358,19 @@ char** searchAirportNamesAndIdents(const std::string& aFilter)
 {
   const std::ctype<char> &ct = std::use_facet<std::ctype<char> >(std::locale());
   std::string filter(aFilter);
-  if (!filter.empty()) {
+  bool hasFilter = !filter.empty();
+  if (hasFilter) {
     ct.toupper((char *)filter.data(), (char *)filter.data() + filter.size());
   }
   
   NamedPositionedIndex::const_iterator it = global_namedIndex.begin();
   NamedPositionedIndex::const_iterator end = global_namedIndex.end();
   
-  FGPositioned::List matches;
-  if (aFilter.empty()) {
-    matches.reserve(2000);
-  }
+  // note this is a vector of raw pointers, not smart pointers, because it
+  // may get very large and smart-pointer-atomicity-locking then becomes a
+  // bottleneck for this case.
+  std::vector<FGPositioned*> matches;
+  std::string upper;
   
   for (; it != end; ++it) {
     FGPositioned::Type ty = it->second->type();
@@ -366,19 +378,20 @@ char** searchAirportNamesAndIdents(const std::string& aFilter)
       continue;
     }
     
-    if (aFilter.empty()) {
-      matches.push_back(it->second);
-      continue;
-    }
-    
-    if ((it->second->name().find(aFilter) == std::string::npos) &&
-        (it->second->ident().find(aFilter) == std::string::npos)) {
-      continue;
+    if (hasFilter && (it->second->ident().find(aFilter) == std::string::npos)) {
+      upper = it->second->name(); // string copy, sadly
+      ct.toupper((char *)upper.data(), (char *)upper.data() + upper.size());
+      if (upper.find(aFilter) == std::string::npos) {
+        continue;
+      }
     }
     
     matches.push_back(it->second);
   }
   
+  // sort alphabetically on name
+  std::sort(matches.begin(), matches.end(), OrderByName());
+  
   // convert results to format comptible with puaList
   unsigned int numMatches = matches.size();
   char** result = new char*[numMatches + 1];
@@ -386,23 +399,27 @@ char** searchAirportNamesAndIdents(const std::string& aFilter)
   
   // nasty code to avoid excessive string copying and allocations.
   // We format results as follows (note whitespace!):
-  //   ' name-of-airport-chars   (icao)'
+  //   ' name-of-airport-chars   (ident)'
   // so the total length is:
-  //    1 + strlen(name) + 4 + 4 (for the ICAO) + 1 + 1 (for the null)
+  //    1 + strlen(name) + 4 + 4 (for the ident) + 1 + 1 (for the null)
   // which gives a grand total of 11 + the length of the name.
-  
+  // note the ident is sometimes only three letters for non-ICAO small strips
   for (unsigned int i=0; i<numMatches; ++i) {
     int nameLength = matches[i]->name().size();
+    int icaoLength = matches[i]->ident().size();
     char* entry = new char[nameLength + 11];
-    entry[0] = ' ';
-    memcpy(entry + 1, matches[i]->name().c_str(), nameLength);
-    entry[nameLength + 1] = ' ';
-    entry[nameLength + 2] = ' ';
-    entry[nameLength + 3] = ' ';
-    entry[nameLength + 4] = '(';
-    memcpy(entry + nameLength + 5, matches[i]->ident().c_str(), 4);
-    entry[nameLength + 9] = ')';
-    entry[nameLength + 10] = 0;
+    char* dst = entry;
+    *dst++ = ' ';
+    memcpy(dst, matches[i]->name().c_str(), nameLength);
+    dst += nameLength;
+    *dst++ = ' ';
+    *dst++ = ' ';
+    *dst++ = ' ';
+    *dst++ = '(';
+    memcpy(dst, matches[i]->ident().c_str(), icaoLength);
+    dst += icaoLength;
+    *dst++ = ')';
+    *dst++ = 0;
     result[i] = entry;
   }