Opera 12.15 Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Cursor.cpp 8.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /* -*- Mode: c++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*-
  2. **
  3. ** Copyright (C) 1995-2011 Opera Software ASA. All rights reserved.
  4. **
  5. ** This file is part of the Opera web browser.
  6. ** It may not be distributed under any circumstances.
  7. */
  8. #include "core/pch.h"
  9. #ifdef SEARCH_ENGINE // to remove compilation errors with ADVANCED_OPVECTOR
  10. #include "modules/search_engine/Cursor.h"
  11. // how many bytes to preallocate for variable fields
  12. #define ALLOC_VARIABLE_FIELD 32
  13. BSCursor::BSCursor(BOOL autocreate_transaction) : null_field()
  14. {
  15. buf = NULL;
  16. bufsize = 0;
  17. datasize = 0;
  18. this->autocreate_transaction = autocreate_transaction;
  19. filepos = INVALID_FILE_LENGTH;
  20. table = NULL;
  21. fields = NULL;
  22. current_field = NULL;
  23. current_pos = NULL;
  24. modified = FALSE;
  25. }
  26. BSCursor::BSCursor(BlockStorage *table, BOOL autocreate_transaction) : null_field()
  27. {
  28. buf = NULL;
  29. bufsize = 0;
  30. datasize = 0;
  31. this->autocreate_transaction = autocreate_transaction;
  32. filepos = INVALID_FILE_LENGTH;
  33. this->table = table;
  34. fields = NULL;
  35. current_field = NULL;
  36. current_pos = NULL;
  37. modified = FALSE;
  38. }
  39. BSCursor::~BSCursor(void)
  40. {
  41. while (fields != NULL)
  42. {
  43. current_field = (ConstField *)fields->next;
  44. OP_DELETE(fields);
  45. fields = current_field;
  46. }
  47. if (buf != NULL)
  48. OP_DELETEA(buf);
  49. }
  50. void BSCursor::SetStorage(BlockStorage *table)
  51. {
  52. if (this->table != NULL)
  53. {
  54. if (buf != NULL)
  55. {
  56. OP_DELETEA(buf);
  57. buf = NULL;
  58. }
  59. bufsize = 0;
  60. datasize = 0;
  61. filepos = INVALID_FILE_LENGTH;
  62. }
  63. this->table = table;
  64. }
  65. OP_STATUS BSCursor::AddField(const char *name, int size)
  66. {
  67. Field *f;
  68. RETURN_OOM_IF_NULL(f = OP_NEW(Field, (size, name, this)));
  69. if (fields == NULL)
  70. {
  71. fields = f;
  72. current_field = f;
  73. return OpStatus::OK;
  74. }
  75. if (current_field != NULL && current_field->next == NULL && op_strlen(name) < MAX_FIELD_NAME)
  76. {
  77. current_field->next = f;
  78. current_field = f;
  79. return OpStatus::OK;
  80. }
  81. current_field = fields;
  82. while (current_field->next != NULL)
  83. {
  84. if (op_strncmp(current_field->name, name, MAX_FIELD_NAME - 1) == 0)
  85. {
  86. OP_DELETE(f);
  87. return OpStatus::ERR;
  88. }
  89. current_field = (ConstField *)current_field->next;
  90. }
  91. current_field->next = f;
  92. current_field = f;
  93. return OpStatus::OK;
  94. }
  95. OP_STATUS BSCursor::Reserve(int size)
  96. {
  97. unsigned char *res_buf;
  98. if (bufsize >= size)
  99. return OpStatus::OK;
  100. RETURN_OOM_IF_NULL(res_buf = OP_NEWA(unsigned char, size));
  101. if (buf != NULL)
  102. {
  103. op_memcpy(res_buf, buf, datasize);
  104. OP_DELETEA(buf);
  105. }
  106. buf = res_buf;
  107. bufsize = size;
  108. current_field = NULL;
  109. current_pos = NULL;
  110. return OpStatus::OK;
  111. }
  112. OP_STATUS BSCursor::Create(void)
  113. {
  114. int row_size;
  115. if (Modified())
  116. {
  117. RETURN_IF_ERROR(Flush());
  118. }
  119. if (fields == NULL)
  120. return OpStatus::ERR;
  121. if (autocreate_transaction && !table->InTransaction())
  122. RETURN_IF_ERROR(table->BeginTransaction());
  123. row_size = 0;
  124. datasize = 0;
  125. for (current_field = fields; current_field != NULL; current_field = (ConstField *)current_field->next)
  126. {
  127. if (current_field->variable_length)
  128. {
  129. row_size += ALLOC_VARIABLE_FIELD + 4;
  130. datasize += 4;
  131. current_field->size = 0;
  132. }
  133. else {
  134. row_size += current_field->size;
  135. datasize += current_field->size;
  136. }
  137. }
  138. RETURN_IF_ERROR(Reserve(row_size));
  139. current_field = fields;
  140. current_pos = buf;
  141. op_memset(buf, 0, datasize);
  142. filepos = 0;
  143. return OpStatus::OK;
  144. }
  145. OP_STATUS BSCursor::Goto(RowID id)
  146. {
  147. int size;
  148. if (table == NULL || id == 0)
  149. return OpStatus::ERR;
  150. if (Modified())
  151. {
  152. RETURN_IF_ERROR(Flush());
  153. }
  154. size = table->DataLength(((OpFileLength)id) * table->GetBlockSize());
  155. if (size > bufsize)
  156. {
  157. RETURN_IF_ERROR(Reserve(size));
  158. }
  159. filepos = ((OpFileLength)id) * table->GetBlockSize();
  160. if (!table->Read(buf, size, filepos))
  161. return OpStatus::ERR_NO_ACCESS;
  162. current_pos = buf;
  163. for (current_field = fields; current_field != NULL; current_field = (ConstField *)current_field->next)
  164. {
  165. if (current_field->variable_length)
  166. {
  167. #ifdef NEEDS_RISC_ALIGNMENT
  168. op_memcpy(&current_field->size, current_pos, 4);
  169. #else
  170. current_field->size = *(int *)current_pos;
  171. #endif
  172. if (current_field->size < 0)
  173. return OpStatus::ERR_PARSING_FAILED;
  174. current_pos += current_field->size + 4;
  175. }
  176. else
  177. current_pos += current_field->size;
  178. if (current_pos > buf + size || current_pos < buf)
  179. return OpStatus::ERR_PARSING_FAILED;
  180. }
  181. if (current_pos < buf + size)
  182. return OpStatus::ERR_PARSING_FAILED;
  183. current_pos = NULL;
  184. datasize = size;
  185. return OpStatus::OK;
  186. }
  187. OP_STATUS BSCursor::Delete(void)
  188. {
  189. if (table == NULL || filepos == INVALID_FILE_LENGTH)
  190. return OpStatus::ERR_OUT_OF_RANGE;
  191. if (filepos != 0)
  192. {
  193. if (!table->Delete(filepos))
  194. return OpStatus::ERR;
  195. }
  196. modified = FALSE;
  197. filepos = INVALID_FILE_LENGTH;
  198. return OpStatus::OK;
  199. }
  200. OP_STATUS BSCursor::Flush(void)
  201. {
  202. if (!Modified())
  203. return OpStatus::OK;
  204. if (table == NULL || filepos == INVALID_FILE_LENGTH)
  205. return OpStatus::ERR;
  206. if (filepos == 0)
  207. {
  208. OpFileLength pos;
  209. if ((pos = table->Write(buf, datasize)) == 0)
  210. return OpStatus::ERR_NO_DISK;
  211. filepos = pos;
  212. }
  213. else {
  214. if (!table->Update(buf, datasize, filepos))
  215. return OpStatus::ERR_NO_DISK;
  216. }
  217. modified = FALSE;
  218. return OpStatus::OK;
  219. }
  220. const ConstField &BSCursor::GetField(const char *name) const
  221. {
  222. ConstField *tmpf;
  223. if (buf == NULL)
  224. return *(ConstField *)(&null_field);
  225. tmpf = fields;
  226. while (tmpf != NULL && op_strncmp(tmpf->name, name, MAX_FIELD_NAME - 1) != 0)
  227. tmpf = (ConstField *)tmpf->next;
  228. if (tmpf != NULL)
  229. return *tmpf;
  230. return *(ConstField *)(&null_field);
  231. }
  232. const ConstField &BSCursor::GetField(int pos) const
  233. {
  234. ConstField *tmpf;
  235. if (buf == NULL)
  236. return *(ConstField *)(&null_field);
  237. tmpf = fields;
  238. while (tmpf != NULL && pos-- > 0)
  239. tmpf = (ConstField *)tmpf->next;
  240. if (tmpf != NULL)
  241. return *tmpf;
  242. return *(ConstField *)(&null_field);
  243. }
  244. Field &BSCursor::GetField(const char *name)
  245. {
  246. if (buf == NULL)
  247. return *(Field *)(&null_field);
  248. current_field = fields;
  249. current_pos = buf;
  250. while (current_field != NULL && op_strncmp(current_field->name, name, MAX_FIELD_NAME - 1) != 0)
  251. {
  252. current_pos += current_field->size + (current_field->variable_length ? 4 : 0);
  253. current_field = (ConstField *)current_field->next;
  254. }
  255. if (current_field != NULL)
  256. return *(Field *)current_field;
  257. current_pos = NULL;
  258. return *(Field *)(&null_field);
  259. }
  260. Field &BSCursor::GetField(int pos)
  261. {
  262. if (buf == NULL)
  263. return *(Field *)(&null_field);
  264. current_field = fields;
  265. current_pos = buf;
  266. while (current_field != NULL && pos-- > 0)
  267. {
  268. current_pos += current_field->size + (current_field->variable_length ? 4 : 0);
  269. current_field = (ConstField *)current_field->next;
  270. }
  271. if (current_field != NULL)
  272. return *(Field *)current_field;
  273. current_pos = NULL;
  274. return *(Field *)(&null_field);
  275. }
  276. OP_STATUS BSCursor::ModifyField(Field *field, const unsigned char *value, int new_size)
  277. {
  278. int variable_off;
  279. variable_off = field->variable_length ? 4 : 0;
  280. if (autocreate_transaction && field->variable_length && new_size != field->size && !table->InTransaction())
  281. RETURN_IF_ERROR(table->BeginTransaction());
  282. if (new_size > field->size)
  283. {
  284. if (datasize + new_size - field->size > bufsize)
  285. {
  286. RETURN_IF_ERROR(Reserve(datasize + new_size - field->size + ALLOC_VARIABLE_FIELD));
  287. }
  288. current_pos = GetPos(field);
  289. current_field = field;
  290. if (datasize > current_pos - buf + field->size + variable_off)
  291. op_memmove(current_pos + new_size + variable_off, current_pos + field->size + variable_off,
  292. datasize - (current_pos - buf) - field->size - variable_off);
  293. datasize += new_size - field->size;
  294. }
  295. else if (new_size < field->size)
  296. {
  297. current_pos = GetPos(field);
  298. current_field = field;
  299. if (datasize > current_pos - buf + field->size + variable_off)
  300. op_memmove(current_pos + new_size + variable_off, current_pos + field->size + variable_off,
  301. datasize - (current_pos - buf) - field->size - variable_off);
  302. datasize -= field->size - new_size;
  303. }
  304. else {
  305. current_pos = GetPos(field);
  306. current_field = field;
  307. }
  308. if (field->variable_length)
  309. {
  310. #ifdef NEEDS_RISC_ALIGNMENT
  311. op_memcpy(current_pos, &new_size, 4);
  312. #else
  313. *(int *)current_pos = new_size;
  314. #endif
  315. op_memcpy(current_pos + 4, value, new_size);
  316. }
  317. else
  318. op_memcpy(current_pos, value, new_size);
  319. field->size = new_size;
  320. modified = TRUE;
  321. #ifdef _DEBUG
  322. Field *tmpfield = (Field *)fields;
  323. int size = 0;
  324. while (tmpfield != NULL)
  325. {
  326. size += tmpfield->size + (tmpfield->variable_length ? 4 : 0);
  327. tmpfield = (Field *)tmpfield->next;
  328. }
  329. OP_ASSERT(datasize == size);
  330. #endif
  331. return OpStatus::OK;
  332. }
  333. unsigned char *BSCursor::GetPos(const ConstField *field) const
  334. {
  335. ConstField *tmpf;
  336. unsigned char *field_pos;
  337. OP_ASSERT(buf != NULL);
  338. if (field == current_field && current_pos != NULL)
  339. return current_pos;
  340. tmpf = fields;
  341. field_pos = buf;
  342. while (tmpf != field && tmpf != NULL)
  343. {
  344. field_pos += tmpf->size + (tmpf->variable_length ? 4 : 0);
  345. tmpf = (ConstField *)tmpf->next;
  346. }
  347. OP_ASSERT(tmpf != NULL);
  348. OP_ASSERT(field_pos <= buf + bufsize);
  349. return field_pos;
  350. }
  351. #endif // SEARCH_ENGINE