/* FILE: util.cc -*-Mode: c++-*- * * Small utility classes * */ #include #include "oc.h" #include "nb.h" #include "threevector.h" #include "util.h" /* End includes */ //////////////////////////////////////////////////////////////////////// // Oxs_SplitList void Oxs_SplitList::Release() { if(argv!=NULL) { Tcl_Free((char *)argv); argv=NULL; } argc=0; } Oxs_SplitList::~Oxs_SplitList() { Release(); } int Oxs_SplitList::Split(const char* argstr) { Release(); char *str = new char[strlen(argstr)+1]; strcpy(str,argstr); int errcode=Tcl_SplitList(NULL,str,&argc,&argv); delete[] str; return errcode; } void Oxs_SplitList::FillParams(vector& params) const { params.clear(); for(int i=0;i=argc || argv==NULL) return NULL; return argv[n]; } #if (TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION==8 && TCL_MINOR_VERSION>0)) //////////////////////////////////////////////////////////////////////// // Wrapper for Tcl_Obj** Oxs_TclObjArray::Oxs_TclObjArray(int arrsize) { if(arrsize<0) { char buf[512]; Oc_Snprintf(buf,sizeof(buf), "Oxs_TclObjArray constructor: " "Invalid arrsize=%d (must be non-negative)", arrsize); OXS_THROW(Oxs_BadIndex,buf); } size=arrsize; arr = new Tcl_Obj*[size]; for(int i=0;i=size || index<0) { char buf[512]; Oc_Snprintf(buf,sizeof(buf), "const Tcl_Obj*& Oxs_TclObjArray::operator[] const: " "Array out-of-bounds; index=%d, size=%d", index,size); OXS_THROW(Oxs_BadIndex,buf); } #endif return static_cast(arr[index]); /// Brute-force the cast, which assumes that there is no storage /// difference between TclObj* and const TclObj*, at least in /// the indicated direction. This cast is needed by some compilers, /// which otherwise return a reference to a temporary, which is /// definitely *not* what we want! } OxsTclObjPtrRef Oxs_TclObjArray::operator[](int index) { #ifndef NDEBUG if(index>=size || index<0) { char buf[512]; Oc_Snprintf(buf,sizeof(buf), "Tcl_Obj*& Oxs_TclObjArray::operator[]: " "Array out-of-bounds; index=%d, size=%d", index,size); OXS_THROW(Oxs_BadIndex,buf); } #endif return arr[index]; } // Write interface routines. These handle the // copy-on-write semantics of the Tcl referencing // system. We can included additional routines // when needed. void Oxs_TclObjArray::WriteString(int index,const char* cptr) { #ifndef NDEBUG if(index>=size || index<0) { char buf[512]; Oc_Snprintf(buf,sizeof(buf), "void Oxs_TclObjArray::WriteString: " "Array out-of-bounds; index=%d, string=%s", index,cptr); OXS_THROW(Oxs_BadIndex,buf); } #endif Tcl_Obj* obj = arr[index]; if (Tcl_IsShared(obj)) { Tcl_Obj* tmp = obj; arr[index] = obj = Tcl_DuplicateObj(obj); // Create copy to write on Tcl_IncrRefCount(obj); Tcl_DecrRefCount(tmp); } Tcl_SetStringObj(obj, Oc_AutoBuf(cptr), static_cast(strlen(cptr))); } void Oxs_TclObjArray::WriteString(int index,const string& str) { WriteString(index,str.c_str()); } void Oxs_TclObjArray::WriteDouble(int index,double val) { #ifndef NDEBUG if(index>=size || index<0) { char buf[512]; Oc_Snprintf(buf,sizeof(buf), "void Oxs_TclObjArray::WriteDouble: " "Array out-of-bounds; index=%d, double=%g", index,val); OXS_THROW(Oxs_BadIndex,buf); } #endif Tcl_Obj* obj = arr[index]; if (Tcl_IsShared(obj)) { Tcl_Obj* tmp = obj; arr[index] = obj = Tcl_DuplicateObj(obj); // Create copy to write on Tcl_IncrRefCount(obj); Tcl_DecrRefCount(tmp); } Tcl_SetDoubleObj(obj,val); } void Oxs_TclObjArray::WriteInt(int index,int val) { #ifndef NDEBUG if(index>=size || index<0) { char buf[512]; Oc_Snprintf(buf,sizeof(buf), "void Oxs_TclObjArray::WriteInt: " "Array out-of-bounds; index=%d, int=%ld", index,val); OXS_THROW(Oxs_BadIndex,buf); } #endif Tcl_Obj* obj = arr[index]; if (Tcl_IsShared(obj)) { Tcl_Obj* tmp = obj; arr[index] = obj = Tcl_DuplicateObj(obj); // Create copy to write on Tcl_IncrRefCount(obj); Tcl_DecrRefCount(tmp); } Tcl_SetIntObj(obj,val); } void Oxs_TclObjArray::WriteLong(int index,long val) { #ifndef NDEBUG if(index>=size || index<0) { char buf[512]; Oc_Snprintf(buf,sizeof(buf), "void Oxs_TclObjArray::WriteLong: " "Array out-of-bounds; index=%d, long=%ld", index,val); OXS_THROW(Oxs_BadIndex,buf); } #endif Tcl_Obj* obj = arr[index]; if (Tcl_IsShared(obj)) { Tcl_Obj* tmp = obj; arr[index] = obj = Tcl_DuplicateObj(obj); // Create copy to write on Tcl_IncrRefCount(obj); Tcl_DecrRefCount(tmp); } Tcl_SetLongObj(obj,val); } string Oxs_TclObjArray::GetString(int index) const { #ifndef NDEBUG if(index>=size || index<0) { char buf[512]; Oc_Snprintf(buf,sizeof(buf), "string Oxs_TclObjArray::GetString: " "Array out-of-bounds; index=%d", index); OXS_THROW(Oxs_BadIndex,buf); } #endif return string(Tcl_GetString(arr[index])); } #endif // Tcl version check //////////////////////////////////////////////////////////////////////// // Wrappers for Tcl_Merge(). string Oxs_MergeList(const vector* args) { string result; if(args==NULL || args->size()<1) { return result; // Return empty string } // Life would be so much simpler if Tcl would use const char* // instead of char* in parameter lists. Sigh... int argc = args->size(); Oc_AutoBuf* mybuf = new Oc_AutoBuf[argc]; char **argv = new char*[argc]; for(int i=0;i& args) { return Oxs_MergeList(&args); } #if (TCL_MAJOR_VERSION > 8 || (TCL_MAJOR_VERSION==8 && TCL_MINOR_VERSION>0)) string Oxs_MergeList(const Oxs_TclObjArray& arr) { string result; int argc = arr.Size(); if(argc<1) { return result; // Return empty string } // Life would be so much simpler if Tcl would use const char* // instead of char* in parameter lists. Sigh... Oc_AutoBuf* mybuf = new Oc_AutoBuf[argc]; char **argv = new char*[argc]; for(int i=0;ix1) { x1 = other.x1; expanded=1; } if(other.y1>y1) { y1 = other.y1; expanded=1; } if(other.z1>z1) { z1 = other.z1; expanded=1; } return expanded; } BOOL Oxs_Box::Expand(REAL8m x,REAL8m y,REAL8m z) { // Similar to Expand(const Oxs_Box&), but with a single point import // instead of a box. Returns 1 if *this was enlarged, 0 if (x,y,z) // was already contained in *this. if(IsEmpty()) { // *this is an empty box x0=x1=x; y0=y1=y; z0=z1=z; return 1; } BOOL expanded=0; if(xx1) { x1 = x; expanded=1; } if(y>y1) { y1 = y; expanded=1; } if(z>z1) { z1 = z; expanded=1; } return expanded; } BOOL Oxs_Box::Intersect(const Oxs_Box& other) { // Shrinks *this as necessary so that the resulting box // is the intersection of the original *this with other. // Returns 1 if *this is shrunk, 0 if *this is already // contained inside other. if(IsEmpty()) return 0; // *this is already empty if(other.IsEmpty()) { // "other" is an empty box MakeEmpty(); return 1; // We only get to this clause if *this /// was not empty coming in. } BOOL shrunk=0; if(other.x0>x0) { x0 = other.x0; shrunk=1; } if(other.y0>y0) { y0 = other.y0; shrunk=1; } if(other.z0>z0) { z0 = other.z0; shrunk=1; } if(other.x1x1 || point.yy1 || point.zz1) return 0; return 1; } BOOL Oxs_Box::IsContained(const Oxs_Box& other) const { if(other.x0>other.x1) return 1; // "other" is an empty box if(x0>x1) return 0; // *this is an empty box if(other.x0x1 || other.y0y1 || other.z0z1) return 0; return 1; }