xstr.h 3.84 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*
 * EMULAB-COPYRIGHT
 * Copyright (c) 2005-2008 University of Utah and the Flux Group.
 * All rights reserved.
 */

#ifndef __XSTR_H
#define __XSTR_H


#include <string>
using namespace std;
#include <xercesc/util/XMLString.hpp>
XERCES_CPP_NAMESPACE_USE

#include "fstring.h"

/*
 * This class provides for conversion between Xerces' internal XMLCh* type
 * (which is 16 bits wide to hold international characters) and simple
 * char*s. You can construct an XStr with either type, and then call C() or
 * x() to get back the desired type of string. XStr works out on its own what
 * conversion needs to happen, and frees it up in its destructor (normally,
 * when it goes out of scope.)
 *
 * DO NOT MAKE POINTERS TO THIS CLASS - that would defeat the whole purpose
 * of it's string memory management.
 */
class XStr {
public:
31 32
    XStr(const char *_str) : cstr(_str), transcoded(NULL), xmlstr(NULL)
			     /*, fstr(NULL),
33
                             fstr_mine(false)  */ { ; };
34 35
    XStr(const XMLCh *_str) : cstr(NULL), transcoded(NULL), xmlstr(NULL)
			      /*, fstr(NULL), fstr_mine(false) */ {
36 37
	xmlstr = XMLString::replicate(_str);
    };
38 39
    XStr(const fstring &_str) : /* fstr_mine(true), */
      transcoded(NULL), xmlstr(NULL) {
40 41 42 43 44
	//fstr = new fstring(_str);
	cstr = _str.c_str();
    };
    
    ~XStr() {
45 46
	if (transcoded != NULL) {
	    XMLString::release(&transcoded);
47
	}
48
	if (xmlstr != NULL) {
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
	    XMLString::release(&xmlstr);
	}
	/*if (fstr_mine && fstr != NULL) {
	    delete fstr;
	}*/
    };
    
    /*
     * Convert to a Xerces string (XMLCh *)
     */
    const XMLCh *x() {
	if (this->xmlstr == NULL) {
	    this->xmlstr = XMLString::transcode(this->cstr);
	}
	return this->xmlstr;
    };
    
    /*
     * convert to a C-style string (null-terminated char*)
     */
    const char *c() {
	if (this->cstr == NULL) {
71 72
	    this->transcoded = XMLString::transcode(this->xmlstr);
	    this->cstr = this->transcoded;
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
	}
	return this->cstr;
    };
    
    /*
     * convert to the fstring type used internally in assign
     */
    fstring f() {
	/*if (this->fstr == NULL) {
	    this->fstr = new fstring(this->c());
	    this->fstr_mine = true;
	}*/
	return fstring(this->c());
    };
    
    /*
     * Convert to an integer - throws an exception if the string isn't
     * one
     */
    int i() {
	int converted;
	if (sscanf(this->c(),"%d",&converted) == 1) {
	    return converted;
	} else {
	    throw("Tried to convert an non-integer to an integer");
	}
    }
    
    /*
     * Convert to a double - throws and exception if the string isn't one
     */
    double d() {
	double converted;
	if (sscanf(this->c(),"%lf",&converted) == 1) {
	    return converted;
	} else {
	    throw("Tried to convert an non-double to a double");
	}
    }
    
    bool operator==(const char * const other) {
	return (strcmp(this->c(),other) == 0);
    };
    bool operator!=(const char * const other) {
	return (strcmp(this->c(),other) != 0);
    };
    
    /*
     * Crazy, I know, but this is how you tell C++ it can implicilty convert
     * an XString into other data types. Thanks to Jon Duerig and the ghost 
     * of Bjarne Stroustrup (really, his C++ book) for helping me figure 
     * this out.
     */
    operator const char*() { return this->c(); };
    // Note, this operator commented out because some functions that can 
    // take either a char* or an XMLch* get confused if we have conversions
    // to both
    //operator const XMLCh*() { return this->x(); };
    
private:
    const char *cstr;
134
    char * transcoded;
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    XMLCh *xmlstr;

    /*
     * Make the copy and assignment constructors private - I haven't decided
     * on their semantics yet, and want to make sure they are not called
     * automatically
     */
    const XStr &operator=(const XStr& other) { return(other); };
    XStr(const XStr& other) { ; };
    
    /*
    fstring *fstr;
    bool fstr_mine;
     */
};

#endif