Serenity Operating System
at portability 171 lines 4.4 kB view raw
1/* 2 * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "Keypad.h" 28#include <AK/StringBuilder.h> 29#include <math.h> 30 31Keypad::Keypad() 32{ 33} 34 35Keypad::~Keypad() 36{ 37} 38 39void Keypad::type_digit(int digit) 40{ 41 switch (m_state) { 42 case State::External: 43 m_state = State::TypingInteger; 44 m_negative = false; 45 m_int_value = digit; 46 m_frac_value = 0; 47 m_frac_length = 0; 48 break; 49 case State::TypingInteger: 50 ASSERT(m_frac_value == 0); 51 ASSERT(m_frac_length == 0); 52 m_int_value *= 10; 53 m_int_value += digit; 54 break; 55 case State::TypingDecimal: 56 if (m_frac_length > 6) 57 break; 58 m_frac_value *= 10; 59 m_frac_value += digit; 60 m_frac_length++; 61 break; 62 } 63} 64 65void Keypad::type_decimal_point() 66{ 67 switch (m_state) { 68 case State::External: 69 m_negative = false; 70 m_int_value = 0; 71 m_frac_value = 0; 72 m_frac_length = 0; 73 break; 74 case State::TypingInteger: 75 ASSERT(m_frac_value == 0); 76 ASSERT(m_frac_length == 0); 77 m_state = State::TypingDecimal; 78 break; 79 case State::TypingDecimal: 80 // Ignore it. 81 break; 82 } 83} 84 85void Keypad::type_backspace() 86{ 87 switch (m_state) { 88 case State::External: 89 m_negative = false; 90 m_int_value = 0; 91 m_frac_value = 0; 92 m_frac_length = 0; 93 break; 94 case State::TypingDecimal: 95 if (m_frac_length > 0) { 96 m_frac_value /= 10; 97 m_frac_length--; 98 break; 99 } 100 ASSERT(m_frac_value == 0); 101 m_state = State::TypingInteger; 102 [[fallthrough]]; 103 case State::TypingInteger: 104 ASSERT(m_frac_value == 0); 105 ASSERT(m_frac_length == 0); 106 m_int_value /= 10; 107 if (m_int_value == 0) 108 m_negative = false; 109 break; 110 } 111} 112 113double Keypad::value() const 114{ 115 double res = 0.0; 116 117 long frac = m_frac_value; 118 for (int i = 0; i < m_frac_length; i++) { 119 int digit = frac % 10; 120 res += digit; 121 res /= 10.0; 122 frac /= 10; 123 } 124 125 res += m_int_value; 126 if (m_negative) 127 res = -res; 128 129 return res; 130} 131 132void Keypad::set_value(double value) 133{ 134 m_state = State::External; 135 136 if (value < 0.0) { 137 m_negative = true; 138 value = -value; 139 } else 140 m_negative = false; 141 142 m_int_value = value; 143 value -= m_int_value; 144 145 m_frac_value = 0; 146 m_frac_length = 0; 147 while (value != 0) { 148 value *= 10.0; 149 int digit = value; 150 m_frac_value *= 10; 151 m_frac_value += digit; 152 m_frac_length++; 153 value -= digit; 154 155 if (m_frac_length > 6) 156 break; 157 } 158} 159 160String Keypad::to_string() const 161{ 162 StringBuilder builder; 163 if (m_negative) 164 builder.append("-"); 165 builder.appendf("%ld.", m_int_value); 166 167 if (m_frac_length > 0) 168 builder.appendf("%0*ld", m_frac_length, m_frac_value); 169 170 return builder.to_string(); 171}