00001 #ifndef __J2K__JString_Extra_CPP__ 00002 #define __J2K__JString_Extra_CPP__ 00003 00004 #include <j2k/Fred/String/String.hpp> 00005 00006 /* 00007 Functions defined: 00008 ------------------ 00009 AllocBuffer( size ) 00010 AllocBeforeWrite( size ) 00011 GetBuffer( size ) 00012 ReleaseBuffer() 00013 FreeExtra() 00014 LockBuffer() 00015 UnlockBuffer() 00016 00017 Functions used: 00018 --------------- 00019 CopyBeforeWrite() 00020 */ 00021 00022 // ALL THESE ARE FOR EXTERNAL USAGE ONLY ! 00023 00024 /** ANDREA *************************************************** 00025 00026 I didn't know the term "external usage". What does that mean ? 00027 That users of the class can use these methods but implementer 00028 are forbidden to ? 00029 00030 No, it comes from CString, it means that users are able 00031 to screw up the char* as they want. 00032 00033 "External usage of internal privates..." 00034 00035 *************************************************************/ 00036 00037 inline void JString::AllocBuffer(ULONG Len) { 00038 pData->Dec(); 00039 pData = new JStringData( Len ); 00040 } 00041 00042 inline void JString::AllocBeforeWrite(ULONG Len) { 00043 if ( pData == strNull || pData->nbRefs > 1 || Len > pData->bufferSize ) { 00044 pData->Dec(); 00045 pData = new JStringData( Len ); 00046 } 00047 } 00048 00049 //////////////////////////////////////////////////////////////////////////// 00050 // Advanced direct buffer access 00051 //////////////////////////////////////////////////////////////////////////// 00052 00053 char* JString::GetBuffer(ULONG minBuf) { 00054 00055 if (pData == strNull) { 00056 return ""; 00057 } 00058 00059 /** ANDREA *************************************************** 00060 00061 We are ignoring the minBuf parameter. Is this the intended 00062 behaviour ? This surprises me. It means that 00063 00064 char *b=s.GetBuffer(100); 00065 // Now i've a pointer to 100 chars (minimum) 00066 // or may be not if the string was initially empty. 00067 00068 If it's empty then you get nothing, maybe I could provide an empty bigger ?! 00069 00070 *************************************************************/ 00071 00072 if (pData->lock != 0) { // Already locked ! 00073 pData->lock++; 00074 return pData->data; 00075 } 00076 00077 /** ANDREA *************************************************** 00078 00079 Here we ignored the minBuf parameter. Is this correct ? 00080 This surprises me even more. 00081 00082 char *b=s.GetBuffer(100); 00083 // Now i've a pointer to 100 chars (minimum) 00084 // or may be less if someone got the buffer too 00085 // before me and asked for a smaller minimum size. 00086 00087 If it's lock it's lock. 00088 It's not expected behavior. 00089 00090 *************************************************************/ 00091 00092 if ( pData->nbRefs > 1 || minBuf > pData->bufferSize) { 00093 // We have to create a new buffer 00094 if ( minBuf < pData->length ) { 00095 minBuf = pData->length; 00096 } 00097 00098 JStringData* pOldData = pData; 00099 pData = new JStringData( pData->data, minBuf ); 00100 pOldData->Dec(); 00101 } 00102 00103 pData->lock = 1; 00104 00105 // return a pointer to the character storage for this JString 00106 return pData->data; 00107 } 00108 00109 inline void JString::ReleaseBuffer() { 00110 if (pData == strNull) return; 00111 pData->lock--; 00112 pData->Dec(); // Destroy the object, if NO Lock ! 00113 00114 /** ANDREA *************************************************** 00115 00116 After calling ReleaseBuffer the string object is pointing 00117 to an istance of JStringData that has been destroyed. 00118 00119 NO? Unless the user delete it ? 00120 I should check maybe for pData == NULL ? 00121 00122 This means that when the string object will be destroyed 00123 too it will call Dec() on a dead object. 00124 This means undefined behaviour. 00125 00126 hmmm. 00127 *************************************************************/ 00128 } 00129 00130 void JString::FreeExtra() { 00131 if (pData == strNull ) return; 00132 if (pData->length <= 0 ) { 00133 pData->Dec(); 00134 pData = strNull; 00135 return; 00136 } 00137 00138 if (pData->length < pData->bufferSize) { 00139 JStringData* pOldData = pData; 00140 pData = new JStringData( pOldData->data, pOldData->length ); 00141 pOldData->Dec(); 00142 } 00143 } 00144 00145 inline char* JString::LockBuffer() { 00146 return GetBuffer( 0 ); 00147 } 00148 00149 inline void JString::UnlockBuffer() { 00150 ReleaseBuffer(); // The object is Destroy, if NO Lock ! 00151 /** ANDREA *************************************************** 00152 00153 No... the JStringData object is destroyed; not the object. 00154 This generates a serious double-destroy problem or a may 00155 be more subtle memory overwrite: normally good debug memory 00156 handlers can detect a simple double destruction, but if the 00157 memory is reallocated to some other object then you're just 00158 going to access some raw memory considering it a JStringData 00159 object. Even worse there is an high probability that the 00160 memory area will be allocated to just another JStringData 00161 object with even more subtle long-term effects. 00162 00163 And your wonderful "safety checks" are probably going to 00164 further delay the discovery of such problems probably 00165 several millions instructions after this bug gave its bite. 00166 00167 But if you got your A+ in the meanwhile... 00168 00169 00170 Let me think about it again, it comes from CString ( MFC lib ) 00171 it not a safe feature, but I wanted to be compatible... hmmm. 00172 *************************************************************/ 00173 } 00174 00175 #endif