xvect.h is now based on kvec.h
This commit is contained in:
		
							parent
							
								
									9af074d803
								
							
						
					
					
						commit
						f7d506cd35
					
				| 
						 | 
				
			
			@ -17,6 +17,10 @@
 | 
			
		|||
# error enable PIC_NONE_IS_FALSE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef xvect_t(pic_sym *) xvect;
 | 
			
		||||
 | 
			
		||||
#define xv_push_sym(v, x) xv_push(pic_sym *, (v), (x))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * scope object
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +98,7 @@ new_analyze_state(pic_state *pic)
 | 
			
		|||
  push_scope(state, pic_nil_value());
 | 
			
		||||
 | 
			
		||||
  pic_dict_for_each (sym, pic->globals, it) {
 | 
			
		||||
    xv_push(&state->scope->locals, &sym);
 | 
			
		||||
    xv_push_sym(state->scope->locals, sym);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return state;
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +123,7 @@ analyze_args(pic_state *pic, pic_value formals, bool *varg, xvect *args, xvect *
 | 
			
		|||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    sym = pic_sym_ptr(t);
 | 
			
		||||
    xv_push(args, &sym);
 | 
			
		||||
    xv_push_sym(*args, sym);
 | 
			
		||||
  }
 | 
			
		||||
  if (pic_nil_p(v)) {
 | 
			
		||||
    *varg = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +131,7 @@ analyze_args(pic_state *pic, pic_value formals, bool *varg, xvect *args, xvect *
 | 
			
		|||
  else if (pic_sym_p(v)) {
 | 
			
		||||
    *varg = true;
 | 
			
		||||
    sym = pic_sym_ptr(v);
 | 
			
		||||
    xv_push(locals, &sym);
 | 
			
		||||
    xv_push_sym(*locals, sym);
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -144,9 +148,9 @@ push_scope(analyze_state *state, pic_value formals)
 | 
			
		|||
  bool varg;
 | 
			
		||||
  xvect args, locals, captures;
 | 
			
		||||
 | 
			
		||||
  xv_init(&args, sizeof(pic_sym *));
 | 
			
		||||
  xv_init(&locals, sizeof(pic_sym *));
 | 
			
		||||
  xv_init(&captures, sizeof(pic_sym *));
 | 
			
		||||
  xv_init(args);
 | 
			
		||||
  xv_init(locals);
 | 
			
		||||
  xv_init(captures);
 | 
			
		||||
 | 
			
		||||
  if (analyze_args(pic, formals, &varg, &args, &locals)) {
 | 
			
		||||
    scope = pic_alloc(pic, sizeof(analyze_scope));
 | 
			
		||||
| 
						 | 
				
			
			@ -163,8 +167,8 @@ push_scope(analyze_state *state, pic_value formals)
 | 
			
		|||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    xv_destroy(&args);
 | 
			
		||||
    xv_destroy(&locals);
 | 
			
		||||
    xv_destroy(args);
 | 
			
		||||
    xv_destroy(locals);
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -172,12 +176,13 @@ push_scope(analyze_state *state, pic_value formals)
 | 
			
		|||
static void
 | 
			
		||||
pop_scope(analyze_state *state)
 | 
			
		||||
{
 | 
			
		||||
  pic_state *pic = state->pic;
 | 
			
		||||
  analyze_scope *scope;
 | 
			
		||||
 | 
			
		||||
  scope = state->scope;
 | 
			
		||||
  xv_destroy(&scope->args);
 | 
			
		||||
  xv_destroy(&scope->locals);
 | 
			
		||||
  xv_destroy(&scope->captures);
 | 
			
		||||
  xv_destroy(scope->args);
 | 
			
		||||
  xv_destroy(scope->locals);
 | 
			
		||||
  xv_destroy(scope->captures);
 | 
			
		||||
 | 
			
		||||
  scope = scope->up;
 | 
			
		||||
  pic_free(state->pic, state->scope);
 | 
			
		||||
| 
						 | 
				
			
			@ -187,38 +192,33 @@ pop_scope(analyze_state *state)
 | 
			
		|||
static bool
 | 
			
		||||
lookup_scope(analyze_scope *scope, pic_sym *sym)
 | 
			
		||||
{
 | 
			
		||||
  pic_sym **arg, **local;
 | 
			
		||||
  size_t i;
 | 
			
		||||
 | 
			
		||||
  /* args */
 | 
			
		||||
  for (i = 0; i < xv_size(&scope->args); ++i) {
 | 
			
		||||
    arg = xv_get(&scope->args, i);
 | 
			
		||||
    if (*arg == sym)
 | 
			
		||||
  for (i = 0; i < xv_size(scope->args); ++i) {
 | 
			
		||||
    if (xv_A(scope->args, i) == sym)
 | 
			
		||||
      return true;
 | 
			
		||||
  }
 | 
			
		||||
  /* locals */
 | 
			
		||||
  for (i = 0; i < xv_size(&scope->locals); ++i) {
 | 
			
		||||
    local = xv_get(&scope->locals, i);
 | 
			
		||||
    if (*local == sym)
 | 
			
		||||
  for (i = 0; i < xv_size(scope->locals); ++i) {
 | 
			
		||||
    if (xv_A(scope->locals, i) == sym)
 | 
			
		||||
      return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
capture_var(analyze_scope *scope, pic_sym *sym)
 | 
			
		||||
capture_var(pic_state *pic, analyze_scope *scope, pic_sym *sym)
 | 
			
		||||
{
 | 
			
		||||
  pic_sym **var;
 | 
			
		||||
  size_t i;
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < xv_size(&scope->captures); ++i) {
 | 
			
		||||
    var = xv_get(&scope->captures, i);
 | 
			
		||||
    if (*var == sym) {
 | 
			
		||||
  for (i = 0; i < xv_size(scope->captures); ++i) {
 | 
			
		||||
    if (xv_A(scope->captures, i) == sym) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (i == xv_size(&scope->captures)) {
 | 
			
		||||
    xv_push(&scope->captures, &sym);
 | 
			
		||||
  if (i == xv_size(scope->captures)) {
 | 
			
		||||
    xv_push_sym(scope->captures, sym);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -231,7 +231,7 @@ find_var(analyze_state *state, pic_sym *sym)
 | 
			
		|||
  while (scope) {
 | 
			
		||||
    if (lookup_scope(scope, sym)) {
 | 
			
		||||
      if (depth > 0) {
 | 
			
		||||
        capture_var(scope, sym);
 | 
			
		||||
        capture_var(state->pic, scope, sym);
 | 
			
		||||
      }
 | 
			
		||||
      return depth;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -252,7 +252,7 @@ define_var(analyze_state *state, pic_sym *sym)
 | 
			
		|||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  xv_push(&scope->locals, &sym);
 | 
			
		||||
  xv_push_sym(scope->locals, sym);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static pic_value analyze_node(analyze_state *, pic_value, bool);
 | 
			
		||||
| 
						 | 
				
			
			@ -373,13 +373,11 @@ analyze_procedure(analyze_state *state, pic_value name, pic_value formals, pic_v
 | 
			
		|||
 | 
			
		||||
  if (push_scope(state, formals)) {
 | 
			
		||||
    analyze_scope *scope = state->scope;
 | 
			
		||||
    pic_sym **var;
 | 
			
		||||
    size_t i;
 | 
			
		||||
 | 
			
		||||
    args = pic_nil_value();
 | 
			
		||||
    for (i = xv_size(&scope->args); i > 0; --i) {
 | 
			
		||||
      var = xv_get(&scope->args, i - 1);
 | 
			
		||||
      pic_push(pic, pic_obj_value(*var), args);
 | 
			
		||||
    for (i = xv_size(scope->args); i > 0; --i) {
 | 
			
		||||
      pic_push(pic, pic_obj_value(xv_A(scope->args, i - 1)), args);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    varg = scope->varg
 | 
			
		||||
| 
						 | 
				
			
			@ -392,15 +390,13 @@ analyze_procedure(analyze_state *state, pic_value name, pic_value formals, pic_v
 | 
			
		|||
    analyze_deferred(state);
 | 
			
		||||
 | 
			
		||||
    locals = pic_nil_value();
 | 
			
		||||
    for (i = xv_size(&scope->locals); i > 0; --i) {
 | 
			
		||||
      var = xv_get(&scope->locals, i - 1);
 | 
			
		||||
      pic_push(pic, pic_obj_value(*var), locals);
 | 
			
		||||
    for (i = xv_size(scope->locals); i > 0; --i) {
 | 
			
		||||
      pic_push(pic, pic_obj_value(xv_A(scope->locals, i - 1)), locals);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    captures = pic_nil_value();
 | 
			
		||||
    for (i = xv_size(&scope->captures); i > 0; --i) {
 | 
			
		||||
      var = xv_get(&scope->captures, i - 1);
 | 
			
		||||
      pic_push(pic, pic_obj_value(*var), captures);
 | 
			
		||||
    for (i = xv_size(scope->captures); i > 0; --i) {
 | 
			
		||||
      pic_push(pic, pic_obj_value(xv_A(scope->captures, i - 1)), captures);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pop_scope(state);
 | 
			
		||||
| 
						 | 
				
			
			@ -925,27 +921,24 @@ create_activation(codegen_context *cxt)
 | 
			
		|||
{
 | 
			
		||||
  size_t i, n;
 | 
			
		||||
  xhash regs;
 | 
			
		||||
  pic_sym **var;
 | 
			
		||||
  size_t offset;
 | 
			
		||||
 | 
			
		||||
  xh_init_ptr(®s, sizeof(size_t));
 | 
			
		||||
 | 
			
		||||
  offset = 1;
 | 
			
		||||
  for (i = 0; i < xv_size(&cxt->args); ++i) {
 | 
			
		||||
    var = xv_get(&cxt->args, i);
 | 
			
		||||
  for (i = 0; i < xv_size(cxt->args); ++i) {
 | 
			
		||||
    n = i + offset;
 | 
			
		||||
    xh_put_ptr(®s, *var, &n);
 | 
			
		||||
    xh_put_ptr(®s, xv_A(cxt->args, i), &n);
 | 
			
		||||
  }
 | 
			
		||||
  offset += i;
 | 
			
		||||
  for (i = 0; i < xv_size(&cxt->locals); ++i) {
 | 
			
		||||
    var = xv_get(&cxt->locals, i);
 | 
			
		||||
  for (i = 0; i < xv_size(cxt->locals); ++i) {
 | 
			
		||||
    n = i + offset;
 | 
			
		||||
    xh_put_ptr(®s, *var, &n);
 | 
			
		||||
    xh_put_ptr(®s, xv_A(cxt->locals, i), &n);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < xv_size(&cxt->captures); ++i) {
 | 
			
		||||
    var = xv_get(&cxt->captures, i);
 | 
			
		||||
    if ((n = xh_val(xh_get_ptr(®s, *var), size_t)) <= xv_size(&cxt->args) || (cxt->varg && n == xv_size(&cxt->args) + 1)) {
 | 
			
		||||
  for (i = 0; i < xv_size(cxt->captures); ++i) {
 | 
			
		||||
    n = xh_val(xh_get_ptr(®s, xv_A(cxt->captures, i)), size_t);
 | 
			
		||||
    if (n <= xv_size(cxt->args) || (cxt->varg && n == xv_size(cxt->args) + 1)) {
 | 
			
		||||
      /* copy arguments to capture variable area */
 | 
			
		||||
      cxt->code[cxt->clen].insn = OP_LREF;
 | 
			
		||||
      cxt->code[cxt->clen].u.i = (int)n;
 | 
			
		||||
| 
						 | 
				
			
			@ -966,7 +959,6 @@ push_codegen_context(codegen_state *state, pic_value name, pic_value args, pic_v
 | 
			
		|||
  pic_state *pic = state->pic;
 | 
			
		||||
  codegen_context *cxt;
 | 
			
		||||
  pic_value var, it;
 | 
			
		||||
  pic_sym *sym;
 | 
			
		||||
 | 
			
		||||
  assert(pic_sym_p(name) || pic_false_p(name));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -977,21 +969,18 @@ push_codegen_context(codegen_state *state, pic_value name, pic_value args, pic_v
 | 
			
		|||
    : pic_sym_ptr(name);
 | 
			
		||||
  cxt->varg = varg;
 | 
			
		||||
 | 
			
		||||
  xv_init(&cxt->args, sizeof(pic_sym *));
 | 
			
		||||
  xv_init(&cxt->locals, sizeof(pic_sym *));
 | 
			
		||||
  xv_init(&cxt->captures, sizeof(pic_sym *));
 | 
			
		||||
  xv_init(cxt->args);
 | 
			
		||||
  xv_init(cxt->locals);
 | 
			
		||||
  xv_init(cxt->captures);
 | 
			
		||||
 | 
			
		||||
  pic_for_each (var, args, it) {
 | 
			
		||||
    sym = pic_sym_ptr(var);
 | 
			
		||||
    xv_push(&cxt->args, &sym);
 | 
			
		||||
    xv_push_sym(cxt->args, pic_sym_ptr(var));
 | 
			
		||||
  }
 | 
			
		||||
  pic_for_each (var, locals, it) {
 | 
			
		||||
    sym = pic_sym_ptr(var);
 | 
			
		||||
    xv_push(&cxt->locals, &sym);
 | 
			
		||||
    xv_push_sym(cxt->locals, pic_sym_ptr(var));
 | 
			
		||||
  }
 | 
			
		||||
  pic_for_each (var, captures, it) {
 | 
			
		||||
    sym = pic_sym_ptr(var);
 | 
			
		||||
    xv_push(&cxt->captures, &sym);
 | 
			
		||||
    xv_push_sym(cxt->captures, pic_sym_ptr(var));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  cxt->code = pic_calloc(pic, PIC_ISEQ_SIZE, sizeof(pic_code));
 | 
			
		||||
| 
						 | 
				
			
			@ -1026,9 +1015,9 @@ pop_codegen_context(codegen_state *state)
 | 
			
		|||
  irep = (struct pic_irep *)pic_obj_alloc(pic, sizeof(struct pic_irep), PIC_TT_IREP);
 | 
			
		||||
  irep->name = state->cxt->name;
 | 
			
		||||
  irep->varg = state->cxt->varg;
 | 
			
		||||
  irep->argc = (int)xv_size(&state->cxt->args) + 1;
 | 
			
		||||
  irep->localc = (int)xv_size(&state->cxt->locals);
 | 
			
		||||
  irep->capturec = (int)xv_size(&state->cxt->captures);
 | 
			
		||||
  irep->argc = (int)xv_size(state->cxt->args) + 1;
 | 
			
		||||
  irep->localc = (int)xv_size(state->cxt->locals);
 | 
			
		||||
  irep->capturec = (int)xv_size(state->cxt->captures);
 | 
			
		||||
  irep->code = pic_realloc(pic, state->cxt->code, sizeof(pic_code) * state->cxt->clen);
 | 
			
		||||
  irep->clen = state->cxt->clen;
 | 
			
		||||
  irep->irep = pic_realloc(pic, state->cxt->irep, sizeof(struct pic_irep *) * state->cxt->ilen);
 | 
			
		||||
| 
						 | 
				
			
			@ -1039,9 +1028,9 @@ pop_codegen_context(codegen_state *state)
 | 
			
		|||
  irep->slen = state->cxt->slen;
 | 
			
		||||
 | 
			
		||||
  /* finalize */
 | 
			
		||||
  xv_destroy(&cxt->args);
 | 
			
		||||
  xv_destroy(&cxt->locals);
 | 
			
		||||
  xv_destroy(&cxt->captures);
 | 
			
		||||
  xv_destroy(cxt->args);
 | 
			
		||||
  xv_destroy(cxt->locals);
 | 
			
		||||
  xv_destroy(cxt->captures);
 | 
			
		||||
 | 
			
		||||
  /* destroy context */
 | 
			
		||||
  cxt = cxt->up;
 | 
			
		||||
| 
						 | 
				
			
			@ -1056,15 +1045,13 @@ index_capture(codegen_state *state, pic_sym *sym, int depth)
 | 
			
		|||
{
 | 
			
		||||
  codegen_context *cxt = state->cxt;
 | 
			
		||||
  size_t i;
 | 
			
		||||
  pic_sym **var;
 | 
			
		||||
 | 
			
		||||
  while (depth-- > 0) {
 | 
			
		||||
    cxt = cxt->up;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < xv_size(&cxt->captures); ++i) {
 | 
			
		||||
    var = xv_get(&cxt->captures, i);
 | 
			
		||||
    if (*var == sym)
 | 
			
		||||
  for (i = 0; i < xv_size(cxt->captures); ++i) {
 | 
			
		||||
    if (xv_A(cxt->captures, i) == sym)
 | 
			
		||||
      return (int)i;
 | 
			
		||||
  }
 | 
			
		||||
  return -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -1075,18 +1062,15 @@ index_local(codegen_state *state, pic_sym *sym)
 | 
			
		|||
{
 | 
			
		||||
  codegen_context *cxt = state->cxt;
 | 
			
		||||
  size_t i, offset;
 | 
			
		||||
  pic_sym **var;
 | 
			
		||||
 | 
			
		||||
  offset = 1;
 | 
			
		||||
  for (i = 0; i < xv_size(&cxt->args); ++i) {
 | 
			
		||||
    var = xv_get(&cxt->args, i);
 | 
			
		||||
    if (*var == sym)
 | 
			
		||||
  for (i = 0; i < xv_size(cxt->args); ++i) {
 | 
			
		||||
    if (xv_A(cxt->args, i) == sym)
 | 
			
		||||
      return (int)(i + offset);
 | 
			
		||||
  }
 | 
			
		||||
  offset += i;
 | 
			
		||||
  for (i = 0; i < xv_size(&cxt->locals); ++i) {
 | 
			
		||||
    var = xv_get(&cxt->locals, i);
 | 
			
		||||
    if (*var == sym)
 | 
			
		||||
  for (i = 0; i < xv_size(cxt->locals); ++i) {
 | 
			
		||||
    if (xv_A(cxt->locals, i) == sym)
 | 
			
		||||
      return (int)(i + offset);
 | 
			
		||||
  }
 | 
			
		||||
  return -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -1145,7 +1129,7 @@ codegen(codegen_state *state, pic_value obj)
 | 
			
		|||
    name = pic_sym_ptr(pic_list_ref(pic, obj, 1));
 | 
			
		||||
    if ((i = index_capture(state, name, 0)) != -1) {
 | 
			
		||||
      cxt->code[cxt->clen].insn = OP_LREF;
 | 
			
		||||
      cxt->code[cxt->clen].u.i = i + (int)xv_size(&cxt->args) + (int)xv_size(&cxt->locals) + 1;
 | 
			
		||||
      cxt->code[cxt->clen].u.i = i + (int)xv_size(cxt->args) + (int)xv_size(cxt->locals) + 1;
 | 
			
		||||
      cxt->clen++;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1191,7 +1175,7 @@ codegen(codegen_state *state, pic_value obj)
 | 
			
		|||
      name = pic_sym_ptr(pic_list_ref(pic, var, 1));
 | 
			
		||||
      if ((i = index_capture(state, name, 0)) != -1) {
 | 
			
		||||
        cxt->code[cxt->clen].insn = OP_LSET;
 | 
			
		||||
        cxt->code[cxt->clen].u.i = i + (int)xv_size(&cxt->args) + (int)xv_size(&cxt->locals) + 1;
 | 
			
		||||
        cxt->code[cxt->clen].u.i = i + (int)xv_size(cxt->args) + (int)xv_size(cxt->locals) + 1;
 | 
			
		||||
        cxt->clen++;
 | 
			
		||||
        cxt->code[cxt->clen].insn = OP_PUSHNONE;
 | 
			
		||||
        cxt->clen++;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -704,20 +704,20 @@ static void
 | 
			
		|||
gc_sweep_symbols(pic_state *pic)
 | 
			
		||||
{
 | 
			
		||||
  xh_entry *it;
 | 
			
		||||
  xvect xv;
 | 
			
		||||
  xvect_t(xh_entry *) xv;
 | 
			
		||||
  size_t i;
 | 
			
		||||
  char *cstr;
 | 
			
		||||
 | 
			
		||||
  xv_init(&xv, sizeof(xh_entry *));
 | 
			
		||||
  xv_init(xv);
 | 
			
		||||
 | 
			
		||||
  for (it = xh_begin(&pic->syms); it != NULL; it = xh_next(it)) {
 | 
			
		||||
    if (! gc_obj_is_marked((struct pic_object *)xh_val(it, pic_sym *))) {
 | 
			
		||||
      xv_push(&xv, &it);
 | 
			
		||||
      xv_push(xh_entry *, xv, it);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (i = 0; i < xv_size(&xv); ++i) {
 | 
			
		||||
    cstr = xh_key(*(xh_entry **)xv_get(&xv, i), char *);
 | 
			
		||||
  for (i = 0; i < xv_size(xv); ++i) {
 | 
			
		||||
    cstr = xh_key(xv_A(xv, i), char *);
 | 
			
		||||
 | 
			
		||||
    xh_del_str(&pic->syms, cstr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,202 +1,76 @@
 | 
			
		|||
#ifndef XVECT_H__
 | 
			
		||||
#define XVECT_H__
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014 by Yuichi Nishiwaki <yuichi@idylls.jp>
 | 
			
		||||
 */
 | 
			
		||||
/* The MIT License
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
   Copyright (c) 2008, by Attractive Chaos <attractor@live.co.uk>
 | 
			
		||||
   Copyright (c) 2014, by Yuichi Nishiwaki <yuichi@idylls.jp>
 | 
			
		||||
 | 
			
		||||
typedef struct xvect {
 | 
			
		||||
  char *data;
 | 
			
		||||
  size_t size, mask, head, tail, width;
 | 
			
		||||
} xvect;
 | 
			
		||||
   Permission is hereby granted, free of charge, to any person obtaining
 | 
			
		||||
   a copy of this software and associated documentation files (the
 | 
			
		||||
   "Software"), to deal in the Software without restriction, including
 | 
			
		||||
   without limitation the rights to use, copy, modify, merge, publish,
 | 
			
		||||
   distribute, sublicense, and/or sell copies of the Software, and to
 | 
			
		||||
   permit persons to whom the Software is furnished to do so, subject to
 | 
			
		||||
   the following conditions:
 | 
			
		||||
 | 
			
		||||
static inline void xv_init(xvect *, size_t);
 | 
			
		||||
static inline void xv_destroy(xvect *);
 | 
			
		||||
   The above copyright notice and this permission notice shall be
 | 
			
		||||
   included in all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
static inline size_t xv_size(xvect *);
 | 
			
		||||
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
			
		||||
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
			
		||||
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
			
		||||
   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
			
		||||
   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
			
		||||
   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
			
		||||
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
   SOFTWARE.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
static inline void xv_reserve(xvect *, size_t);
 | 
			
		||||
static inline void xv_shrink(xvect *, size_t);
 | 
			
		||||
#define xv_realloc(P,Z) pic_realloc(pic,P,Z)
 | 
			
		||||
#define xv_free(P) pic_free(pic,P)
 | 
			
		||||
 | 
			
		||||
static inline void *xv_get(xvect *, size_t);
 | 
			
		||||
static inline void xv_set(xvect *, size_t, void *);
 | 
			
		||||
#define xv_roundup32(x)                                                 \
 | 
			
		||||
  (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
 | 
			
		||||
 | 
			
		||||
static inline void xv_push(xvect *, void *);
 | 
			
		||||
static inline void *xv_pop(xvect *);
 | 
			
		||||
#define xvect_t(type) struct { size_t n, m; type *a; }
 | 
			
		||||
#define xv_init(v) ((v).n = (v).m = 0, (v).a = 0)
 | 
			
		||||
#define xv_destroy(v) xv_free((v).a)
 | 
			
		||||
#define xv_A(v, i) ((v).a[(i)])
 | 
			
		||||
#define xv_pop(v) ((v).a[--(v).n])
 | 
			
		||||
#define xv_size(v) ((v).n)
 | 
			
		||||
#define xv_max(v) ((v).m)
 | 
			
		||||
 | 
			
		||||
static inline void *xv_shift(xvect *);
 | 
			
		||||
static inline void xv_unshift(xvect *, void *);
 | 
			
		||||
#define xv_resize(type, v, s)                                           \
 | 
			
		||||
  ((v).m = (s), (v).a = (type*)xv_realloc((v).a, sizeof(type) * (v).m))
 | 
			
		||||
 | 
			
		||||
static inline void xv_splice(xvect *, size_t, size_t);
 | 
			
		||||
static inline void xv_insert(xvect *, size_t, void *);
 | 
			
		||||
#define xv_copy(type, v1, v0)                           \
 | 
			
		||||
  do {                                                  \
 | 
			
		||||
    if ((v1).m < (v0).n) xv_resize(type, v1, (v0).n);	\
 | 
			
		||||
    (v1).n = (v0).n;                                    \
 | 
			
		||||
    memcpy((v1).a, (v0).a, sizeof(type) * (v0).n);      \
 | 
			
		||||
  } while (0)                                           \
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_init(xvect *x, size_t width)
 | 
			
		||||
{
 | 
			
		||||
  x->data = NULL;
 | 
			
		||||
  x->width = width;
 | 
			
		||||
  x->size = 0;
 | 
			
		||||
  x->mask = (size_t)-1;
 | 
			
		||||
  x->head = 0;
 | 
			
		||||
  x->tail = 0;
 | 
			
		||||
}
 | 
			
		||||
#define xv_push(type, v, x)                                     \
 | 
			
		||||
  do {                                                          \
 | 
			
		||||
    if ((v).n == (v).m) {                                       \
 | 
			
		||||
      (v).m = (v).m? (v).m<<1 : 2;                              \
 | 
			
		||||
      (v).a = (type*)xv_realloc((v).a, sizeof(type) * (v).m);	\
 | 
			
		||||
    }                                                           \
 | 
			
		||||
    (v).a[(v).n++] = (x);                                       \
 | 
			
		||||
  } while (0)
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_destroy(xvect *x)
 | 
			
		||||
{
 | 
			
		||||
  free(x->data);
 | 
			
		||||
}
 | 
			
		||||
#define xv_pushp(type, v)                                       \
 | 
			
		||||
  (((v).n == (v).m)?                                            \
 | 
			
		||||
   ((v).m = ((v).m? (v).m<<1 : 2),                              \
 | 
			
		||||
    (v).a = (type*)xv_realloc((v).a, sizeof(type) * (v).m), 0)     \
 | 
			
		||||
   : 0), ((v).a + ((v).n++))
 | 
			
		||||
 | 
			
		||||
static inline size_t
 | 
			
		||||
xv_size(xvect *x)
 | 
			
		||||
{
 | 
			
		||||
  return x->tail < x->head
 | 
			
		||||
    ? x->tail + x->size - x->head
 | 
			
		||||
    : x->tail - x->head;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline size_t
 | 
			
		||||
xv_round2(size_t x)
 | 
			
		||||
{
 | 
			
		||||
  x -= 1;
 | 
			
		||||
  x |= (x >> 1);
 | 
			
		||||
  x |= (x >> 2);
 | 
			
		||||
  x |= (x >> 4);
 | 
			
		||||
  x |= (x >> 8);
 | 
			
		||||
  x |= (x >> 16);
 | 
			
		||||
  x |= (x >> 32);
 | 
			
		||||
  x++;
 | 
			
		||||
  return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_rotate(xvect *x)
 | 
			
		||||
{
 | 
			
		||||
  if (x->tail < x->head) {
 | 
			
		||||
    char buf[x->size * x->width];
 | 
			
		||||
 | 
			
		||||
    /* perform rotation */
 | 
			
		||||
    memcpy(buf, x->data, sizeof buf);
 | 
			
		||||
    memcpy(x->data, buf + x->head * x->width, (x->size - x->head) * x->width);
 | 
			
		||||
    memcpy(x->data + (x->size - x->head) * x->width, buf, x->tail * x->width);
 | 
			
		||||
    x->tail = x->size - x->head + x->tail;
 | 
			
		||||
    x->head = 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_adjust(xvect *x, size_t size)
 | 
			
		||||
{
 | 
			
		||||
  size = xv_round2(size);
 | 
			
		||||
  if (size != x->size) {
 | 
			
		||||
    xv_rotate(x);
 | 
			
		||||
    x->data = realloc(x->data, size * x->width);
 | 
			
		||||
    x->size = size;
 | 
			
		||||
    x->mask = size - 1;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_reserve(xvect *x, size_t mincapa)
 | 
			
		||||
{
 | 
			
		||||
  if (x->size < mincapa + 1) {
 | 
			
		||||
    xv_adjust(x, mincapa + 1);  /* capa == size - 1 */
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_shrink(xvect *x, size_t maxcapa)
 | 
			
		||||
{
 | 
			
		||||
  if (x->size > maxcapa + 1) {
 | 
			
		||||
    xv_adjust(x, maxcapa + 1);  /* capa == size - 1 */
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void *
 | 
			
		||||
xv_get(xvect *x, size_t i)
 | 
			
		||||
{
 | 
			
		||||
  assert(i < xv_size(x));
 | 
			
		||||
 | 
			
		||||
  return x->data + ((x->head + i) & x->mask) * x->width;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_set(xvect *x, size_t i, void *src)
 | 
			
		||||
{
 | 
			
		||||
  memcpy(xv_get(x, i), src, x->width);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_push(xvect *x, void *src)
 | 
			
		||||
{
 | 
			
		||||
  xv_reserve(x, xv_size(x) + 1);
 | 
			
		||||
  x->tail = (x->tail + 1) & x->mask;
 | 
			
		||||
  xv_set(x, xv_size(x) - 1, src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void *
 | 
			
		||||
xv_pop(xvect *x)
 | 
			
		||||
{
 | 
			
		||||
  void *dat;
 | 
			
		||||
 | 
			
		||||
  assert(xv_size(x) >= 1);
 | 
			
		||||
 | 
			
		||||
  dat = xv_get(x, xv_size(x) - 1);
 | 
			
		||||
  x->tail = (x->tail - 1) & x->mask;
 | 
			
		||||
  return dat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void *
 | 
			
		||||
xv_shift(xvect *x)
 | 
			
		||||
{
 | 
			
		||||
  void *dat;
 | 
			
		||||
 | 
			
		||||
  assert(xv_size(x) >= 1);
 | 
			
		||||
 | 
			
		||||
  dat = xv_get(x, 0);
 | 
			
		||||
  x->head = (x->head + 1) & x->mask;
 | 
			
		||||
  return dat;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_unshift(xvect *x, void *src)
 | 
			
		||||
{
 | 
			
		||||
  xv_reserve(x, xv_size(x) + 1);
 | 
			
		||||
  x->head = (x->head - 1) & x->mask;
 | 
			
		||||
  xv_set(x, 0, src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_splice(xvect *x, size_t i, size_t j)
 | 
			
		||||
{
 | 
			
		||||
  assert(i <= j && j < xv_size(x));
 | 
			
		||||
 | 
			
		||||
  xv_rotate(x);
 | 
			
		||||
  memmove(xv_get(x, i), xv_get(x, j), (xv_size(x) - j) * x->width);
 | 
			
		||||
  x->tail = (x->tail - j + i) & x->mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xv_insert(xvect *x, size_t i, void *src)
 | 
			
		||||
{
 | 
			
		||||
  assert(i <= xv_size(x));
 | 
			
		||||
 | 
			
		||||
  xv_reserve(x, xv_size(x) + 1);
 | 
			
		||||
  xv_rotate(x);
 | 
			
		||||
  x->tail = (x->tail + 1) & x->mask;
 | 
			
		||||
 | 
			
		||||
  if (xv_size(x) - 1 != i) {
 | 
			
		||||
    memmove(xv_get(x, i + 1), xv_get(x, i), (xv_size(x) - 1 - i) * x->width);
 | 
			
		||||
  }
 | 
			
		||||
  xv_set(x, i, src);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
#define xv_a(type, v, i)                                        \
 | 
			
		||||
  (((v).m <= (size_t)(i)?                                       \
 | 
			
		||||
    ((v).m = (v).n = (i) + 1, xv_roundup32((v).m),              \
 | 
			
		||||
     (v).a = (type*)xv_realloc((v).a, sizeof(type) * (v).m), 0)    \
 | 
			
		||||
    : (v).n <= (size_t)(i)? (v).n = (i) + 1                     \
 | 
			
		||||
    : 0), (v).a[(i)])
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue