dtview.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. #include <cdt/dthdr.h>
  2. #include <stddef.h>
  3. /* Set a view path from dict to view.
  4. **
  5. ** Written by Kiem-Phong Vo (5/25/96)
  6. */
  7. static void* dtvsearch(Dt_t* dt, void* obj, int type)
  8. {
  9. Dt_t *d, *p;
  10. void *o = NULL, *n, *ok, *nk;
  11. int cmp, lk, sz, ky;
  12. Dtcompar_f cmpf;
  13. (void)lk;
  14. /* these operations only happen at the top level */
  15. if(type&(DT_INSERT|DT_DELETE|DT_CLEAR|DT_RENEW))
  16. return dt->meth->searchf(dt, obj, type);
  17. if((type&(DT_MATCH|DT_SEARCH)) || /* order sets first/last done below */
  18. ((type&(DT_FIRST|DT_LAST)) && !(dt->meth->type&(DT_OBAG|DT_OSET)) ) )
  19. { for(d = dt; d; d = d->view)
  20. if ((o = d->meth->searchf(d, obj, type)))
  21. break;
  22. dt->walk = d;
  23. return o;
  24. }
  25. if(dt->meth->type & (DT_OBAG|DT_OSET) )
  26. { if(!(type & (DT_FIRST|DT_LAST|DT_NEXT|DT_PREV)) )
  27. return NULL;
  28. n = nk = NULL; p = NULL;
  29. for(d = dt; d; d = d->view)
  30. { if (!(o = d->meth->searchf(d, obj, type)))
  31. continue;
  32. _DTDSC(d->disc,ky,sz,lk,cmpf);
  33. ok = _DTKEY(o,ky,sz);
  34. if(n) /* get the right one among all dictionaries */
  35. { cmp = _DTCMP(ok, nk, cmpf, sz);
  36. if(((type & (DT_NEXT|DT_FIRST)) && cmp < 0) ||
  37. ((type & (DT_PREV|DT_LAST)) && cmp > 0) )
  38. goto a_dj;
  39. }
  40. else /* looks good for now */
  41. { a_dj: p = d;
  42. n = o;
  43. nk = ok;
  44. }
  45. }
  46. dt->walk = p;
  47. return n;
  48. }
  49. /* non-ordered methods */
  50. if(!(type & (DT_NEXT|DT_PREV)) )
  51. return NULL;
  52. if(!dt->walk || obj != _DTOBJ(dt->walk->data->here, dt->walk->disc->link) )
  53. { for(d = dt; d; d = d->view)
  54. if ((o = d->meth->searchf(d, obj, DT_SEARCH)))
  55. break;
  56. dt->walk = d;
  57. if(!(obj = o) )
  58. return NULL;
  59. }
  60. for (d = dt->walk, obj = d->meth->searchf(d, obj, type);; )
  61. { while(obj) /* keep moving until finding an uncovered object */
  62. { for(p = dt; ; p = p->view)
  63. { if(p == d) /* adjacent object is uncovered */
  64. return obj;
  65. if (p->meth->searchf(p, obj, DT_SEARCH))
  66. break;
  67. }
  68. obj = d->meth->searchf(d, obj, type);
  69. }
  70. if(!(d = dt->walk = d->view) ) /* move on to next dictionary */
  71. return NULL;
  72. else if(type&DT_NEXT)
  73. obj = d->meth->searchf(d, NULL, DT_FIRST);
  74. else obj = d->meth->searchf(d, NULL, DT_LAST);
  75. }
  76. }
  77. Dt_t* dtview(Dt_t* dt, Dt_t* view)
  78. {
  79. Dt_t* d;
  80. UNFLATTEN(dt);
  81. if(view)
  82. { UNFLATTEN(view);
  83. if(view->meth != dt->meth) /* must use the same method */
  84. return NULL;
  85. }
  86. /* make sure there won't be a cycle */
  87. for(d = view; d; d = d->view)
  88. if(d == dt)
  89. return NULL;
  90. /* no more viewing lower dictionary */
  91. if((d = dt->view) )
  92. d->nview -= 1;
  93. dt->view = dt->walk = NULL;
  94. if(!view)
  95. { dt->searchf = dt->meth->searchf;
  96. return d;
  97. }
  98. /* ok */
  99. dt->view = view;
  100. dt->searchf = dtvsearch;
  101. view->nview += 1;
  102. return view;
  103. }