StringField.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /* ---------------------------------------------------------------------------
  2. Nullsoft Database Engine
  3. --------------------
  4. codename: Near Death Experience
  5. --------------------------------------------------------------------------- */
  6. /* ---------------------------------------------------------------------------
  7. StringField Class
  8. Mac OS X (CFStringRef) implementation
  9. --------------------------------------------------------------------------- */
  10. #include "../nde.h"
  11. #include "StringField.h"
  12. //---------------------------------------------------------------------------
  13. StringField::StringField(CFStringRef Str)
  14. {
  15. InitField();
  16. Type = FIELD_STRING;
  17. if (Str)
  18. {
  19. SetNDEString(Str);
  20. }
  21. }
  22. //---------------------------------------------------------------------------
  23. void StringField::InitField(void)
  24. {
  25. Type = FIELD_STRING;
  26. String=0;
  27. }
  28. //---------------------------------------------------------------------------
  29. StringField::StringField()
  30. {
  31. InitField();
  32. }
  33. //---------------------------------------------------------------------------
  34. StringField::~StringField()
  35. {
  36. if (String)
  37. CFRelease(String);
  38. }
  39. //---------------------------------------------------------------------------
  40. void StringField::ReadTypedData(const uint8_t *data, size_t len)
  41. {
  42. unsigned short c;
  43. CHECK_SHORT(len);
  44. c = (unsigned short)(data[0]|(data[1]<<8));
  45. data+=2;
  46. if (c)
  47. {
  48. bool unicode=false;
  49. if (c >= 2 // enough room for BOM
  50. && (c % 2) == 0) // can't be unicode if it's not an even multiple of 2
  51. {
  52. wchar_t BOM=0;
  53. memcpy(&BOM, data, 2);
  54. if (BOM == 0xFEFF || BOM == 0xFFFE)
  55. {
  56. unicode=true;
  57. }
  58. }
  59. CHECK_BIN(len, c);
  60. if (unicode)
  61. {
  62. if (String)
  63. CFRelease(String);
  64. String = CFStringCreateWithBytes(kCFAllocatorDefault, data, c, kCFStringEncodingUTF16, true);
  65. }
  66. else
  67. {
  68. if (String)
  69. CFRelease(String);
  70. String = CFStringCreateWithBytes(kCFAllocatorDefault, data, c, kCFStringEncodingWindowsLatin1, false);
  71. }
  72. }
  73. }
  74. //---------------------------------------------------------------------------
  75. void StringField::WriteTypedData(uint8_t *data, size_t len)
  76. {
  77. int pos=0;
  78. CHECK_SHORT(len);
  79. if (String)
  80. {
  81. CFIndex lengthRequired=0;
  82. CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, NULL, 0, &lengthRequired);
  83. CHECK_BIN(len, lengthRequired+2);
  84. PUT_SHORT(lengthRequired); pos+=2;
  85. CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, data+pos, lengthRequired, 0);
  86. }
  87. else
  88. {
  89. PUT_SHORT(0);
  90. }
  91. }
  92. CFStringRef StringField::GetString()
  93. {
  94. return String;
  95. }
  96. void StringField::SetNDEString(CFStringRef Str)
  97. {
  98. if (!Str)
  99. return;
  100. CFStringRef old = String;
  101. String = (CFStringRef)CFRetain(Str);
  102. CFRelease(old);
  103. }
  104. //---------------------------------------------------------------------------
  105. size_t StringField::GetDataSize(void)
  106. {
  107. if (String)
  108. {
  109. CFIndex lengthRequired=0;
  110. CFStringGetBytes(String, CFRangeMake(0, CFStringGetLength(String)), kCFStringEncodingUTF16, 0, true, NULL, 0, &lengthRequired);
  111. return lengthRequired+2;
  112. }
  113. else
  114. return 2;
  115. }
  116. //---------------------------------------------------------------------------
  117. int StringField::Compare(Field *Entry)
  118. {
  119. if (!Entry) return -1;
  120. if (Entry->GetType() != GetType()) return 0;
  121. CFStringRef compareString = ((StringField*)Entry)->GetString();
  122. if (!String && !compareString) return 0;
  123. if (!String && compareString) return 1;
  124. if (!compareString) return -1;
  125. return CFStringCompare(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive);
  126. }
  127. //---------------------------------------------------------------------------
  128. int StringField::Starts(Field *Entry)
  129. {
  130. if (!Entry) return -1;
  131. if (Entry->GetType() != GetType()) return 0;
  132. CFStringRef compareString = ((StringField*)Entry)->GetString();
  133. if (!String || !compareString) return 0;
  134. CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareAnchored|kCFCompareDiacriticInsensitive);
  135. if (findRange.location == kCFNotFound)
  136. return 0;
  137. return findRange.location == 0;
  138. }
  139. //---------------------------------------------------------------------------
  140. int StringField::Contains(Field *Entry)
  141. {
  142. if (!Entry) return -1;
  143. if (Entry->GetType() != GetType()) return 0;
  144. CFStringRef compareString = ((StringField*)Entry)->GetString();
  145. if (!String || !compareString) return 0;
  146. CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareDiacriticInsensitive);
  147. return findRange.location != kCFNotFound;
  148. }
  149. Field *StringField::Clone(Table *pTable)
  150. {
  151. StringField *clone = new StringField(String);
  152. clone->Pos = FIELD_CLONE;
  153. clone->ID = ID;
  154. clone->MaxSizeOnDisk = GetDataSize();
  155. return clone;
  156. }
  157. //---------------------------------------------------------------------------
  158. bool StringField::ApplyFilter(Field *Data, int op)
  159. {
  160. if (op == FILTER_ISEMPTY || op == FILTER_ISNOTEMPTY)
  161. {
  162. bool r = (op == FILTER_ISEMPTY);
  163. if (!String)
  164. return r;
  165. if (CFStringGetLength(String) == 0)
  166. return r;
  167. return !r;
  168. }
  169. //
  170. bool r;
  171. StringField *compField = (StringField *)Data;
  172. switch (op)
  173. {
  174. case FILTER_EQUALS:
  175. r = !Compare(Data);
  176. break;
  177. case FILTER_NOTEQUALS:
  178. r = !!Compare(Data);
  179. break;
  180. case FILTER_CONTAINS:
  181. r = !!Contains(Data);
  182. break;
  183. case FILTER_NOTCONTAINS:
  184. r = !Contains(Data);
  185. break;
  186. case FILTER_ABOVE:
  187. r = (bool)(Compare(Data) > 0);
  188. break;
  189. case FILTER_ABOVEOREQUAL:
  190. r = (bool)(Compare(compField) >= 0);
  191. break;
  192. case FILTER_BELOW:
  193. r = (bool)(Compare(compField) < 0);
  194. break;
  195. case FILTER_BELOWOREQUAL:
  196. r = (bool)(Compare(compField) <= 0);
  197. break;
  198. case FILTER_BEGINS:
  199. r = !!Starts(compField);
  200. break;
  201. case FILTER_ENDS:
  202. {
  203. CFStringRef compareString = ((StringField*)Data)->GetString();
  204. if (!String || !compareString) return 0;
  205. CFRange findRange = CFStringFind(String, compareString, kCFCompareCaseInsensitive|kCFCompareNonliteral|kCFCompareAnchored|kCFCompareBackwards);
  206. if (findRange.location == kCFNotFound)
  207. r=0;
  208. else
  209. r = findRange.location != 0;
  210. }
  211. break;
  212. case FILTER_LIKE:
  213. /* TODO
  214. if (compField->optimized_the)
  215. p = compField->optimized_the;
  216. else
  217. {
  218. SKIP_THE_AND_WHITESPACEW(p);
  219. compField->optimized_the = p;
  220. }
  221. if (optimized_the)
  222. d = optimized_the;
  223. else
  224. {
  225. SKIP_THE_AND_WHITESPACEW(d);
  226. optimized_the=d;
  227. }
  228. r = (bool)(nde_wcsicmp(d, p) == 0);
  229. */
  230. r = !!Compare(compField);
  231. break;
  232. case FILTER_BEGINSLIKE:
  233. /*
  234. if (compField->optimized_the)
  235. p = compField->optimized_the;
  236. else
  237. {
  238. SKIP_THE_AND_WHITESPACEW(p);
  239. compField->optimized_the = p;
  240. }
  241. if (optimized_the)
  242. d = optimized_the;
  243. else
  244. {
  245. SKIP_THE_AND_WHITESPACEW(d);
  246. optimized_the=d;
  247. }
  248. r = (bool)(nde_wcsnicmp(d, p, wcslen(p)) == 0);
  249. */
  250. r = !!Starts(compField);
  251. break;
  252. default:
  253. r = true;
  254. break;
  255. }
  256. return r;
  257. }