summaryrefslogtreecommitdiff
path: root/generic/String.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'generic/String.cpp')
-rw-r--r--generic/String.cpp358
1 files changed, 358 insertions, 0 deletions
diff --git a/generic/String.cpp b/generic/String.cpp
new file mode 100644
index 0000000..d6a1e01
--- /dev/null
+++ b/generic/String.cpp
@@ -0,0 +1,358 @@
+#include <iostream.h>
+#include <string.h>
+#include <stdarg.h>
+#include "String.h"
+#include "Exceptions.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define _(x) x
+#endif
+
+extern "C" {
+ double dateCalc(char *, char *);
+ int isDateArgument(char *);
+}
+
+char String::t[BUFSIZ + 1];
+
+String::String(const String & s) : str(Base::strdup(s.str)), siz(s.siz) { }
+
+String::String(char c) : siz(1) {
+ char * t = (char *) malloc(2);
+
+ sprintf(t, "%c", c);
+ str = t;
+}
+
+String::String(const char * s) : str(s ? Base::strdup(s) : Base::strdup("")) {
+ siz = ::strlen(str);
+}
+
+String::String(int hs, const char * s) : str(s ? Base::strdup(s) : Base::strdup("")), siz(hs) { }
+
+String::String(int i) {
+ char t[20];
+
+ sprintf(t, "%i", i);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::String(unsigned int i) {
+ char t[20];
+
+ sprintf(t, "%u", i);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+#ifdef USE_LONGLONG
+String::String(long long l) {
+ char t[40];
+
+ sprintf(t, "%lld", l);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::String(unsigned long long l) {
+ char t[40];
+
+ sprintf(t, "%llu", l);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+#endif
+
+String::String(double d) {
+ char t[30];
+
+ sprintf(t, "%g", d);
+ str = Base::strdup(t);
+ siz = ::strlen(str);
+}
+
+String::~String() {
+ free(str);
+}
+
+const char * String::set(const char * s, ...) {
+ va_list ap;
+
+/* This causes a warning: cannot pass objects of type `const String' through `...'
+ but it is not really a problem. */
+ va_start(ap, s);
+ vsnprintf(t, BUFSIZ, s, ap);
+ free(str);
+ str = Base::strdup(t);
+ va_end(ap);
+ siz = ::strlen(str);
+ return t;
+}
+
+const char * String::set(const String & s, ...) {
+ va_list ap;
+
+ va_start(ap, s);
+ vsnprintf(t, BUFSIZ, s.str, ap);
+ free(str);
+ str = Base::strdup(t);
+ va_end(ap);
+ siz = ::strlen(str);
+ return t;
+}
+
+const char * String::to_charp(size_t from, ssize_t to) const {
+ if (to < 0) {
+ strncpy(t, &(str[from]), BUFSIZ);
+ } else {
+ if (((size_t) to) >= siz) {
+ to = siz - 1;
+ }
+
+ if ((((size_t) to) - from) > BUFSIZ) {
+ from -= (to - from) - BUFSIZ;
+ }
+
+ if (((size_t) to) >= from) {
+ size_t i;
+ for (i = 0; i <= ((size_t) to) - from; i++) {
+ t[i] = str[i + from];
+ }
+ t[i] = '\0';
+ } else {
+ t[0] = '\0';
+ }
+ }
+ return t;
+}
+
+String String::extract(size_t from, ssize_t to) const {
+ return String(to_charp(from, to));
+}
+
+char * String::strdup(size_t from, ssize_t to) const {
+ return Base::strdup(to_charp(from, to));
+}
+
+int String::to_int(void) const {
+ int r;
+
+ sscanf(str, "%i", &r);
+ return r;
+}
+
+double String::to_double(void) const {
+ double r;
+
+ sscanf(str, "%lf", &r);
+ return r;
+}
+
+String & String::operator=(const String & s) {
+ if (str != s.str) {
+ // On évite l'autodestruction...
+ free(str);
+ str = s.strdup();
+ siz = s.siz;
+ }
+ return *this;
+}
+
+String String::operator+(const String & s) const {
+ char * t = (char *) malloc(s.siz + siz + 1), * u;
+ String o;
+
+ strcpy((u = t), str);
+ u += siz;
+ strcpy(u, s.str);
+ o = String(siz + s.siz, t);
+ free(t);
+ return o;
+}
+
+String & String::operator+=(const String & s) {
+ char * t = (char *) malloc(s.siz + siz + 1), * u;
+
+ strcpy((u = t), str);
+ u += siz;
+ strcat(u, s.str);
+ free(str);
+ str = t;
+ siz += s.siz;
+ return (*this);
+}
+
+ostream & operator<<(ostream & os, const String & s) {
+ return (os << s.to_charp());
+}
+
+istream & operator>>(istream & is, String & s) {
+ char c = 0;
+
+ s.set("");
+
+ while (!is.eof()) {
+ c = is.get();
+ if (c == '\n') return is;
+ if (c == '\r') continue;
+ s += c;
+ }
+
+ return is;
+}
+
+bool String::operator!=(const String & s) const {
+ return (strcmp(str, s.str) != 0);
+}
+
+bool String::operator==(const String & s) const {
+ return (strcmp(str, s.str) == 0);
+}
+
+bool String::operator<=(const String & s) const {
+ return (strcmp(str, s.str) <= 0);
+}
+
+bool String::operator>=(const String & s) const {
+ return (strcmp(str, s.str) >= 0);
+}
+
+bool String::operator<(const String & s) const {
+ return (strcmp(str, s.str) < 0);
+}
+
+bool String::operator>(const String & s) const {
+ return (strcmp(str, s.str) > 0);
+}
+
+size_t String::strlen() const {
+ return (siz);
+}
+
+char String::operator[](size_t i) const {
+ if (i >= siz) {
+ return 0;
+ } else {
+ return str[i];
+ }
+}
+
+ssize_t String::strchr(char c, size_t from) const {
+ for (size_t i = from; i < siz; i++) {
+ if (str[i] == c) return i;
+ }
+
+ return -1;
+}
+
+ssize_t String::strrchr(char c) const {
+ for (size_t i = siz - 1; i >= 0; i--) {
+ if (str[i] == c) return i;
+ }
+
+ return -1;
+}
+
+ssize_t String::strstr(const String & s) const {
+ char * p = ::strstr(str, s.str);
+
+ if (p) {
+ return p - str;
+ } else {
+ return -1;
+ }
+}
+
+int String::strchrcnt(char c) const {
+ size_t i, cnt = 0;
+ for (i = 0; i < siz; i++) {
+ if (str[i] == c) cnt++;
+ }
+
+ return cnt;
+}
+
+String String::to_sqldate(void) const {
+/* DD/MM/YYYY ==> YYYYMMMDD */
+ return (is_date() ? extract(6, 9) + extract(3, 4) + extract(0, 1) : "");
+}
+
+String String::to_sqltime(void) const {
+/* h:m ==> h * 60 + m */
+ int p = strchr(':');
+ return (is_time() ? String(extract(0, p - 1).to_int() * 60 + extract(p + 1).to_int()) : "");
+}
+
+String String::from_sqldate(void) const {
+/* YYYYMMDD ==> DD/MM/YYYY */
+ return ((strlen() == 8) && is_number() ? extract(6, 7) + '/' + extract(4, 5) + '/' + extract(0, 3) : "");
+}
+
+String String::from_sqltime(void) const {
+/* t ==> (t / 60):(t % 60) */
+ int t = to_int();
+ return (is_number() ? String((int) (t / 60)) + ':' + (t % 60) : "");
+}
+
+bool String::is_date(void) const {
+/* 'DD/MM/YYYY'
+ 0123456789 */
+
+ if (strlen() != 10) return false;
+ if ((str[2] != '/') || (str[5] != '/') ||
+ (!extract(0, 1).is_number()) ||
+ (!extract(3, 4).is_number()) ||
+ (!extract(6, 9).is_number())) {
+ return (isDateArgument(to_sqldate().str));
+ }
+
+ return true;
+}
+
+double String::datedif(const String & s) const {
+ double r;
+ if (is_date() && s.is_date()) {
+ r = dateCalc(str, s.str);
+ return r < 0 ? -r : r;
+ }
+
+ return -1;
+}
+
+bool String::is_number(void) const {
+ for (size_t i = ((str[0] == '-') ? 1 : 0); i < siz; i++) {
+ if ((str[i] > '9') || (str[i] < '0')) return false;
+ }
+ return true;
+}
+
+bool String::is_float(void) const {
+ bool seendot = false;
+
+ for (size_t i = ((str[0] == '-') ? 1 : 0); i < siz; i++) {
+ if ((str[i] > '9') || (str[i] < '0')) {
+ if ((str[i] == '.') && !seendot) {
+ seendot = true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool String::is_time(void) const {
+ int p = strchr(':');
+
+ if (p == -1) return false;
+
+ // On accepte les heures sous le format xxxxxx:yy pour pouvoir indiquer des durées.
+
+ if ((!extract(0, p - 1).is_number()) || (!extract(p + 1).is_number()))
+ return false;
+
+ return (extract(p + 1).to_int() < 60) ? true : false;
+}