Leaked source code of windows server 2003
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.

859 lines
25 KiB

  1. //
  2. // RANGE.CPP
  3. //
  4. // 2-20-96: (EricAn)
  5. // Hacked from the Route66 source tree, eliminated stuff we don't use.
  6. // Original copyright below - where did this thing come from?
  7. //
  8. // -*- C -*-
  9. //
  10. // Copyright 1992 Software Innovations, Inc.
  11. //
  12. // $Source: D:\CLASS\SOURCE\range.c-v $
  13. // $Author: martin $
  14. // $Date: 92/07/15 05:09:24 $
  15. // $Revision: 1.1 $
  16. //
  17. //
  18. #include "pch.hxx"
  19. #include "range.h"
  20. #include "rangetst.h"
  21. // QUANTUM defines the number of m_rangeTable cells to be allocated at
  22. // one time. Whenever the m_rangeTable becomes full, it is expanded
  23. // by QUANTUM range cells. m_rangeTable's never shrink.
  24. const int QUANTUM = 64;
  25. inline int inRange(RangeType r, ULONG x) { return ((x>=r.low) && (x<=r.high)); };
  26. CRangeList::CRangeList()
  27. {
  28. m_cRef = 1;
  29. m_numRanges = 0;
  30. m_rangeTableSize = 0;
  31. m_rangeTable = NULL;
  32. }
  33. #if 0
  34. /*
  35. CRangeList::CRangeList(CRangeList& r)
  36. {
  37. m_numRanges = r.m_numRanges;
  38. m_rangeTableSize = r.m_rangeTableSize;
  39. m_rangeTable = new RangeType[m_rangeTableSize];
  40. CopyMemory(m_rangeTable, r.m_rangeTable, m_numRanges * sizeof(RangeType));
  41. }
  42. */
  43. #endif
  44. CRangeList::~CRangeList()
  45. {
  46. if (m_rangeTable)
  47. MemFree(m_rangeTable);
  48. }
  49. ULONG CRangeList::AddRef(void)
  50. {
  51. return (ULONG)InterlockedIncrement((LPLONG)&m_cRef);
  52. }
  53. ULONG CRangeList::Release(void)
  54. {
  55. ULONG cRefT = (ULONG)InterlockedDecrement((LPLONG)&m_cRef);
  56. if (cRefT == 0)
  57. delete this;
  58. return (cRefT);
  59. }
  60. BOOL CRangeList::IsInRange(const ULONG value) const
  61. {
  62. for (int i=0; i<m_numRanges; i++)
  63. if (inRange(m_rangeTable[i], value))
  64. return TRUE;
  65. return FALSE;
  66. }
  67. ULONG CRangeList::MinOfRange(const ULONG value) const
  68. {
  69. if (RANGE_ERROR == value)
  70. return RANGE_ERROR;
  71. for (register int i=0; i<m_numRanges; i++)
  72. if (inRange(m_rangeTable[i], value))
  73. return m_rangeTable[i].low;
  74. return RANGE_ERROR;
  75. }
  76. ULONG CRangeList::MaxOfRange(const ULONG value) const
  77. {
  78. if (RANGE_ERROR == value)
  79. return RANGE_ERROR;
  80. for (register int i=0; i<m_numRanges; i++)
  81. if (inRange(m_rangeTable[i], value))
  82. return m_rangeTable[i].high;
  83. return RANGE_ERROR;
  84. }
  85. ULONG CRangeList::Max() const
  86. {
  87. if (m_numRanges==0)
  88. return RANGE_ERROR;
  89. return m_rangeTable[m_numRanges-1].high;
  90. }
  91. ULONG CRangeList::Min() const
  92. {
  93. if (m_numRanges==0)
  94. return RANGE_ERROR;
  95. return m_rangeTable[0].low;
  96. }
  97. BOOL CRangeList::Save(LPBYTE *const ppb, ULONG *const pcb) const
  98. {
  99. Assert(ppb);
  100. Assert(pcb);
  101. *pcb = m_numRanges * sizeof(RangeType);
  102. if (*pcb)
  103. {
  104. if (!MemAlloc((LPVOID*)ppb, *pcb))
  105. return FALSE;
  106. CopyMemory(*ppb, m_rangeTable, *pcb);
  107. }
  108. else
  109. *ppb = NULL;
  110. return TRUE;
  111. }
  112. BOOL CRangeList::Load(const LPBYTE pb, const ULONG cb)
  113. {
  114. RangeType *pRangeTable;
  115. Assert(pb != NULL);
  116. Assert(cb > 0);
  117. if (!MemAlloc((void **)&pRangeTable, cb))
  118. return(FALSE);
  119. m_numRanges = m_rangeTableSize = cb / sizeof(RangeType);
  120. if (m_rangeTable)
  121. MemFree(m_rangeTable);
  122. CopyMemory(pRangeTable, pb, cb);
  123. m_rangeTable = pRangeTable;
  124. return TRUE;
  125. }
  126. BOOL CRangeList::NextLowerAntiRange(const ULONG value, RangeType *const rt) const
  127. {
  128. if (RANGE_ERROR == value || m_numRanges < 2 || !rt)
  129. return FALSE;
  130. for (register int i=0; i<m_numRanges; i++)
  131. if (inRange(m_rangeTable[i], value))
  132. {
  133. if (0 == i)
  134. return FALSE;
  135. rt->high = m_rangeTable[i].low-1;
  136. rt->low = m_rangeTable[i-1].high+1;
  137. return TRUE;
  138. }
  139. return FALSE;
  140. }
  141. BOOL CRangeList::NextHigherAntiRange(const ULONG value, RangeType *const rt) const
  142. {
  143. if (RANGE_ERROR == value || m_numRanges < 2 || !rt)
  144. return FALSE;
  145. for (register int i=0; i<m_numRanges; i++)
  146. if (inRange(m_rangeTable[i], value))
  147. {
  148. if (m_numRanges-1 == i)
  149. return FALSE;
  150. rt->low = m_rangeTable[i].high+1;
  151. rt->high = m_rangeTable[i+1].low-1;
  152. return TRUE;
  153. }
  154. return FALSE;
  155. }
  156. BOOL CRangeList::HighestAntiRange(RangeType *const rt) const
  157. {
  158. if (m_numRanges < 2 || !rt)
  159. return FALSE;
  160. rt->high = m_rangeTable[m_numRanges-1].low-1;
  161. rt->low = m_rangeTable[m_numRanges-2].high+1;
  162. return TRUE;
  163. }
  164. BOOL CRangeList::LowestAntiRange(RangeType *const rt) const
  165. {
  166. if (m_numRanges < 2 || !rt)
  167. return FALSE;
  168. rt->high = m_rangeTable[1].low-1;
  169. rt->low = m_rangeTable[0].high+1;
  170. return TRUE;
  171. }
  172. BOOL CRangeList::AddRange(const ULONG value)
  173. {
  174. RangeType r = { value, value };
  175. return AddRange(r);
  176. }
  177. BOOL CRangeList::AddRange(const ULONG low, const ULONG high)
  178. {
  179. RangeType r = { low, high };
  180. return AddRange(r);
  181. }
  182. BOOL CRangeList::AddRange(CRangeList& r)
  183. {
  184. for (int i=0 ; i<r.m_numRanges ; ++i)
  185. if (!AddRange(r.m_rangeTable[i]))
  186. return FALSE;
  187. return TRUE;
  188. }
  189. BOOL CRangeList::AddRange(RangeType *rt, int count)
  190. {
  191. for (int i=0 ; i<count ; ++i)
  192. if (!AddRange(rt[i]))
  193. return FALSE;
  194. return TRUE;
  195. }
  196. BOOL CRangeList::AddRange(const RangeType range)
  197. {
  198. int possibleLoc;
  199. int insertPosition;
  200. if (range.low > range.high)
  201. {
  202. DOUTL(2, "Empty range passed to AddRange()");
  203. return FALSE;
  204. }
  205. if (m_numRanges==0)
  206. {
  207. if (m_rangeTableSize == 0)
  208. if (!Expand())
  209. return FALSE;
  210. m_numRanges = 1;
  211. CopyMemory(&m_rangeTable[0], &range, sizeof(RangeType));
  212. }
  213. else
  214. {
  215. possibleLoc = BinarySearch(range.low);
  216. if (!((possibleLoc > -1) &&
  217. (inRange(m_rangeTable[possibleLoc], range.low)) &&
  218. (inRange(m_rangeTable[possibleLoc], range.high))))
  219. {
  220. insertPosition = possibleLoc + 1;
  221. if (m_numRanges == m_rangeTableSize)
  222. if (!Expand())
  223. return FALSE;
  224. ShiftRight(insertPosition, 1);
  225. CopyMemory(&m_rangeTable[insertPosition], &range, sizeof(RangeType));
  226. if (insertPosition > 0)
  227. SubsumeDown(insertPosition);
  228. if (insertPosition < m_numRanges)
  229. SubsumeUpwards(insertPosition);
  230. }
  231. }
  232. return TRUE;
  233. }
  234. BOOL CRangeList::DeleteRange(const ULONG value)
  235. {
  236. RangeType r = { value, value };
  237. return DeleteRange(r);
  238. }
  239. BOOL CRangeList::DeleteRange(const ULONG low, const ULONG high)
  240. {
  241. RangeType r = { low, high };
  242. return DeleteRange(r);
  243. }
  244. BOOL CRangeList::DeleteRange(CRangeList& r)
  245. {
  246. for (int i=0 ; i<r.m_numRanges ; ++i)
  247. if (!DeleteRange(r.m_rangeTable[i]))
  248. return FALSE;
  249. return TRUE;
  250. }
  251. BOOL CRangeList::DeleteRange(const RangeType range)
  252. {
  253. int lowEndChange;
  254. int highEndChange;
  255. if (range.low > range.high)
  256. {
  257. DOUTL(2, "Empty range passed to DeleteRange()");
  258. return FALSE;
  259. }
  260. lowEndChange = BinarySearch(range.low);
  261. highEndChange = BinarySearch(range.high);
  262. if ((lowEndChange != -1) && (highEndChange == lowEndChange))
  263. {
  264. if (inRange(m_rangeTable[lowEndChange], range.low))
  265. {
  266. if (inRange(m_rangeTable[lowEndChange], range.high))
  267. {
  268. if ((m_rangeTable[lowEndChange].low == range.low) &&
  269. (m_rangeTable[lowEndChange].high == range.high))
  270. {
  271. if (lowEndChange == (m_numRanges-1))
  272. {
  273. m_numRanges--;
  274. }
  275. else
  276. {
  277. ShiftLeft(lowEndChange + 1, 1);
  278. }
  279. }
  280. else
  281. {
  282. if (m_rangeTable[lowEndChange].low == range.low)
  283. {
  284. m_rangeTable[lowEndChange].low = range.high + 1;
  285. }
  286. else
  287. {
  288. if (m_rangeTable[lowEndChange].high == range.high)
  289. {
  290. Assert(range.low > 0);
  291. m_rangeTable[lowEndChange].high = range.low - 1;
  292. }
  293. else
  294. {
  295. // the range to be deleted is properly contained in
  296. // m_rangeTable[lowEndChange]
  297. if (m_numRanges == m_rangeTableSize)
  298. if (!Expand())
  299. return FALSE;
  300. ShiftRight(lowEndChange + 1, 1);
  301. m_rangeTable[lowEndChange + 1].low = range.high + 1;
  302. m_rangeTable[lowEndChange + 1].high = m_rangeTable[lowEndChange].high;
  303. Assert(range.low > 0);
  304. m_rangeTable[lowEndChange].high = range.low - 1;
  305. }
  306. }
  307. }
  308. }
  309. else
  310. {
  311. // range.low is in m_rangeTable[lowEndChange], but range.high
  312. // is not
  313. if (m_rangeTable[lowEndChange].low == range.low)
  314. {
  315. ShiftLeft(lowEndChange + 1, 1);
  316. }
  317. else
  318. {
  319. Assert(range.low > 0);
  320. m_rangeTable[lowEndChange].high = range.low - 1;
  321. }
  322. }
  323. } // of the cases where range.low actually in m_rangeTable[lowEndChange]
  324. }
  325. else
  326. { // of the cases where highEndChange == lowEndChange
  327. if (lowEndChange != -1)
  328. {
  329. if (inRange(m_rangeTable[lowEndChange], range.low))
  330. {
  331. if (range.low == m_rangeTable[lowEndChange].low)
  332. {
  333. lowEndChange = lowEndChange - 1;
  334. }
  335. else
  336. {
  337. Assert(range.low > 0);
  338. m_rangeTable[lowEndChange].high = range.low - 1;
  339. }
  340. }
  341. }
  342. if (highEndChange != -1)
  343. {
  344. if (inRange(m_rangeTable[highEndChange], range.high))
  345. {
  346. if (range.high == m_rangeTable[highEndChange].high)
  347. {
  348. highEndChange = highEndChange + 1;
  349. }
  350. else
  351. {
  352. m_rangeTable[highEndChange].low = range.high + 1;
  353. }
  354. }
  355. else
  356. {
  357. highEndChange++;
  358. }
  359. }
  360. if (!(lowEndChange > highEndChange))
  361. {
  362. // (0 <= lowEndChange < m_numRanges => m_rangeTable[lowEndChange] has received
  363. // any requisite adjustments and is to be kept)
  364. // and (0 <= highEndChange < m_numRanges => m_rangeTable[highEndChange]
  365. // has received any requistie adjs. and is a keeper)
  366. // and "forall" i [ lowEndChange < i < highEndChange =>
  367. // m_rangeTable[i] is to be overwritten]
  368. if (highEndChange >= m_numRanges)
  369. {
  370. m_numRanges = lowEndChange + 1;
  371. }
  372. else
  373. {
  374. if ((highEndChange - lowEndChange - 1) > 0)
  375. {
  376. ShiftLeft(highEndChange, (highEndChange-lowEndChange-1));
  377. }
  378. }
  379. } // else there's a problem with this code...
  380. }
  381. return TRUE;
  382. }
  383. ULONG CRangeList::Next(const ULONG current) const
  384. {
  385. int loc;
  386. if (m_numRanges == 0)
  387. return RANGE_ERROR;
  388. if ((loc = BinarySearch(current)) == -1)
  389. return m_rangeTable[0].low;
  390. else if (loc == (m_numRanges-1))
  391. {
  392. if (inRange(m_rangeTable[m_numRanges-1], current))
  393. {
  394. if (inRange(m_rangeTable[m_numRanges-1], current + 1))
  395. return current + 1;
  396. else
  397. return RANGE_ERROR;
  398. }
  399. else
  400. return RANGE_ERROR;
  401. }
  402. else // case where loc == m_numRanges-1
  403. {
  404. // 1 <= loc < m_numRanges
  405. if (inRange(m_rangeTable[loc], current))
  406. {
  407. if (inRange(m_rangeTable[loc], current + 1))
  408. return current + 1;
  409. else
  410. return m_rangeTable[loc + 1].low;
  411. }
  412. else
  413. return m_rangeTable[loc + 1].low;
  414. }
  415. }
  416. ULONG CRangeList::Prev(const ULONG current) const
  417. {
  418. int loc;
  419. if (m_numRanges == 0)
  420. return RANGE_ERROR;
  421. if ((loc = BinarySearch(current)) == -1)
  422. {
  423. return RANGE_ERROR;
  424. }
  425. else if (loc == 0)
  426. {
  427. if (inRange(m_rangeTable[0], current))
  428. {
  429. if (current > 0 && inRange(m_rangeTable[0], current - 1))
  430. return current - 1;
  431. else
  432. return RANGE_ERROR;
  433. }
  434. else
  435. return m_rangeTable[0].high;
  436. }
  437. else
  438. {
  439. // 1 < loc <= m_numRanges
  440. if (inRange(m_rangeTable[loc], current))
  441. {
  442. if (current > 0 && inRange(m_rangeTable[loc], current - 1))
  443. return current - 1;
  444. else
  445. return m_rangeTable[loc-1].high;
  446. }
  447. else
  448. return m_rangeTable[loc].high;
  449. }
  450. }
  451. ULONG CRangeList::Cardinality(void) const
  452. {
  453. ULONG card = 0;
  454. for (int i=0 ; i<m_numRanges ; i++)
  455. card += (m_rangeTable[i].high - m_rangeTable[i].low + 1);
  456. return card;
  457. }
  458. int CRangeList::BinarySearch(const ULONG value) const
  459. {
  460. // We are looking for `value' in the m_rangeTable. If value is in the
  461. // set of valid ranges, we return the array subscript of the range
  462. // containing `value'. If `value' is not contained in any of the
  463. // ranges then return `loc' where
  464. // (0 <= loc < m_numRanges =>
  465. // (m_rangeTable[loc].low < rangeNum)
  466. // "and" (m_rangeTable[loc + 1].low > rangeNum))
  467. // "and" (loc = m_numRanges => rangeNum > m_rangeTable[m_numRanges].low)
  468. // "and" (loc = -1 => m_numRanges = 0
  469. // "or" rangeNum < m_rangeTable[0].low) }
  470. long low, high, mid;
  471. int loc=-1;
  472. if (m_numRanges == 0)
  473. return -1;
  474. if (value < m_rangeTable[0].low)
  475. return -1;
  476. low = 0;
  477. high = m_numRanges - 1;
  478. while (low <= high) {
  479. // inv: low < high - 1, and if rngNum is any where in m_rangeTable, it is in
  480. // the range from m_rangeTable[low] to m_rangeTable[high]
  481. mid = (low + high) / 2;
  482. if ((value >= m_rangeTable[mid].low) &&
  483. ((mid == (m_numRanges-1)) || (value < m_rangeTable[mid + 1].low)))
  484. {
  485. loc = mid;
  486. high = low - 1;
  487. }
  488. else
  489. {
  490. if (value > m_rangeTable[mid].low)
  491. low = mid + 1;
  492. else
  493. high = mid - 1;
  494. }
  495. }
  496. return loc;
  497. }
  498. // Expand() will grow the m_rangeTable by QUANTUM range cells.
  499. BOOL CRangeList::Expand()
  500. {
  501. RangeType *newRangeTable;
  502. if (!MemAlloc((LPVOID*)&newRangeTable, (m_rangeTableSize + QUANTUM) * sizeof(RangeType)))
  503. return FALSE;
  504. m_rangeTableSize += QUANTUM;
  505. if (m_rangeTable)
  506. {
  507. if (m_numRanges > 0)
  508. CopyMemory(newRangeTable, m_rangeTable, m_numRanges * sizeof(RangeType));
  509. MemFree(m_rangeTable);
  510. }
  511. m_rangeTable = newRangeTable;
  512. return TRUE;
  513. }
  514. void CRangeList::ShiftLeft(int low, int distance)
  515. {
  516. if (m_numRanges - low)
  517. MoveMemory(&m_rangeTable[low-distance], &m_rangeTable[low], (m_numRanges-low)*sizeof(RangeType));
  518. m_numRanges -= distance;
  519. }
  520. void CRangeList::ShiftRight(int low, int distance)
  521. {
  522. if (m_numRanges - low)
  523. MoveMemory(&m_rangeTable[low+distance], &m_rangeTable[low], (m_numRanges-low)*sizeof(RangeType));
  524. m_numRanges += distance;
  525. }
  526. // pre: (m_rangeTable[anchorPosition] has probably just been added to m_rangeTable.)
  527. // 1 <= anchorPosition <= m_numRanges
  528. // and ( anchorPosition = 1
  529. // or (m_rangeTable[anchorPosition].low >
  530. // m_rangeTable[anchorPosition - 1].high) )
  531. // post: No overlapping or contiguous ranges from 1 to m_numRanges. }
  532. void CRangeList::SubsumeUpwards(const int anchor)
  533. {
  534. int posOfLargerLow;
  535. int copyDownDistance;
  536. int copyPos;
  537. posOfLargerLow = anchor + 1;
  538. while ((posOfLargerLow < m_numRanges) &&
  539. (m_rangeTable[posOfLargerLow].low <= m_rangeTable[anchor].high + 1))
  540. posOfLargerLow++;
  541. if (posOfLargerLow == m_numRanges)
  542. {
  543. if (m_rangeTable[m_numRanges-1].high > m_rangeTable[anchor].high)
  544. m_rangeTable[anchor].high = m_rangeTable[m_numRanges-1].high;
  545. m_numRanges = anchor + 1;
  546. }
  547. else
  548. {
  549. // posOfLargerLow now indexes the first element of m_rangeTable, looking from
  550. // m_rangeTable[anchor], with .low > m_rangeTable[anchor].high + 1
  551. if (posOfLargerLow > (anchor + 1))
  552. {
  553. if (m_rangeTable[posOfLargerLow - 1].high > m_rangeTable[anchor].high)
  554. m_rangeTable[anchor].high = m_rangeTable[posOfLargerLow - 1].high;
  555. copyDownDistance = posOfLargerLow - anchor - 1;
  556. copyPos = posOfLargerLow;
  557. while (copyPos < m_numRanges)
  558. {
  559. m_rangeTable[copyPos - copyDownDistance] = m_rangeTable[copyPos];
  560. copyPos = copyPos + 1;
  561. }
  562. m_numRanges -= copyDownDistance;
  563. }
  564. }
  565. }
  566. void CRangeList::SubsumeDown(int& anchor)
  567. {
  568. int posOfSmallerHigh;
  569. int copyDownDistance;
  570. int copyPos;
  571. posOfSmallerHigh = anchor - 1;
  572. while ((posOfSmallerHigh >= 0) &&
  573. (m_rangeTable[posOfSmallerHigh].high + 1 >= m_rangeTable[anchor].low))
  574. {
  575. posOfSmallerHigh--;
  576. }
  577. if (posOfSmallerHigh < 0)
  578. {
  579. if (m_rangeTable[0].low < m_rangeTable[anchor].low)
  580. m_rangeTable[anchor].low = m_rangeTable[0].low;
  581. }
  582. // posOfSmallerHigh either has value 0 or subscripts the first element of
  583. // m_rangeTable, looking down from anchor, with a .high that is
  584. // less than m_rangeTable[anchor].low - 1.
  585. if (m_rangeTable[posOfSmallerHigh + 1].low < m_rangeTable[anchor].low)
  586. m_rangeTable[anchor].low = m_rangeTable[posOfSmallerHigh + 1].low;
  587. copyDownDistance = anchor - posOfSmallerHigh - 1;
  588. if (copyDownDistance > 0)
  589. {
  590. copyPos = anchor;
  591. while (copyPos < m_numRanges)
  592. {
  593. m_rangeTable[copyPos - copyDownDistance] = m_rangeTable[copyPos];
  594. copyPos++;
  595. }
  596. m_numRanges -= copyDownDistance;
  597. anchor -= copyDownDistance;
  598. }
  599. }
  600. #if 0
  601. /*
  602. * We might need these ones again if we decide to import .newsrc files
  603. *
  604. void CRangeList::AddRange(const char *s)
  605. {
  606. char *token, *q;
  607. char *p = new char[strlen(s)+1];
  608. strcpy(p, s);
  609. if ((token = strtok(p, ","))==NULL)
  610. return;
  611. while (token!=NULL) {
  612. if ((q = strchr(token, '-'))==NULL) { // no dash - single value
  613. AddRange(atol(token));
  614. } else {
  615. long low, high;
  616. low = atol(token);
  617. high = atol(q+1);
  618. if (low<=high)
  619. AddRange(low, high);
  620. }
  621. token = strtok(NULL, ",");
  622. }
  623. }
  624. void CRangeList::DeleteRange(const char *s)
  625. {
  626. char *token, *q;
  627. char *p = new char[strlen(s)+1];
  628. strcpy(p, s);
  629. if ((token = strtok(p, ","))==NULL)
  630. return;
  631. while (token!=NULL) {
  632. if ((q = strchr(token, '-'))==NULL) { // no dash - single value
  633. DeleteRange(atol(token));
  634. } else {
  635. long low, high;
  636. low = atol(token);
  637. high = atol(q+1);
  638. if (low<=high)
  639. DeleteRange(low, high);
  640. }
  641. token = strtok(NULL, ",");
  642. }
  643. }
  644. */
  645. #endif
  646. #ifdef DEBUG
  647. #define WORK_BUFSIZ 256
  648. LPTSTR CRangeList::RangeToString()
  649. {
  650. LPTSTR p, buffer;
  651. TCHAR temp[20];
  652. int buffsize = m_numRanges ? WORK_BUFSIZ : 1;
  653. if (!MemAlloc((LPVOID*)&buffer, buffsize * sizeof(TCHAR)))
  654. return NULL;
  655. *buffer = '\0';
  656. // nothing to do?
  657. if (m_numRanges == 0)
  658. return buffer;
  659. // dump the ranges as a string: "low-high, low-high, singleton, low-high\n"
  660. for (int i=0; i<m_numRanges; i++)
  661. {
  662. if (m_rangeTable[i].low == m_rangeTable[i].high)
  663. wnsprintf(temp, ARRAYSIZE(temp), "%ld", m_rangeTable[i].low);
  664. else
  665. wnsprintf(temp, ARRAYSIZE(temp), "%ld-%ld", m_rangeTable[i].low, m_rangeTable[i].high);
  666. if ((lstrlen(temp) + lstrlen(buffer) + 2) > buffsize)
  667. {
  668. // buffer is about to overflow... double its size
  669. if (!MemAlloc((LPVOID*)&p, 2 * buffsize))
  670. {
  671. MemFree(buffer);
  672. return NULL;
  673. }
  674. buffsize *= 2;
  675. StrCpyN(p, buffer, buffsize);
  676. MemFree(buffer);
  677. buffer = p;
  678. }
  679. StrCatBuff(buffer, temp, buffsize);
  680. if (i < (m_numRanges-1))
  681. StrCatBuff(buffer, ",", buffsize);
  682. }
  683. // save some space, trim the buffer down
  684. buffsize = lstrlen(buffer)+1;
  685. if (MemAlloc((LPVOID*)&p, buffsize * sizeof(TCHAR)))
  686. {
  687. StrCpyN(p, buffer, buffsize);
  688. MemFree(buffer);
  689. buffer = p;
  690. }
  691. return buffer;
  692. }
  693. void CRangeList::DebugOutput(LPTSTR szComment)
  694. {
  695. LPTSTR szRange = RangeToString();
  696. OutputDebugString(szComment);
  697. if (szRange)
  698. {
  699. OutputDebugString(szRange);
  700. MemFree(szRange);
  701. }
  702. OutputDebugString("\r\n");
  703. }
  704. #endif
  705. #ifdef DEBUG
  706. INT_PTR CALLBACK RangeTestDlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
  707. {
  708. CRangeList *pRL = (CRangeList *)GetWindowLongPtr(hwnd, DWLP_USER);
  709. switch(msg)
  710. {
  711. case WM_INITDIALOG:
  712. {
  713. pRL = new CRangeList();
  714. SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)pRL);
  715. break;
  716. }
  717. case WM_COMMAND:
  718. {
  719. int i1 = GetDlgItemInt(hwnd, idcInput1, NULL, FALSE);
  720. int i2 = GetDlgItemInt(hwnd, idcInput2, NULL, FALSE);
  721. BOOL fRet;
  722. LPTSTR szRange;
  723. switch(GET_WM_COMMAND_ID(wp,lp))
  724. {
  725. case IDOK:
  726. case IDCANCEL:
  727. delete pRL;
  728. SetWindowLongPtr(hwnd, DWLP_USER, 0);
  729. EndDialog(hwnd, TRUE);
  730. return TRUE;
  731. case idcAddRange:
  732. fRet = pRL->AddRange(i1, i2);
  733. szRange = pRL->RangeToString();
  734. SetDlgItemText(hwnd, idcPrint, szRange);
  735. if (szRange)
  736. MemFree(szRange);
  737. SetDlgItemInt(hwnd, idcResult, fRet, FALSE);
  738. return TRUE;
  739. case idcDeleteRange:
  740. fRet = pRL->DeleteRange(i1, i2);
  741. szRange = pRL->RangeToString();
  742. SetDlgItemText(hwnd, idcPrint, szRange);
  743. if (szRange)
  744. MemFree(szRange);
  745. SetDlgItemInt(hwnd, idcResult, fRet, FALSE);
  746. return TRUE;
  747. case idcIsInRange:
  748. SetDlgItemInt(hwnd, idcResult, pRL->IsInRange(i1), FALSE);
  749. return TRUE;
  750. case idcNextInRange:
  751. SetDlgItemInt(hwnd, idcResult, pRL->Next(i1), TRUE);
  752. return TRUE;
  753. case idcPrevInRange:
  754. SetDlgItemInt(hwnd, idcResult, pRL->Prev(i1), TRUE);
  755. return TRUE;
  756. case idcClear:
  757. pRL->Clear();
  758. SetDlgItemText(hwnd, idcPrint, NULL);
  759. SetDlgItemInt(hwnd, idcResult, TRUE, FALSE);
  760. return TRUE;
  761. }
  762. }
  763. break;
  764. }
  765. return FALSE;
  766. }
  767. #endif