1 /*
2    Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include "Rope.hpp"
26 #include "DataBuffer2.hpp"
27 
28 #define JAM_FILE_ID 330
29 
30 
31 #define DEBUG_ROPE 0
32 
33 void
copy(char * buf) const34 ConstRope::copy(char* buf) const {
35   char * ptr = buf;
36   if(DEBUG_ROPE)
37     ndbout_c("ConstRope::copy() head = [ %d 0x%x 0x%x ]",
38 	     head.used, head.firstItem, head.lastItem);
39   Uint32 left = head.used;
40   Ptr<Segment> curr;
41   curr.i = head.firstItem;
42   while(left > 4 * getSegmentSize()){
43     thePool.getPtr(curr);
44     memcpy(buf, curr.p->data, 4 * getSegmentSize());
45     curr.i = curr.p->nextPool;
46     left -= 4 * getSegmentSize();
47     buf += 4 * getSegmentSize();
48   }
49   if(left > 0){
50     thePool.getPtr(curr);
51     memcpy(buf, curr.p->data, left);
52   }
53 
54   if(DEBUG_ROPE)
55     ndbout_c("ConstRope::copy()-> %s", ptr);
56 }
57 
58 int
compare(const char * str,Uint32 len) const59 ConstRope::compare(const char * str, Uint32 len) const {
60   if(DEBUG_ROPE)
61     ndbout_c("ConstRope[ %d  0x%x  0x%x ]::compare(%s, %d)",
62 	     head.used, head.firstItem, head.lastItem, str, (int) len);
63   Uint32 left = head.used > len ? len : head.used;
64   Ptr<Segment> curr;
65   curr.i = head.firstItem;
66   while(left > 4 * getSegmentSize()){
67     thePool.getPtr(curr);
68     int res = memcmp(str, (const char*)curr.p->data, 4 * getSegmentSize());
69     if(res != 0){
70       if(DEBUG_ROPE)
71 	ndbout_c("ConstRope::compare(%s, %d, %s) -> %d", str, left,
72 		 (const char*)curr.p->data, res);
73       return res;
74     }
75     curr.i = curr.p->nextPool;
76     left -= 4 * getSegmentSize();
77     str += 4 * getSegmentSize();
78   }
79 
80   if(left > 0){
81     thePool.getPtr(curr);
82     int res = memcmp(str, (const char*)curr.p->data, left);
83     if(res){
84       if(DEBUG_ROPE)
85 	ndbout_c("ConstRope::compare(%s, %d, %s) -> %d",
86 		 str, left, (const char*)curr.p->data, res);
87       return res;
88     }
89   }
90   if(DEBUG_ROPE)
91     ndbout_c("ConstRope::compare(%s, %d) -> %d", str, (int) len, head.used > len);
92   return head.used > len;
93 }
94 
95 void
copy(char * buf) const96 LocalRope::copy(char* buf) const {
97   char * ptr = buf;
98   if(DEBUG_ROPE)
99     ndbout_c("LocalRope::copy() head = [ %d 0x%x 0x%x ]",
100 	     head.used, head.firstItem, head.lastItem);
101   Uint32 left = head.used;
102   Ptr<Segment> curr;
103   curr.i = head.firstItem;
104   while(left > 4 * getSegmentSize()){
105     thePool.getPtr(curr);
106     memcpy(buf, curr.p->data, 4 * getSegmentSize());
107     curr.i = curr.p->nextPool;
108     left -= 4 * getSegmentSize();
109     buf += 4 * getSegmentSize();
110   }
111   if(left > 0){
112     thePool.getPtr(curr);
113     memcpy(buf, curr.p->data, left);
114   }
115   if(DEBUG_ROPE)
116     ndbout_c("LocalRope::copy()-> %s", ptr);
117 }
118 
119 int
compare(const char * str,Uint32 len) const120 LocalRope::compare(const char * str, Uint32 len) const {
121   if(DEBUG_ROPE)
122     ndbout_c("LocalRope::compare(%s, %d)", str, (int) len);
123   Uint32 left = head.used > len ? len : head.used;
124   Ptr<Segment> curr;
125   curr.i = head.firstItem;
126   while(left > 4 * getSegmentSize()){
127     thePool.getPtr(curr);
128     int res = memcmp(str, (const char*)curr.p->data, 4 * getSegmentSize());
129     if(res != 0){
130       if(DEBUG_ROPE)
131 	ndbout_c("LocalRope::compare(%s, %d, %s) -> %d", str, (int) len,
132 		 (const char*)curr.p->data, res);
133       return res;
134     }
135 
136     curr.i = curr.p->nextPool;
137     left -= 4 * getSegmentSize();
138     str += 4 * getSegmentSize();
139   }
140 
141   if(left > 0){
142     thePool.getPtr(curr);
143     int res = memcmp(str, (const char*)curr.p->data, left);
144     if(res){
145       if(DEBUG_ROPE)
146 	ndbout_c("LocalRope::compare(%s, %d) -> %d", str, (int) len, res);
147       return res;
148     }
149   }
150   if(DEBUG_ROPE)
151     ndbout_c("LocalRope::compare(%s, %d) -> %d", str, (int) len, head.used > len);
152   return head.used > len;
153 }
154 
155 bool
assign(const char * s,Uint32 len,Uint32 hash)156 LocalRope::assign(const char * s, Uint32 len, Uint32 hash){
157   if(DEBUG_ROPE)
158     ndbout_c("LocalRope::assign(%s, %d, 0x%x)", s, (int) len, hash);
159   m_hash = hash;
160   head.used = (head.used + 3) / 4;
161   release();
162   if(append((const Uint32*)s, len >> 2)){
163     if(len & 3){
164       Uint32 buf = 0;
165       const char * src = (const char*)(((Uint32*)s)+(len >> 2));
166       char* dst = (char*)&buf;
167       Uint32 left = len & 3;
168       while(left){
169 	* dst ++ = * src++;
170 	left--;
171       }
172       if(!append(&buf, 1))
173 	return false;
174     }
175     head.used = len;
176     if(DEBUG_ROPE)
177       ndbout_c("LocalRope::assign(...) head = [ %d 0x%x 0x%x ]",
178 	       head.used, head.firstItem, head.lastItem);
179     return true;
180   }
181   return false;
182 }
183 
184 void
erase()185 LocalRope::erase(){
186   head.used = (head.used + 3) / 4;
187   release();
188 }
189 
190 Uint32
hash(const char * p,Uint32 len)191 LocalRope::hash(const char * p, Uint32 len){
192   if(DEBUG_ROPE)
193     ndbout_c("LocalRope::hash(%s, %d)", p, len);
194   Uint32 h = 0;
195   for (; len > 0; len--)
196     h = (h << 5) + h + (* p++);
197   if(DEBUG_ROPE)
198     ndbout_c("LocalRope::hash(...) -> 0x%x", h);
199   return h;
200 }
201 
202 bool
equal(const ConstRope & r2) const203 ConstRope::equal(const ConstRope& r2) const
204 {
205   if (head.used != r2.head.used)
206     return false;
207 
208   if (src.m_hash != r2.src.m_hash)
209     return false;
210 
211   Uint32 left = head.used;
212   Ptr<Segment> s1, s2;
213   s1.i = head.firstItem;
214   s2.i = r2.head.firstItem;
215   while(left > 4 * getSegmentSize())
216   {
217     thePool.getPtr(s1);
218     thePool.getPtr(s2);
219     int res = memcmp(s1.p->data, s2.p->data, 4 * getSegmentSize());
220     if(res != 0)
221     {
222       return false;
223     }
224     s1.i = s1.p->nextPool;
225     s2.i = s2.p->nextPool;
226     left -= 4 * getSegmentSize();
227   }
228 
229   if(left > 0)
230   {
231     thePool.getPtr(s1);
232     thePool.getPtr(s2);
233     int res = memcmp(s1.p->data, s2.p->data, left);
234     if (res != 0)
235     {
236       return false;
237     }
238   }
239   return true;
240 }
241