changeset 15008:ff9a638a5555

preserve order of path elements when doing "path (new_path)" * load-path.cc, load-path.h (load_path::do_clear): Delete argument. Simply clear dir_info_list. (load_path::do_set, load_path::do_append, load_path::do_add): Eliminate is_init argument. (load_path::dir_info::is_init): Delete data member and all uses. (load_path::init_dirs): New data member. (load_path::do_set): Store default path elements in list and set. Warn about altering default load path. Preserve order of path elements.
author John W. Eaton <jwe@octave.org>
date Tue, 24 Jul 2012 13:13:45 -0400
parents 8f0e3c5bfa5f
children 6239f5806c26
files src/load-path.cc src/load-path.h
diffstat 2 files changed, 42 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/src/load-path.cc	Tue Jul 24 09:34:51 2012 -0700
+++ b/src/load-path.cc	Tue Jul 24 13:13:45 2012 -0400
@@ -523,36 +523,9 @@
 }
 
 void
-load_path::do_clear (std::set<std::string>& new_elts)
+load_path::do_clear (void)
 {
-  bool warn_default_path_clobbered = false;
-  for (dir_info_list_iterator i = dir_info_list.begin ();
-       i != dir_info_list.end ();
-       /* conditionally advance iterator in loop body */)
-    {
-      //Don't remove it if it's gonna be added again, but remove it from
-      //list of items to add, to avoid duplicates later on
-      std::set<std::string>::iterator j = new_elts.find (i->dir_name);
-      if (j != new_elts.end ())
-        {
-          new_elts.erase (j);
-          i++;
-        }
-      else
-        {
-          //Warn if removing a default directory and not immediately adding
-          //it back again
-          if (i->is_init)
-            warn_default_path_clobbered = true;
-          i = dir_info_list.erase (i);
-        }
-    }
-
-  if (warn_default_path_clobbered)
-    warning_with_id ("Octave:remove-init-dir",
-                     "default load path altered.  Some built-in functions may "
-                     "not be found.  Try restoredefaultpath() to recover it.");
-
+  dir_info_list.clear ();
   fcn_map.clear ();
   private_fcn_map.clear ();
   method_map.clear ();
@@ -594,8 +567,27 @@
 void
 load_path::do_set (const std::string& p, bool warn, bool is_init)
 {
-  std::list<std::string> elts_l = split_path (p);
-  std::set<std::string> elts(elts_l.begin (), elts_l.end ());
+  // Use a list when we need to preserve order.
+  std::list<std::string> elts = split_path (p);
+
+  // Use a set when we need to search and order is not important.
+  std::set<std::string> elts_set (elts.begin (), elts.end ());
+
+  if (is_init)
+    init_dirs = elts_set;
+  else
+    {
+      for (std::set<std::string>::const_iterator it = init_dirs.begin ();
+           it != init_dirs.end (); it++)
+        {
+          if (elts_set.find (*it) == elts_set.end ())
+            {
+              warning_with_id ("Octave:remove-init-dir",
+                               "default load path altered.  Some built-in functions may not be found.  Try restoredefaultpath() to recover it.");
+              break;
+            }
+        }
+    }
 
   // Temporarily disable add hook.
 
@@ -604,12 +596,11 @@
 
   add_hook = 0;
 
-  do_clear (elts);
-
-  for (std::set<std::string>::const_iterator i = elts.begin ();
-       i != elts.end ();
-       i++)
-    do_append (*i, warn, is_init);
+  do_clear ();
+
+  for (std::list<std::string>::const_iterator i = elts.begin ();
+       i != elts.end (); i++)
+    do_append (*i, warn);
 
   // Restore add hook and execute for all newly added directories.
   frame.run_top ();
@@ -627,10 +618,10 @@
 }
 
 void
-load_path::do_append (const std::string& dir, bool warn, bool is_init)
+load_path::do_append (const std::string& dir, bool warn)
 {
   if (! dir.empty ())
-    do_add (dir, true, warn, is_init);
+    do_add (dir, true, warn);
 }
 
 void
@@ -659,8 +650,7 @@
 }
 
 void
