cairo-script-stack.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*
  2. * Copyright © 2008 Chris Wilson <chris@chris-wilson.co.uk>
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it either under the terms of the GNU Lesser General Public
  6. * License version 2.1 as published by the Free Software Foundation
  7. * (the "LGPL") or, at your option, under the terms of the Mozilla
  8. * Public License Version 1.1 (the "MPL"). If you do not alter this
  9. * notice, a recipient may use your version of this file under either
  10. * the MPL or the LGPL.
  11. *
  12. * You should have received a copy of the LGPL along with this library
  13. * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  15. * You should have received a copy of the MPL along with this library
  16. * in the file COPYING-MPL-1.1
  17. *
  18. * The contents of this file are subject to the Mozilla Public License
  19. * Version 1.1 (the "License"); you may not use this file except in
  20. * compliance with the License. You may obtain a copy of the License at
  21. * http://www.mozilla.org/MPL/
  22. *
  23. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  24. * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  25. * the specific language governing rights and limitations.
  26. *
  27. * The Original Code is the cairo graphics library.
  28. *
  29. * The Initial Developer of the Original Code is Chris Wilson.
  30. *
  31. * Contributor(s):
  32. * Chris Wilson <chris@chris-wilson.co.uk>
  33. */
  34. #include "config.h"
  35. #include "cairo-script-private.h"
  36. #include <limits.h> /* INT_MAX */
  37. #include <string.h>
  38. csi_status_t
  39. _csi_stack_init (csi_t *ctx, csi_stack_t *stack, csi_integer_t size)
  40. {
  41. csi_status_t status = CSI_STATUS_SUCCESS;
  42. stack->len = 0;
  43. stack->size = size;
  44. /* assert ((unsigned) size < INT_MAX / sizeof (csi_object_t)); */
  45. stack->objects = _csi_alloc (ctx, size * sizeof (csi_object_t));
  46. if (_csi_unlikely (stack->objects == NULL))
  47. status = _csi_error (CSI_STATUS_NO_MEMORY);
  48. return status;
  49. }
  50. void
  51. _csi_stack_fini (csi_t *ctx, csi_stack_t *stack)
  52. {
  53. csi_integer_t n;
  54. for (n = 0; n < stack->len; n++)
  55. csi_object_free (ctx, &stack->objects[n]);
  56. _csi_free (ctx, stack->objects);
  57. }
  58. csi_status_t
  59. _csi_stack_roll (csi_t *ctx,
  60. csi_stack_t *stack,
  61. csi_integer_t mod, csi_integer_t n)
  62. {
  63. csi_object_t stack_copy[128];
  64. csi_object_t *copy;
  65. csi_integer_t last, i, len;
  66. switch (mod) { /* special cases */
  67. case 1:
  68. last = stack->len - 1;
  69. stack_copy[0] = stack->objects[last];
  70. for (i = last; --n; i--)
  71. stack->objects[i] = stack->objects[i-1];
  72. stack->objects[i] = stack_copy[0];
  73. return CSI_STATUS_SUCCESS;
  74. case -1:
  75. last = stack->len - 1;
  76. stack_copy[0] = stack->objects[i = last - n + 1];
  77. for (; --n; i++)
  78. stack->objects[i] = stack->objects[i+1];
  79. stack->objects[i] = stack_copy[0];
  80. return CSI_STATUS_SUCCESS;
  81. }
  82. /* fall back to a copy */
  83. if (n > ARRAY_LENGTH (stack_copy)) {
  84. if (_csi_unlikely ((unsigned) n > INT_MAX / sizeof (csi_object_t)))
  85. return _csi_error (CSI_STATUS_NO_MEMORY);
  86. copy = _csi_alloc (ctx, n * sizeof (csi_object_t));
  87. if (copy == NULL)
  88. return _csi_error (CSI_STATUS_NO_MEMORY);
  89. } else
  90. copy = stack_copy;
  91. i = stack->len - n;
  92. memcpy (copy, stack->objects + i, n * sizeof (csi_object_t));
  93. mod = -mod;
  94. if (mod < 0)
  95. mod += n;
  96. last = mod;
  97. for (len = n; n--; i++) {
  98. stack->objects[i] = copy[last];
  99. if (++last == len)
  100. last = 0;
  101. }
  102. if (copy != stack_copy)
  103. _csi_free (ctx, copy);
  104. return CSI_STATUS_SUCCESS;
  105. }
  106. csi_status_t
  107. _csi_stack_grow (csi_t *ctx, csi_stack_t *stack, csi_integer_t cnt)
  108. {
  109. csi_integer_t newsize;
  110. csi_object_t *newstack;
  111. if (_csi_likely (cnt <= stack->size))
  112. return CSI_STATUS_SUCCESS;
  113. if (_csi_unlikely ((unsigned) cnt >= INT_MAX / sizeof (csi_object_t)))
  114. return _csi_error (CSI_STATUS_NO_MEMORY);
  115. newsize = stack->size;
  116. do {
  117. newsize *= 2;
  118. } while (newsize <= cnt);
  119. newstack = _csi_realloc (ctx,
  120. stack->objects,
  121. newsize * sizeof (csi_object_t));
  122. if (_csi_unlikely (newstack == NULL))
  123. return _csi_error (CSI_STATUS_NO_MEMORY);
  124. stack->objects = newstack;
  125. stack->size = newsize;
  126. return CSI_STATUS_SUCCESS;
  127. }
  128. csi_status_t
  129. _csi_stack_push_internal (csi_t *ctx, csi_stack_t *stack,
  130. const csi_object_t *obj)
  131. {
  132. csi_status_t status;
  133. status = _csi_stack_grow (ctx, stack, stack->size + 1);
  134. if (_csi_unlikely (status))
  135. return status;
  136. stack->objects[stack->len++] = *obj;
  137. return CSI_STATUS_SUCCESS;
  138. }
  139. csi_object_t *
  140. _csi_stack_peek (csi_stack_t *stack, csi_integer_t i)
  141. {
  142. if (_csi_unlikely (stack->len < i))
  143. return NULL;
  144. return &stack->objects[stack->len - i -1];
  145. }
  146. void
  147. _csi_stack_pop (csi_t *ctx, csi_stack_t *stack, csi_integer_t count)
  148. {
  149. if (_csi_unlikely (stack->len < count))
  150. count = stack->len;
  151. while (count--)
  152. csi_object_free (ctx, &stack->objects[--stack->len]);
  153. }
  154. csi_status_t
  155. _csi_stack_exch (csi_stack_t *stack)
  156. {
  157. csi_object_t tmp;
  158. csi_integer_t n;
  159. if (_csi_unlikely (stack->len < 2))
  160. return _csi_error (CSI_STATUS_INVALID_SCRIPT);
  161. n = stack->len - 1;
  162. tmp = stack->objects[n];
  163. stack->objects[n] = stack->objects[n - 1];
  164. stack->objects[n - 1] = tmp;
  165. return CSI_STATUS_SUCCESS;
  166. }