Home | History | Annotate | Download | only in simple_injection
      1 /*
      2  * Copyright 2014 Google Inc. All rights reserved.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "checked_adder.h"
     18 
     19 #include <climits>
     20 #include <iostream>
     21 
     22 class CheckedAdder : public Adder {
     23 private:
     24   bool add_overflows(int x, int y) {
     25     if (y > x)
     26       std::swap(x, y);
     27     // Now y <= x.
     28     const int half_max = INT_MAX / 2;
     29     const int half_min = INT_MIN / 2;
     30     if (x > half_max) {
     31       // We can't have negative overflow, but might have positive overflow.
     32       if (y > half_max)
     33         return true;
     34       if (y <= 0)
     35         return false;
     36       // x <= INT_MAX && y <= half_max,
     37       // so: x + y <= INT_MAX + half_max
     38       // so: x - half_max + y <= INT_MAX
     39       // so: (x - half_max + y) doesn't overflow.
     40       // (x + y) > INT_MAX iff (x - half_max + y) > (INT_MAX - half_max)
     41       return (x - half_max + y) > (INT_MAX - half_max);
     42     }
     43     // y <= x <= half_max, can't have positive overflow.
     44     if (y < half_min) {
     45       // We can't have positive overflow, but might have negative overflow.
     46       if (x < half_min)
     47         return true;
     48       if (x >= 0)
     49         return false;
     50       // y >= INT_MIN && x >= half_min,
     51       // so: y + x >= INT_MIN + half_min
     52       // so: y - half_min + x >= INT_MAX
     53       // so: (y - half_min + x) doesn't overflow.
     54       // (y + x) < INT_MIN iff (y - half_min + x) < (INT_MIN - half_min)
     55       return (y - half_min + x) < (INT_MIN - half_min);
     56     }
     57     // Neither negative nor positive overflow.
     58     return false;
     59   }
     60 
     61 public:
     62   INJECT(CheckedAdder()) = default;
     63 
     64   virtual int add(int x, int y) override {
     65     if (add_overflows(x, y)) {
     66       std::cerr << "CheckedAdder: detected overflow during addition of " << x << " and " << y << std::endl;
     67       abort();
     68     }
     69     return x + y;
     70   }
     71 };
     72 
     73 fruit::Component<Adder> getCheckedAdderComponent() {
     74   return fruit::createComponent().bind<Adder, CheckedAdder>();
     75 }
     76