Imported Upstream version 1.46.0
[platform/upstream/nghttp2.git] / third-party / mruby / mrbgems / mruby-error / src / exception.c
1 #include <mruby.h>
2 #include <mruby/throw.h>
3 #include <mruby/error.h>
4
5 MRB_API mrb_value
6 mrb_protect(mrb_state *mrb, mrb_func_t body, mrb_value data, mrb_bool *state)
7 {
8   struct mrb_jmpbuf *prev_jmp = mrb->jmp;
9   struct mrb_jmpbuf c_jmp;
10   mrb_value result = mrb_nil_value();
11   int ai = mrb_gc_arena_save(mrb);
12
13   if (state) { *state = FALSE; }
14
15   MRB_TRY(&c_jmp) {
16     mrb->jmp = &c_jmp;
17     result = body(mrb, data);
18     mrb->jmp = prev_jmp;
19   } MRB_CATCH(&c_jmp) {
20     mrb->jmp = prev_jmp;
21     result = mrb_obj_value(mrb->exc);
22     mrb->exc = NULL;
23     if (state) { *state = TRUE; }
24   } MRB_END_EXC(&c_jmp);
25
26   mrb_gc_arena_restore(mrb, ai);
27   mrb_gc_protect(mrb, result);
28   return result;
29 }
30
31 MRB_API mrb_value
32 mrb_ensure(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t ensure, mrb_value e_data)
33 {
34   struct mrb_jmpbuf *prev_jmp = mrb->jmp;
35   struct mrb_jmpbuf c_jmp;
36   mrb_value result;
37   int ai = mrb_gc_arena_save(mrb);
38
39   MRB_TRY(&c_jmp) {
40     mrb->jmp = &c_jmp;
41     result = body(mrb, b_data);
42     mrb->jmp = prev_jmp;
43   } MRB_CATCH(&c_jmp) {
44     mrb->jmp = prev_jmp;
45     mrb_gc_arena_restore(mrb, ai);
46     ensure(mrb, e_data);
47     MRB_THROW(mrb->jmp); /* rethrow catched exceptions */
48   } MRB_END_EXC(&c_jmp);
49
50   mrb_gc_arena_restore(mrb, ai);
51   mrb_gc_protect(mrb, result);
52   ensure(mrb, e_data);
53   mrb_gc_arena_restore(mrb, ai);
54   mrb_gc_protect(mrb, result);
55   return result;
56 }
57
58 MRB_API mrb_value
59 mrb_rescue(mrb_state *mrb, mrb_func_t body, mrb_value b_data,
60            mrb_func_t rescue, mrb_value r_data)
61 {
62   return mrb_rescue_exceptions(mrb, body, b_data, rescue, r_data, 1, &mrb->eStandardError_class);
63 }
64
65 MRB_API mrb_value
66 mrb_rescue_exceptions(mrb_state *mrb, mrb_func_t body, mrb_value b_data, mrb_func_t rescue, mrb_value r_data,
67                       mrb_int len, struct RClass **classes)
68 {
69   struct mrb_jmpbuf *prev_jmp = mrb->jmp;
70   struct mrb_jmpbuf c_jmp;
71   mrb_value result;
72   mrb_bool error_matched = FALSE;
73   mrb_int i;
74   int ai = mrb_gc_arena_save(mrb);
75
76   MRB_TRY(&c_jmp) {
77     mrb->jmp = &c_jmp;
78     result = body(mrb, b_data);
79     mrb->jmp = prev_jmp;
80   } MRB_CATCH(&c_jmp) {
81     mrb->jmp = prev_jmp;
82
83     for (i = 0; i < len; ++i) {
84       if (mrb_obj_is_kind_of(mrb, mrb_obj_value(mrb->exc), classes[i])) {
85         error_matched = TRUE;
86         break;
87       }
88     }
89
90     if (!error_matched) { MRB_THROW(mrb->jmp); }
91
92     mrb->exc = NULL;
93     mrb_gc_arena_restore(mrb, ai);
94     result = rescue(mrb, r_data);
95   } MRB_END_EXC(&c_jmp);
96
97   mrb_gc_arena_restore(mrb, ai);
98   mrb_gc_protect(mrb, result);
99   return result;
100 }
101
102 void
103 mrb_mruby_error_gem_init(mrb_state *mrb)
104 {
105 }
106
107 void
108 mrb_mruby_error_gem_final(mrb_state *mrb)
109 {
110 }