#include "ZString.h" #include "Log.h" #include "Exception.h" #include #include namespace coreutils { std::ostream &operator<<(std::ostream &os, const ZString &zstring) { for (char *ix = zstring.data; ix < (zstring.data + zstring.length); ++ix) os << *ix; return os; } std::ostream &operator<<(std::ostream &os, const std::string &string) { os << string; return os; } std::ostream &operator+(std::ostream &os, const ZString &zstring) { os << zstring; return os; } std::ostream &operator+(std::ostream &os, const char *value) { os << value; return os; } ZString::ZString() { data = NULL; length = 0; cursor = data; } ZString::ZString(const char *data) { if((char *)data != NULL) { this->data = (char *)data; this->length = strlen(data); this->cursor = (char *)data; } else { this->data = NULL; this->length = 0; this->cursor = NULL; } } ZString::ZString(char *data, size_t length) : data(data), length(length), cursor(data) {} ZString::ZString(unsigned char *data, size_t length) : data((char *)data), length(length), cursor((char *)data) {} ZString::ZString(const char *data, size_t length) : data((char *)data), length(length), cursor((char *)data) {} ZString::ZString(const unsigned char *data, size_t length) : data((char *)data), length(length), cursor((char *)data) {} ZString::ZString(const ZString &zstring) { data = zstring.data; length = zstring.length; cursor = zstring.cursor; } ZString::ZString(std::string &data) { this->data = (char *)data.c_str(); length = data.length(); cursor = (char *)data.c_str(); } ZString::~ZString() { if(cdata != NULL) free(cdata); } bool ZString::operator<(const ZString &valuex) const { char *end1 = data + length; char *end2 = valuex.getData() + valuex.getLength(); char *cursor1 = cursor; char *cursor2 = valuex.getCursor(); while((cursor1 < end1) && (cursor2 < end2)) { if(*cursor1 < *cursor2) return 1; if(*cursor1 > *cursor2) return 0; ++cursor1; ++cursor2; } if((cursor1 == end1) && (cursor2 != end2)) return 1; if((cursor2 == end2) && (cursor1 != end1)) return 0; return 0; } // TODO: Fix the following comparison operators to handle the length problem appropriately. bool ZString::operator<=(const ZString &valuex) const { return (strncmp(data, valuex.data, valuex.length <= length ? valuex.length : length) <= 0); } bool ZString::operator>=(const ZString &valuex) const { return (strncmp(data, valuex.data, valuex.length <= length ? valuex.length : length) >= 0); } bool ZString::operator>(const ZString &valuex) const { return (strncmp(data, valuex.data, valuex.length <= length ? valuex.length : length) > 0); } bool ZString::operator==(const ZString valuex) { if(valuex.getLength() != length) return false; return (strncmp(data, valuex.data, length) == 0); } bool ZString::operator!=(const ZString valuex) const { if(length != valuex.getLength()) return true; return (strncmp(data, valuex.data, length) != 0); } bool ZString::operator!=(const char *valuex) const { if(strlen(valuex) != length) return true; return (strncmp(data, valuex, length) != 0); } std::vector &ZString::getList() { return list; } int ZString::asInteger() { int value = 0; bool negative = false; char *end = data + length; if(*cursor == '-') { negative = true; ++cursor; } else if(*cursor == '+') ++cursor; if(cursor == end) return 0; while((*cursor >= '0') && (*cursor <= '9')) { value *= 10; value += *cursor - 48; ++cursor; if(cursor == end) { if(negative) return -value; else return value; } } if(negative) return -value; return value; } double ZString::asDouble() { double value = 0; bool negative = false; char *end = data + length; if(*cursor == '-') { negative = true; ++cursor; } else if(*cursor == '+') ++cursor; if(cursor == end) return 0; while((*cursor >= '0') && (*cursor <= '9')) { value *= 10; value += *cursor - 48; ++cursor; if(cursor == end) { if(negative) return -value; else return value; } } if(*cursor != '.') { if(negative) return -value; else return value; } ++cursor; if(cursor == end) { if(negative) return -value; else return value; } double div = 10; while((*cursor >= '0') && (*cursor <= '9')) { value += (*cursor - 48) / div; div *= 10; ++cursor; if(cursor == end) { if(negative) return -value; else return value; } } if(negative) return -value; return value; } int ZString::incrementCursor(int length) { char *temp = cursor; if((cursor + length) > (data + this->length)) cursor = data + this->length; else cursor += length; return cursor - temp; } void ZString::push() { stack.push(cursor); } void ZString::pop() { cursor = stack.top(); stack.pop(); } std::string ZString::str() { return std::string(data, length); } std::string ZString::str(int len) { return std::string(data, len); } char* ZString::c_str() { if(cdata == NULL) cdata = (char *)malloc(length + 1); else cdata = (char *)realloc(cdata, length + 1); strncpy(cdata, data, length); cdata[length] = '\0'; return cdata; } ZString ZString::substring(int start) { char *end = data + length; char *startChar = data + start; if(startChar < end) { return ZString(startChar, end - startChar); } return ZString(); } ZString ZString::substring(int start, int len) { char *end = data + length; char *startChar = data + start; char *endChar = startChar + len; char newlen = endChar > end ? endChar - end: len; if(startChar < end) return ZString(startChar, newlen); return ZString(); } std::vector &ZString::split(std::string delimiter, size_t maxSize) { coreutils::ZString zDelimiter((char *)delimiter.c_str(), delimiter.size()); return split(zDelimiter, maxSize); } std::vector &ZString::split(ZString &delimiter, size_t maxSize) { list.clear(); if (length == 0) { list.push_back(ZString("")); return list; } maxSize = maxSize == 0 ? 255: maxSize; char *end = data + length; char *pos = cursor; while ((pos + delimiter.getLength()) <= end) { if ((strncmp(pos, delimiter.getData(), delimiter.getLength()) == 0) && (maxSize != 0)) { list.push_back(ZString(cursor, pos - cursor)); cursor = pos + delimiter.getLength(); pos = cursor; --maxSize; } else { ++pos; } } list.push_back(ZString(cursor, pos - cursor)); cursor = data; return list; } bool ZString::isCharacter(char ch, ZString include) { for (int ix = 0; ix < include.getLength(); ++ix) { if (ch == include.charAt(ix)) return true; } return false; } bool ZString::ifNextInclude(ZString include) { if((cursor <= (data + length)) && isCharacter(*cursor, include)) return true; return false; } ZString ZString::getTokenInclude(const char *include) { char *start = cursor; while ((cursor <= (data + length)) && isCharacter(*cursor, include)) ++cursor; return ZString(start, cursor - start); } ZString ZString::getTokenExclude(const char *exclude) { char previous = 0; char *start = cursor; do { while ((cursor < (data + length)) && !isCharacter(*cursor, exclude)) { previous = *cursor; ++cursor; } ++cursor; } while(previous == '\\'); --cursor; return ZString(start, cursor - start); } ZString ZString::getTokenExclude(std::string exclude) { return getTokenExclude(exclude.c_str()); } ZString ZString::getContainer() { char term = *cursor == '"' ? '"': *cursor == '(' ? ')': *cursor == '[' ? ']': *cursor == '{' ? '}': 0; if(!term) return ZString(); char *start = cursor; char nest = *cursor; char *end = cursor + length; int level = 0; ++cursor; while(cursor != end) { if(*cursor == term) { if(!level) { ++cursor; return ZString(start, cursor - start); } --level; } else if(*cursor == nest) { ++level; } ++cursor; } return ZString(); } ZString &ZString::operator[](int index) { return list[index]; } bool ZString::eod() { return cursor >= data + length; } int ZString::goeod() { char *temp = cursor; cursor = data + length; return cursor - temp; } bool ZString::startsWith(const char *value) { return strncmp(cursor, value, strlen(value)) == 0; } bool ZString::startsWithNumber() { return ((*cursor >= '0') && (*cursor <= '9')); } int ZString::compare(ZString zstring) { char *end1 = data + length; char *end2 = zstring.getData() + zstring.getLength(); char *cursor1 = cursor; char *cursor2 = zstring.getCursor(); while((cursor1 < end1) && (cursor2 < end2)) { if(*cursor1 < *cursor2) return -1; if(*cursor1 > *cursor2) return 1; ++cursor1; ++cursor2; } if((cursor1 == end1) && (cursor2 != end2)) return -1; if((cursor2 == end2) && (cursor1 != end1)) return 1; return 0; } bool ZString::equals(const char *value) { if (strlen(value) != length) return false; return strncmp(data, value, length) == 0; } bool ZString::equals(char *value) { if (strlen(value) != length) return false; return strncmp(data, value, length) == 0; } bool ZString::equals(ZString &zstring) { if (zstring.getLength() != length) return false; return strncmp(data, zstring.getData(), length) == 0; } bool ZString::equals(std::string &string) { return string == std::string(data, length); } bool ZString::ifNext(ZString value) { if (((data + length) - cursor) < value.getLength()) return false; bool test = (strncmp(cursor, value.getCursor(), value.getLength()) == 0); if (test) cursor += value.getLength(); return test; } bool ZString::ifNextIgnoreCase(ZString value) { if (((data + length) - cursor) < value.getLength()) return false; bool test = (strncasecmp(cursor, value.getCursor(), value.getLength()) == 0); if (test) cursor += value.getLength(); return test; } int ZString::ifEqualsCount(ZString &comparator) { int count = 0; while (cursor < (data + length)) { if (*cursor == *comparator.cursor) { ++count; ++cursor; ++comparator.cursor; } else { return count; } } return count; } int ZString::skipWhitespace() { char *end = data + length; int len = 0; while((cursor < end) && ((*cursor == ' ') || (*cursor == '\n') || (*cursor == '\t'))) { ++cursor; ++len; } return len; } int ZString::trimTrailingWhitespace() { goeod(); int len = 0; --cursor; while((cursor > data) && ((*cursor == ' ') || (*cursor == '\n') || (*cursor == '\t'))) { --cursor; --length; ++len; } ++cursor; return len; } bool ZString::lineIsWhitespace() { char *end = data + length; char *temp = cursor; while(temp < end) { if(*temp == '\n') return true; if((*temp != ' ') && (*temp != '\t')) return false; ++temp; } return true; } ZString ZString::goeol() { bool set = false; char *temp = cursor; char *tempend = data + length; while (cursor <= (data + length)) { if (*cursor == '\r') { tempend = cursor++; set = true; } if (*cursor == '\n') { if (!set) tempend = cursor; ++cursor; break; } ++cursor; } return ZString(temp, tempend - temp); } ZString ZString::goeolwithContinuation() { ZString temp = goeol(); while(ifNextInclude(" \t")) goeol(); return temp; } ZString ZString::trim() { trimTrailingWhitespace(); reset(); skipWhitespace(); return unparsed(); } int ZString::find(ZString comparator) { int count = 0; char *temp = cursor; char *temp2 = cursor; while(!ifNext(comparator)) { ++count; ++cursor; ++temp2; if(cursor > (data + length)) { cursor = temp; return -1; } } cursor = temp2; return count; } ZString ZString::readBlock(size_t size) { char *temp = cursor; cursor += size; return ZString(temp, size); } char *ZString::getData() const { return data; } char *ZString::getCursor() const { return cursor; } void ZString::setCursor(char *cursor) { if((cursor < data) || (cursor > (data + length))) throw Exception("Cursor out of range on setCursor."); this->cursor = cursor; } size_t ZString::getLength() const { return length - (cursor - data); } void ZString::setZString(ZString zstring) { data = zstring.getData(); length = zstring.getLength(); cursor = data; } ZString ZString::parsed() { return ZString(data, cursor - data); } ZString ZString::unparsed() { return ZString(cursor, data + length - cursor); } void ZString::reset() { cursor = data; } char ZString::charAt(int index) { return *(cursor + index); } bool ZString::trimCRLF() { int len = length; if (*(data + length - 1) == '\n') --length; if (*(data + length - 1) == '\r') --length; if (cursor >= (data + length)) cursor = data + length; return len != length; } bool ZString::boolValue() { if(this->equals("false")) return false; else if(this->equals("0")) return false; else if(this->equals("")) return false; return true; } ZString ZString::removeTrailingZeros() { if(length > 2) { while((*(data + length - 1)) == '0') --length; if(*(data + length - 1) == '.') --length; } return *this; } char ZString::nextChar() { char temp = 0; if(!eod()) temp = *cursor++; return temp; } int ZString::getLineNumberAtCursor() { char *temp = cursor; int line = 1; while(temp != data) if(*temp-- == '\n') ++line; return line; } void ZString::moveBackToLineStart() { while(cursor != data) { if(*cursor == '\n') { cursor++; break; } cursor--; } return; } }