view src/fn-cache.cc @ 2232:834eab508368

[project @ 1996-05-17 17:11:40 by jwe] Initial revision
author jwe
date Fri, 17 May 1996 17:11:40 +0000
parents
children 0da2c91573d9
line wrap: on
line source

/*

Copyright (C) 1996 John W. Eaton

This file is part of Octave.

Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.

Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING.  If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <string>

#include "file-ops.h"
#include "str-vec.h"

#include "defaults.h"
#include "dir-ops.h"
#include "dirfns.h"
#include "error.h"
#include "fn-cache.h"
#include "pathsearch.h"

octave_fcn_file_name_cache *octave_fcn_file_name_cache::instance = 0;

// Update the cache.  Returns TRUE if something needed to be updated.

// XXX FIXME XXX -- I suppose we could also keep track of the load
// path.  Then if a directory is deleted from the load path, we could
// also delete it from the cache.  Currently, we just accumulate all
// directories ever referenced in the cache.

bool
octave_fcn_file_name_cache::update (void)
{
  bool retval = false;

  dir_path p (Vload_path);

  string_vector dirs = p.all_directories ();

  int len = dirs.length ();

  for (int i = 0; i < len; i++)
    {
      string d = dirs[i];

      if (cache.contains (d))
	{
	  if (cache[d].update (d))
	    retval = true;
	}
      else
	{
	  cache[d] = file_name_cache_elt (d);
	  retval = true;
	}
    }

  return retval;
}

// Check to see if any of the elements in the cache need to be
// updated, then return the list of names in the cache.

string_vector
octave_fcn_file_name_cache::do_list (bool no_suffix)
{
  // Only recompute the cache if something has changed.

  if (update ())
    {
      int total_len = 0;

      dir_path p (Vload_path);

      string_vector dirs = p.all_directories ();

      int ndirs = dirs.length ();

      for (int i = 0; i < ndirs; i++)
	{
	  string d = dirs[i];

	  total_len += cache[d].length ();
	}

      fcn_file_names.resize (total_len);
      fcn_file_names_no_suffix.resize (total_len);

      int k = 0;

      for (int j = 0; j < ndirs; j++)
	{
	  string d = dirs[j];

	  file_name_cache_elt elt = cache[d];

	  int len = elt.length ();

	  string_vector ffn = elt.fcn_file_names;
	  string_vector ffnns = elt.fcn_file_names_no_suffix;

	  for (int i = 0; i < len; i++)
	    {
	      fcn_file_names[k] = ffn[i];
	      fcn_file_names_no_suffix[k] = ffnns[i];

	      k++;
	    }
	}
    }

  return no_suffix ? fcn_file_names_no_suffix : fcn_file_names;
}

string_vector
octave_fcn_file_name_cache::list (bool no_suffix = false)
{
  string_vector retval;

  if (! instance)
    instance = new octave_fcn_file_name_cache ();

  if (instance)
    retval = instance->do_list (no_suffix);
  else
    panic_impossible ();

  return retval;
}

// Create a list of the function names in a given directory.  Returns
// TRUE if the cache element was out of date.

bool
file_name_cache_elt::update (const string& dir_name)
{
  bool retval = false;

  file_stat file (dir_name);

  // If the directory doesn't exist, delete the names in the cache.
  // If it does exist,read it only if it is out of date.

  if (file)
    {
      if (file.is_newer (timestamp))
	{
	  retval = true;

	  timestamp = file.mtime ();

	  dir_entry dir (dir_name);

	  if (dir)
	    {
	      string_vector tmp = dir.read ();

	      int max_len = tmp.length ();

	      fcn_file_names.resize (max_len);
	      fcn_file_names_no_suffix.resize (max_len);

	      int k = 0;
	      int i;
	      for (i = 0; i < max_len; i++)
		{
		  string entry = tmp[i];

		  int len = entry.length ();

#if defined (WITH_DYNAMIC_LINKING)
		  if ((len > 2
		       && entry[len-2] == '.' && entry[len-1] == 'm')
		      || (len > 4
			  && entry[len-4] == '.' && entry[len-3] == 'o'
			  && entry[len-2] == 'c' && entry[len-1] == 't'))
#else
		  if (len > 2
		      && entry[len-2] == '.' && entry[len-1] == 'm')
#endif
		    {
		      fcn_file_names[k] = entry;

		      fcn_file_names_no_suffix[k] = (entry[len-1] == 'm')
			? string (entry, 0, len-2)
			: string (entry, 0, len-4);

		      k++;
		    }
		}

	      fcn_file_names.resize (k);
	      fcn_file_names_no_suffix.resize (k);
	    }
	  else
	    {
	      fcn_file_names.resize (0);
	      fcn_file_names_no_suffix.resize (0);
	    }
	}
    }
  else
    {
      fcn_file_names.resize (0);
      fcn_file_names_no_suffix.resize (0);
    }

  return retval;
}

/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/