diff options
Diffstat (limited to 'wirish')
| -rw-r--r-- | wirish/Print.cpp | 245 | ||||
| -rw-r--r-- | wirish/Print.h | 87 | 
2 files changed, 145 insertions, 187 deletions
diff --git a/wirish/Print.cpp b/wirish/Print.cpp index 9c52321..c66ca61 100644 --- a/wirish/Print.cpp +++ b/wirish/Print.cpp @@ -1,127 +1,91 @@ -/****************************************************************************** - * The MIT License +/* + * Print.cpp - Base class that provides print() and println() + * Copyright (c) 2008 David A. Mellis.  All right reserved.   * - * Copyright (c) 2011 LeafLabs, LLC. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version.   * - * 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: + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.   * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA   * - * 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. - *****************************************************************************/ + * Modified 23 November 2006 by David A. Mellis + */ +#include "wirish.h"  #include "Print.h" -#include <cstdio> -#include <climits> -#include <cstring> - -// We'll allocate character buffers of size INT_BUF_SIZE to hold the -// string representations of numbers; this value ensures that they're -// big enough to accomodate the biggest integral value + null byte. -// -// E.g., consider -(2^63-1) = -9223372036854775807, which is 20 -// characters long, including the minus sign.  The other edge cases -// are similar. -// -// (Nonetheless, use snprintf everywhere, just in case of error). -#define INT_BUF_SIZE 21 - -// An IEEE-754 double buys you about 16 digits of precision; there's -// the possibility of minus signs, a decimal point, 'e+'/'e-', etc. -// While the Right Thing is to follow Steele and White, I'm just going -// to double what I consider a safe number of bytes and hope for the -// best. -#define DOUBLE_BUF_SIZE 40 - -static void fillBase(char *buf, int buf_size, int64 n, -                     uint8 n_real_bits, int base); -static void fillBinary(char *buf, int64 n, int start_bit); -static char baseToFmtSpec(int base); +//------------------------------ Public Methods -------------------------------  void Print::write(const char *str) { -    for (const char *c = str; *c != '\0'; c++) { -        write(*c); -    } +    while (*str) +        write(*str++);  }  void Print::write(void *buffer, uint32 size) { -    for (uint32 i = 0; i < size; i++) { -        write(*((uint8*)buffer + i)); +    uint8 *ch = (uint8*)buffer; +    while (size--) { +        write(*ch++);      }  } +void Print::print(uint8 b) { +    this->write(b); +} +  void Print::print(char c) { -    print((uint8) c); +    print((byte) c);  }  void Print::print(const char str[]) {      write(str);  } -void Print::print(uint8 b) { -    write(b); -} - -void Print::print(int32 n) { -    print(n, DEC); +void Print::print(int n) { +    print((long) n);  } -void Print::print(uint32 n) { -    print((uint64) n); +void Print::print(unsigned int n) { +    print((unsigned long) n);  } -void Print::print(int64 n) { -    print(n, DEC); -} - -void Print::print(uint64 n) { -    char buf[INT_BUF_SIZE]; -    snprintf(buf, INT_BUF_SIZE, "%llu", n); -    write(buf); +void Print::print(long n) { +    if (n < 0) { +        print('-'); +        n = -n; +    } +    printNumber(n, 10);  } -void Print::print(int32 n, int base) { -    // Worst case: sign bit set && base == BIN: 32 bytes for digits + -    // 1 null (base == BIN means no minus sign). -    char buf[33]; -    fillBase(buf, sizeof(buf), (int64)n, 32, base); -    write(buf); +void Print::print(unsigned long n) { +    printNumber(n, 10);  } -void Print::print(int64 n, int base) { -    // As above, but now 64 bytes for bits + 1 null -    char buf[65]; -    fillBase(buf, sizeof(buf), n, 64, base); -    write(buf); +void Print::print(long n, int base) { +    if (base == 0) { +        print((char) n); +    } else if (base == 10) { +        print(n); +    } else { +        printNumber(n, base); +    }  }  void Print::print(double n) { -    char buf[DOUBLE_BUF_SIZE]; -    // This breaks strict compliance with the Arduino library behavior -    // (which is equivalent to using "%.2f"), but that's really not -    // enough.  According to Stroustrup, "%f" without precision is -    // equivalent to ".6f", which is much better. -    snprintf(buf, DOUBLE_BUF_SIZE, "%f", n); -    write(buf); +    printFloat(n, 2);  }  void Print::println(void) { -    print("\r\n"); +    print('\r'); +    print('\n');  }  void Print::println(char c) { @@ -139,32 +103,27 @@ void Print::println(uint8 b) {      println();  } -void Print::println(int32 n) { +void Print::println(int n) {      print(n);      println();  } -void Print::println(uint32 n) { +void Print::println(unsigned int n) {      print(n);      println();  } -void Print::println(int64 n) { +void Print::println(long n) {      print(n);      println();  } -void Print::println(uint64 n) { +void Print::println(unsigned long n) {      print(n);      println();  } -void Print::println(int32 n, int base) { -    print(n, base); -    println(); -} - -void Print::println(int64 n, int base) { +void Print::println(long n, int base) {      print(n, base);      println();  } @@ -174,54 +133,58 @@ void Print::println(double n) {      println();  } -// -- Auxiliary functions ----------------------------------------------------- +//------------------------------ Private Methods ------------------------------ -static void fillBase(char *buf, int buf_size, int64 n, -                     uint8 n_real_bits, int base) { -    if (base == BIN) { -        fillBinary(buf, n, n_real_bits - 1); -    } else { -        char spec = baseToFmtSpec(base); -        char fmt[5]; - -        if (base == BYTE) -            n = (uint8)n; - -        if (n_real_bits == 32) { -            snprintf(fmt, sizeof(fmt), "%%l%c", spec); -            snprintf(buf, buf_size, fmt, (int32)n); -        } else { -            snprintf(fmt, sizeof(fmt), "%%ll%c", spec); -            snprintf(buf, buf_size, fmt, n); -        } +void Print::printNumber(unsigned long n, uint8 base) { +    unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. +    unsigned long i = 0; + +    if (n == 0) { +        print('0'); +        return;      } + +    while (n > 0) { +        buf[i++] = n % base; +        n /= base; +    } + +    for (; i > 0; i--) +        print((char) (buf[i - 1] < 10 ? +                      '0' + buf[i - 1] : +                      'A' + buf[i - 1] - 10));  } -// Assumes sizeof(buf) > start_bit. -static void fillBinary(char *buf, int64 n, int start_bit) { -    int b = 0;                // position in buf -    int i = start_bit;        // position in n's bits -    while(!(n & (1 << i))) { -        i--; +void Print::printFloat(double number, uint8 digits) { +    // Handle negative numbers +    if (number < 0.0) { +        print('-'); +        number = -number;      } -    for(; i >= 0; i--) { -        buf[b++] = '0' + ((n >> i) & 0x1); + +    // Round correctly so that print(1.999, 2) prints as "2.00" +    double rounding = 0.5; +    for (uint8 i=0; i<digits; ++i) { +        rounding /= 10.0; +    } + +    number += rounding; + +    // Extract the integer part of the number and print it +    unsigned long int_part = (unsigned long)number; +    double remainder = number - (double)int_part; +    print(int_part); + +    // Print the decimal point, but only if there are digits beyond +    if (digits > 0) { +        print(".");      } -    buf[b] = '\0'; -} - -static char baseToFmtSpec(int base) { -    switch (base) { -    case DEC: -        return 'd'; -    case HEX: -        return 'x'; -    case OCT: -        return 'o'; -    case BYTE: -        return 'd'; -    default: -        // Shouldn't happen, but give a sensible default -        return 'd'; + +    // Extract digits from the remainder one at a time +    while (digits-- > 0) { +        remainder *= 10.0; +        int toPrint = int(remainder); +        print(toPrint); +        remainder -= toPrint;      }  } diff --git a/wirish/Print.h b/wirish/Print.h index 4527948..dc21183 100644 --- a/wirish/Print.h +++ b/wirish/Print.h @@ -1,67 +1,62 @@ -/****************************************************************************** - * The MIT License +/* + * Print.h - Base class that provides print() and println() + * Copyright (c) 2008 David A. Mellis.  All right reserved.   * - * Copyright (c) 2011 LeafLabs, LLC. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version.   * - * 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: + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details.   * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * 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. - *****************************************************************************/ + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ -#ifndef _PRINT_H_ -#define _PRINT_H_ +#ifndef Print_h +#define Print_h -#include "libmaple_types.h" +#include <libmaple_types.h> +#include <stdio.h> // for size_t -#define DEC   10 -#define HEX   16 -#define OCT    8 -#define BIN    2 -#define BYTE   0                // yuck +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 +#define BYTE 0 -class Print { +class Print +{ + private: +    void printNumber(unsigned long, uint8); +    void printFloat(double, uint8);   public:      virtual void write(uint8) = 0;      virtual void write(const char *str); -    virtual void write(void *buf, uint32 size); - +    virtual void write(void *, uint32);      void print(char);      void print(const char[]);      void print(uint8); -    void print(int32); -    void print(uint32); -    void print(int64); -    void print(uint64); -    void print(int32, int); -    void print(int64, int); +    void print(int); +    void print(unsigned int); +    void print(long); +    void print(unsigned long); +    void print(long, int);      void print(double); -      void println(void);      void println(char);      void println(const char[]);      void println(uint8); -    void println(int32); -    void println(uint32); -    void println(int64); -    void println(uint64); -    void println(int32, int); -    void println(int64, int); +    void println(int); +    void println(unsigned int); +    void println(long); +    void println(unsigned long); +    void println(long, int);      void println(double);  };  | 