-load_path::do_add (const std::string& dir_arg, bool at_end, bool warn,
-                   bool is_init)
+load_path::do_add (const std::string& dir_arg, bool at_end, bool warn)
 {
   size_t len = dir_arg.length ();
 
@@ -685,7 +675,6 @@
           if (fs.is_dir ())
             {
               dir_info di (dir);
-              di.is_init = is_init;
 
               if (! error_state)
                 {
--- a/src/load-path.h	Tue Jul 24 09:34:51 2012 -0700
+++ b/src/load-path.h	Tue Jul 24 13:13:45 2012 -0400
@@ -39,7 +39,8 @@
 protected:
 
   load_path (void)
-    : dir_info_list (), fcn_map (), private_fcn_map (), method_map () { }
+    : dir_info_list (), fcn_map (), private_fcn_map (), method_map (),
+      init_dirs () { }
 
 public:
 
@@ -56,10 +57,7 @@
   static void clear (void)
   {
     if (instance_ok ())
-      {
-        std::set<std::string> no_new_elts;
-        instance->do_clear (no_new_elts);
-      }
+      instance->do_clear ();
   }
 
   static void set (const std::string& p, bool warn = false)
@@ -297,13 +295,13 @@
     // constructor for any other purpose.
     dir_info (void)
       : dir_name (), abs_dir_name (), is_relative (false),
-        is_init (false), dir_mtime (), dir_time_last_checked (),
+        dir_mtime (), dir_time_last_checked (),
         all_files (), fcn_files (), private_file_map (), method_file_map ()
       { }
 
     dir_info (const std::string& d)
       : dir_name (d), abs_dir_name (), is_relative (false),
-        is_init (false), dir_mtime (), dir_time_last_checked (),
+        dir_mtime (), dir_time_last_checked (),
         all_files (), fcn_files (), private_file_map (), method_file_map ()
     {
       initialize ();
@@ -312,7 +310,6 @@
     dir_info (const dir_info& di)
       : dir_name (di.dir_name), abs_dir_name (di.abs_dir_name),
         is_relative (di.is_relative),
-        is_init (di.is_init),
         dir_mtime (di.dir_mtime),
         dir_time_last_checked (di.dir_time_last_checked),
         all_files (di.all_files), fcn_files (di.fcn_files),
@@ -328,7 +325,6 @@
           dir_name = di.dir_name;
           abs_dir_name = di.abs_dir_name;
           is_relative = di.is_relative;
-          is_init = di.is_init;
           dir_mtime = di.dir_mtime;
           dir_time_last_checked = di.dir_time_last_checked;
           all_files = di.all_files;
@@ -345,7 +341,6 @@
     std::string dir_name;
     std::string abs_dir_name;
     bool is_relative;
-    bool is_init; //Was this directory set by init? Warn when clearing it.
     octave_time dir_mtime;
     octave_time dir_time_last_checked;
     string_vector all_files;
@@ -447,6 +442,8 @@
 
   mutable method_map_type method_map;
 
+  mutable std::set<std::string> init_dirs;
+
   static load_path *instance;
 
   static void cleanup_instance (void) { delete instance; instance = 0; }
@@ -477,16 +474,15 @@
 
   void do_initialize (bool set_initial_path);
 
-  void do_clear (std::set<std::string>& new_elts);
+  void do_clear (void);
 
-  void do_set (const std::string& p, bool warn, bool is_init=false);
+  void do_set (const std::string& p, bool warn, bool is_init = false);
 
-  void do_append (const std::string& dir, bool warn, bool is_init=false);
+  void do_append (const std::string& dir, bool warn);
 
   void do_prepend (const std::string& dir, bool warn);
 
-  void do_add (const std::string& dir, bool at_end, bool warn,
-               bool is_init=false);
+  void do_add (const std::string& dir, bool at_end, bool warn);
 
   void remove_fcn_map (const std::string& dir, const string_vector& fcn_files);