00001 // -*- C++ -*- 00002 // Little library of copy-on-write wrappers 00003 // Copyright (C) 2007- Leon Bottou 00004 00005 00006 // This library is free software; you can redistribute it and/or 00007 // modify it under the terms of the GNU Lesser General Public 00008 // License as published by the Free Software Foundation; either 00009 // version 2.1 of the License, or (at your option) any later version. 00010 // 00011 // This program is distributed in the hope that it will be useful, 00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 // GNU General Public License for more details. 00015 // 00016 // You should have received a copy of the GNU General Public License 00017 // along with this program; if not, write to the Free Software 00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA 00019 00020 00021 00022 // $Id: wrapper.h,v 1.8 2007/10/02 20:40:06 cvs Exp $ 00023 00024 00025 #ifndef WRAPPER_H 00026 #define WRAPPER_H 1 00027 00028 00029 template <class Rep> 00030 class Wrapper 00031 { 00032 private: 00033 Rep *q; 00034 Rep *ref(Rep *q) { q->refcount++; return q; } 00035 void deref(Rep *q) { if (! --(q->refcount)) delete q; } 00036 00037 public: 00038 Wrapper() 00039 : q(new Rep) { q->refcount = 1; } 00040 Wrapper(Rep *rep) 00041 : q(rep) { q->refcount = 1; } 00042 Wrapper(const Wrapper<Rep> &other) 00043 : q(ref(other.q)) {} 00044 ~Wrapper() 00045 { deref(q); } 00046 Wrapper& operator=(const Wrapper<Rep> &other) 00047 { Rep *p = q; q = ref(other.q); deref(p); return *this; } 00048 void detach() 00049 { if (q->refcount > 1) { deref(q); q=q->copy(); q->refcount=1; } } 00050 Rep *rep() const 00051 { return q; } 00052 }; 00053 00054 00055 00056 // Recommended usage 00057 // 00058 // #include <cstdlib> 00059 // #include <cstring> 00060 // 00061 // class String 00062 // { 00063 // private: 00064 // 00065 // struct Rep 00066 // { 00067 // int refcount; 00068 // int length; 00069 // char *data; 00070 // Rep(const char *s, int l) 00071 // : length(len), data(new char[l+1]) 00072 // { ::memcpy(data, s, l); data[len] = 0; } 00073 // Rep *copy() 00074 // { return new StringRep(data, length); } 00075 // }; 00076 // 00077 // Wrapper<Rep> w; 00078 // Rep *rep() { return w.rep(); } 00079 // const Rep *rep() const { return w.rep(); } 00080 // 00081 // public: 00082 // String(const char *s, int l) 00083 // : w(new Rep(s,l)) {} 00084 // String(const char *s) 00085 // : w(new Rep(s,::strlen(s))) {} 00086 // 00087 // // function that do not mutate 00088 // int size() const { return rep()->length; } 00089 // operator const char*() const { return rep()->data; } 00090 // char operator[](int i) const { return rep()->data[i]; } 00091 // 00092 // // functions that perform a mutation 00093 // void set(int i, char c) { w.detach(); rep()->data[i] = c; } 00094 // } 00095 // 00096 00097 00098 00099 #endif 00100 00101 00102 00103 /* ------------------------------------------------------------- 00104 Local Variables: 00105 c++-font-lock-extra-types: ( "\\sw+_t" "[A-Z]\\sw*[a-z]\\sw*" ) 00106 End: 00107 ------------------------------------------------------------- */