diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/test/namedtempfile.h | 97 | 
1 files changed, 94 insertions, 3 deletions
diff --git a/indra/test/namedtempfile.h b/indra/test/namedtempfile.h index aa7058b111..6069064627 100644 --- a/indra/test/namedtempfile.h +++ b/indra/test/namedtempfile.h @@ -12,6 +12,7 @@  #if ! defined(LL_NAMEDTEMPFILE_H)  #define LL_NAMEDTEMPFILE_H +#include "llerror.h"  #include "llapr.h"  #include "apr_file_io.h"  #include <string> @@ -28,6 +29,7 @@   */  class NamedTempFile: public boost::noncopyable  { +    LOG_CLASS(NamedTempFile);  public:      NamedTempFile(const std::string& pfx, const std::string& content, apr_pool_t* pool=gAPRPoolp):          mPool(pool) @@ -53,12 +55,12 @@ public:          createFile(pfx, func);      } -    ~NamedTempFile() +    virtual ~NamedTempFile()      {          ll_apr_assert_status(apr_file_remove(mPath.c_str(), mPool));      } -    std::string getName() const { return mPath; } +    virtual std::string getName() const { return mPath; }      void peep()      { @@ -70,7 +72,7 @@ public:          std::cout << "---\n";      } -private: +protected:      void createFile(const std::string& pfx, const Streamer& func)      {          // Create file in a temporary place. @@ -111,4 +113,93 @@ private:      apr_pool_t* mPool;  }; +/** + * Create a NamedTempFile with a specified filename extension. This is useful + * when, for instance, you must be able to use the file in a Python import + * statement. + * + * A NamedExtTempFile actually has two different names. We retain the original + * no-extension name as a placeholder in the temp directory to ensure + * uniqueness; to that we link the name plus the desired extension. Naturally, + * both must be removed on destruction. + */ +class NamedExtTempFile: public NamedTempFile +{ +    LOG_CLASS(NamedExtTempFile); +public: +    NamedExtTempFile(const std::string& ext, const std::string& content, apr_pool_t* pool=gAPRPoolp): +        NamedTempFile(remove_dot(ext), content, pool), +        mLink(mPath + ensure_dot(ext)) +    { +        linkto(mLink); +    } + +    // Disambiguate when passing string literal +    NamedExtTempFile(const std::string& ext, const char* content, apr_pool_t* pool=gAPRPoolp): +        NamedTempFile(remove_dot(ext), content, pool), +        mLink(mPath + ensure_dot(ext)) +    { +        linkto(mLink); +    } + +    NamedExtTempFile(const std::string& ext, const Streamer& func, apr_pool_t* pool=gAPRPoolp): +        NamedTempFile(remove_dot(ext), func, pool), +        mLink(mPath + ensure_dot(ext)) +    { +        linkto(mLink); +    } + +    virtual ~NamedExtTempFile() +    { +        ll_apr_assert_status(apr_file_remove(mLink.c_str(), mPool)); +    } + +    // Since the caller has gone to the trouble to create the name with the +    // extension, that should be the name we return. In this class, mPath is +    // just a placeholder to ensure that future createFile() calls won't +    // collide. +    virtual std::string getName() const { return mLink; } + +    static std::string ensure_dot(const std::string& ext) +    { +        if (ext.empty()) +        { +            // What SHOULD we do when the caller makes a point of using +            // NamedExtTempFile to generate a file with a particular +            // extension, then passes an empty extension? Use just "."? That +            // sounds like a Bad Idea, especially on Windows. Treat that as a +            // coding error. +            LL_ERRS("NamedExtTempFile") << "passed empty extension" << LL_ENDL; +        } +        if (ext[0] == '.') +        { +            return ext; +        } +        return std::string(".") + ext; +    } + +    static std::string remove_dot(const std::string& ext) +    { +        std::string::size_type found = ext.find_first_not_of("."); +        if (found == std::string::npos) +        { +            return ext; +        } +        return ext.substr(found); +    } + +private: +    void linkto(const std::string& path) +    { +        // This method assumes that since mPath (without extension) is +        // guaranteed by apr_file_mktemp() to be unique, then (mPath + any +        // extension) is also unique. This is likely, though not guaranteed: +        // files could be created in the same temp directory other than by +        // this class. +        ll_apr_assert_status(apr_file_link(mPath.c_str(), path.c_str())); +    } + +    std::string mLink; +}; +  #endif /* ! defined(LL_NAMEDTEMPFILE_H) */  | 
