Skip to content

Instantly share code, notes, and snippets.

@pareis
Created April 1, 2012 23:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pareis/2279561 to your computer and use it in GitHub Desktop.
Save pareis/2279561 to your computer and use it in GitHub Desktop.
Java programming in C++
#include <iostream>
#include <sstream>
#include <assert.h>
#include <vector>
size_t globalRefCount = 0;
class Object;
class String;
std::ostream &operator<<(std::ostream&, Object&);
std::ostream &operator<<(std::ostream &, const String&);
class Object {
protected:
struct Impl {
size_t _refCount;
Impl() : _refCount(0) {}
virtual ~Impl() {}
} *data;
inline void retain() {
if(data) {
data->_refCount++;
globalRefCount++;
}
}
inline void release() {
if(data) {
data->_refCount--;
globalRefCount--;
if(data->_refCount == 0) {
delete data;
data = 0;
}
}
}
Object(): data(new Impl) {
retain();
}
Object(Impl *imp) : data(imp) {
retain();
}
Object(const Object& other): data(0) {
operator=(other);
}
public:
virtual ~Object() {
release();
}
virtual const char *type() const { return "Object"; }
void operator=(const Object& other) {
if(data!=other.data) {
release();
data = other.data;
retain();
}
}
// make a heap clone of this object for usage in containers
virtual Object *clone() const {
return new Object(*this);
}
virtual String toString() const;
};
class String : public Object {
protected:
struct Impl: public Object::Impl {
std::string str;
};
public:
String(): Object(new Impl) {}
String(const char *s): Object(new Impl) {
static_cast<Impl*>(data)->str = s;
}
String(const String &other): Object(other) {}
String operator+(const String& s) const {
String result;
static_cast<Impl*>(result.data)->str = static_cast<Impl*>(data)->str;
static_cast<Impl*>(result.data)->str += static_cast<Impl*>(s.data)->str;
return result;
}
String operator+(const Object& s) const {
String result;
static_cast<Impl*>(result.data)->str = static_cast<Impl*>(data)->str;
static_cast<Impl*>(result.data)->str += static_cast<Impl*>(s.toString().data)->str;
return result;
}
String operator+(long l) const {
std::ostringstream oss;
oss << static_cast<Impl*>(data)->str << l;
String result;
static_cast<Impl*>(result.data)->str = oss.str();
return result;
}
const char *c_str() const {
return static_cast<Impl*>(data)->str.c_str();
}
bool operator==(const String &other) const {
return static_cast<Impl*>(data)->str == static_cast<Impl*>(other.data)->str;
}
// must have's
const char *type() const { return "String"; }
Object *clone() const { return new String(*this); }
String toString() const {
return *this;
}
};
std::ostream &operator<<(std::ostream &os, const String& s) {
os << s.c_str();
return os;
}
String Object::toString() const {
std::ostringstream os;
os << this->type() << "@" << (void *)this << "[" << (data ? data->_refCount : 0) << "]";
return String(os.str().c_str());
}
std::ostream &operator<<(std::ostream &os, Object& o) {
os << o.toString().c_str();
return os;
}
class ClassCastException: public Object {
struct Impl: public Object::Impl {
String message;
};
public:
ClassCastException() : Object(new Impl) {}
ClassCastException(const String& msg) : Object(new Impl) {
static_cast<Impl*>(data)->message = msg;
}
const char *type() const { return "ClassCastException"; }
Object *clone() const { return new ClassCastException(*this); }
String message() const {
return static_cast<Impl*>(data)->message;
}
String toString() const {
return message();
}
};
class ArrayList: public Object {
struct Impl: public Object::Impl {
std::vector<Object*> _data;
};
public:
ArrayList(): Object(new Impl) {}
~ArrayList() {
Impl *self = static_cast<Impl*>(data);
for (std::vector<Object*>::iterator it = self->_data.begin(); it!=self->_data.end(); it++) {
delete *it;
}
}
void add(const Object& element) {
static_cast<Impl*>(data)->_data.push_back(element.clone());
}
size_t size() const {
return static_cast<Impl*>(data)->_data.size();
}
Object &at(size_t index) const {
return *static_cast<Impl*>(data)->_data.at(index);
}
template<class T> const T &at(size_t index) const {
Object *o = static_cast<Impl*>(data)->_data.at(index);
T *t = dynamic_cast<T*>(o);
if(t) return *t;
throw ClassCastException(o->type());
}
const char *type() const { return "ArrayList"; }
Object *clone() const { return new ArrayList(*this); }
String toString() const {
std::ostringstream oss;
oss << Object::toString() << "(";
for (size_t i = 0; i<size(); i++) {
oss << at(i).toString();
if(i+1<size()) {
oss << ",";
}
}
oss << ")";
return oss.str().c_str();
}
};
class OutputStream: public Object {
struct Impl: public Object::Impl {
std::ostream &stream;
Impl(std::ostream &os): stream(os) {}
};
OutputStream() {}
public:
OutputStream(std::ostream& os): Object(new Impl(os)) {}
OutputStream(const OutputStream &other): Object(other) {}
void println(const Object &object) {
static_cast<Impl*>(data)->stream << object.toString() << std::endl;
}
const char *type() const { return "OutputStream"; }
Object *clone() const { return new OutputStream(*this); }
};
struct system {
OutputStream out;
system(): out(std::cout) {}
};
struct system System;
int main (int argc, const char * argv[]) {
assert(globalRefCount==1); // 1 is for System.out
{
String s;
assert(globalRefCount==2);
}
assert(globalRefCount==1);
{
String s = "Connecting...";
System.out.println(String("s = ") + s);
String dots = "the dots";
String t = s + " " + dots + ".";
System.out.println(String("t = ") + t);
ArrayList l;
l.add(s);
assert(l.size() == 1);
assert(globalRefCount==6);
l.add(t);
l.add(ArrayList());
System.out.println(String("l = ") + l);
assert(globalRefCount==8);
try {
System.out.println(String("l[0] as String = ") + l.at<String>(0)); // ok
System.out.println(String("l[1] as String = ") + l.at<String>(1)); // ok
System.out.println(String("l[2] as String = ") + l.at<String>(2)); // this throws!
assert(false);
} catch(ClassCastException e) {
System.out.println(String("ClassCastException: ") + e);
l.add(e);
}
// adding to the list in other scope will keep the object valid
{
String other = "Created in other scope";
l.add(other);
}
System.out.println(String("l[3] as String = ") + l.at(3));
assert(l.size()==5);
assert(l.at<String>(4) == "Created in other scope");
System.out.println(String("l = ") + l);
}
assert(globalRefCount == 1);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment