int Luhn::Mod10(const AnyString& s) { // The string must have at least one char if (s.size() > 1) { // The algorithm : // 1 - Counting from the check digit, which is the rightmost, and moving // left, double the value of every second digit. // 2 - Sum the digits of the products together with the undoubled digits // from the original number. // 3 - If the total ends in 0 (put another way, if the total modulo 10 is // congruent to 0), then the number is valid according to the Luhn formula // static const int prefetch[] = {0, 2, 4, 6, 8, 1, 3, 5, 7, 9}; int sum = 0; bool alternate = true; const AnyString::iterator end = s.end(); // For each char for (AnyString::iterator i = s.begin(); end != i; ++i) { // Each char in the string must be a digit if (!String::IsDigit(i.value())) return false; // The `real` digit int n = i.value() - '0'; // Computing the sum sum += (alternate = !alternate) ? prefetch[n] : n; } return sum % 10; } return -1; }
DBI::Error Transaction::truncate(const AnyString& tablename) { if (YUNI_UNLIKELY(not IsValidIdentifier(tablename))) return errInvalidIdentifier; assert(!(!pChannel)); // the adapter ::yn_dbi_adapter& adapter = pChannel->adapter; // The DBI interface should provide the most appropriate way for // truncating a table (autoincrement / cascade...) if (YUNI_LIKELY(adapter.truncate)) { return (DBI::Error) adapter.truncate(adapter.dbh, tablename.c_str(), tablename.size()); } else { // Fallback to a failsafe method // -- stmt << "TRUNCATE " << tablename << ';'; // The SQL command Truncate is not supported by all databases. `DELETE FROM` // is not the most efficient way for truncating a table // but it should work almost everywhere String stmt; stmt << "DELETE FROM " << tablename << ';'; return perform(stmt); } }
Cursor Transaction::prepare(const AnyString& stmt) { assert(!(!pChannel)); // the adapter ::yn_dbi_adapter& adapter = pChannel->adapter; if (YUNI_UNLIKELY(nullHandle == pTxHandle)) { if (errNone != pChannel->begin(pTxHandle)) return Cursor(adapter, nullptr); } // query handle void* handle = nullptr; if (YUNI_LIKELY(not stmt.empty() and adapter.dbh)) { assert(adapter.query_new != NULL and "invalid adapter query_new"); assert(adapter.query_ref_acquire != NULL and "invalid adapter query_ref_acquire"); assert(adapter.query_ref_release != NULL and "invalid adapter query_ref_release"); adapter.query_new(&handle, adapter.dbh, stmt.c_str(), stmt.size()); } return Cursor(adapter, handle); }
Yuni::IO::NodeType TypeOf(const AnyString& filename) { if (filename.empty()) return Yuni::IO::typeUnknown; # ifdef YUNI_OS_WINDOWS const char* p = filename.c_str(); unsigned int len = filename.size(); if (p[len - 1] == '\\' or p[len - 1] == '/') { if (!--len) { # ifdef YUNI_OS_WINDOWS return Yuni::IO::typeUnknown; # else // On Unixes, `/` is a valid folder return Yuni::IO::typeFolder; # endif } } // Driver letters if (len == 2 and p[1] == ':') return Yuni::IO::typeFolder; String norm; Yuni::IO::Normalize(norm, AnyString(p, len)); // Conversion into wchar_t Private::WString<true> wstr(norm); if (wstr.empty()) return Yuni::IO::typeUnknown; WIN32_FILE_ATTRIBUTE_DATA infoFile; if (!GetFileAttributesExW(wstr.c_str(), GetFileExInfoStandard, &infoFile)) return Yuni::IO::typeUnknown; return ((infoFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) ? Yuni::IO::typeFolder : Yuni::IO::typeFile; # else // WINDOWS struct stat s; if (stat(filename.c_str(), &s) != 0) return Yuni::IO::typeUnknown; return (S_ISDIR(s.st_mode)) ? Yuni::IO::typeFolder : Yuni::IO::typeFile; # endif }
DBI::Error Transaction::perform(const AnyString& script) { assert(!(!pChannel)); // the adapter ::yn_dbi_adapter& adapter = pChannel->adapter; assert(adapter.query_exec != NULL); if (YUNI_LIKELY(nullHandle != pTxHandle)) { return (DBI::Error) adapter.query_exec(adapter.dbh, script.c_str(), script.size()); } else { // start a new transaction DBI::Error error = pChannel->begin(pTxHandle); if (YUNI_LIKELY(error == errNone)) error = (DBI::Error) adapter.query_exec(adapter.dbh, script.c_str(), script.size()); return error; } }
bool Size(const AnyString& filename, uint64& value) { unsigned int len = filename.size(); if (!len) { value = 0u; return false; } const char* const p = filename.c_str(); if (p[len - 1] == '\\' || p[len - 1] == '/') --len; // Driver letters if (len == 2 && p[1] == ':') { value = 0u; return true; } String norm; Yuni::IO::Normalize(norm, p, len); // Conversion into wchar_t Private::WString<true> wstr(norm); if (wstr.empty()) { value = 0u; return false; } HANDLE hndl = CreateFileW(wstr.c_str(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hndl == INVALID_HANDLE_VALUE) { value = 0u; return false; } LARGE_INTEGER v; if (!GetFileSizeEx(hndl, &v)) { CloseHandle(hndl); value = 0u; return false; } value = (uint64) v.QuadPart; CloseHandle(hndl); return true; }
Yuni::IO::Error Delete(const AnyString& filename) { // DeleteFile is actually a macro and will be replaced by DeleteFileW // with Visual Studio. Consequently we can not use the word DeleteFile..... if (filename.empty()) return Yuni::IO::errUnknown; # ifndef YUNI_OS_WINDOWS return (unlink(filename.c_str())) ? Yuni::IO::errUnknown : Yuni::IO::errNone; # else const char* const p = filename.c_str(); uint len = filename.size(); if (p[len - 1] == '\\' or p[len - 1] == '/') --len; // Driver letters if (len == 2 and p[1] == ':') return Yuni::IO::errBadFilename; String norm; Yuni::IO::Normalize(norm, AnyString(p, len)); // Conversion into wchar_t WString wstr(norm, true); if (wstr.empty()) return Yuni::IO::errUnknown; wstr.replace('/', '\\'); return (DeleteFileW(wstr.c_str())) ? Yuni::IO::errNone : Yuni::IO::errUnknown; # endif }
static bool UnixMake(const AnyString& path, uint mode) { const uint len = path.size(); char* buffer = new char[len + 1]; YUNI_MEMCPY(buffer, len, path.c_str(), len); buffer[len] = '\0'; char* pt = buffer; char tmp; do { if ('\\' == *pt or '/' == *pt or '\0' == *pt) { tmp = *pt; *pt = '\0'; if ('\0' != buffer[0] and '\0' != buffer[1] and '\0' != buffer[2]) { if (mkdir(buffer, static_cast<mode_t>(mode)) < 0) { if (errno != EEXIST and errno != EISDIR and errno != ENOSYS) { delete[] buffer; return false; } } } if ('\0' == tmp) break; *pt = tmp; } ++pt; } while (true); delete[] buffer; return true; }
EventPropagation TextEditor::charInput(const AnyString& str) { switch (str[0]) { // Backspace case 0x08: for (uint i = 0; i < str.size(); ++i) { // Cannot use backspace when at beginning of file if (0 == pCursorPos.y && 1 == pCursorPos.x) return epStop; // When at beginning of line but not on first line, move up if (0 == pCursorPos.y && pCursorPos.x > 1) cursorPos(pCursorPos.x - 1, columnCount(pCursorPos.x - 1)); else cursorPos(pCursorPos.x, pCursorPos.y - 1); // Erase pText.erase(cursorToByte(pCursorPos), 1); } invalidate(); break; // Space case ' ': pText.insert(cursorToByte(pCursorPos), str); pCursorPos.x += str.size(); invalidate(); break; // Tab case '\t': pText.insert(cursorToByte(pCursorPos), str); cursorPos(pCursorPos.x, pCursorPos.y + str.size() * pTabWidth); invalidate(); break; // Carriage Return case '\r': // New Line / Line Feed case '\n': for (uint i = 0; i < str.size(); ++i) pText.insert(cursorToByte(pCursorPos), '\n'); pCursorPos.y += str.size(); invalidate(); break; // Normal displayable characters default: // Normal ASCII if ((uint8)str[0] < 0x80) { // Non-displayable characters are ignored std::locale loc; if (!std::isgraph(str[0], loc)) break; } pText.insert(cursorToByte(pCursorPos), str); // Advance the cursor pCursorPos.x += str.utf8size(); invalidate(); break; } return epStop; }
static bool DecodeURLQuery(KeyValueStore& params, const AnyString& query) { // note: mongoose does not provide the fragment here, so we don't have // to check it // Some tests are already done before calling this method assert(not query.empty()); String key; // temporary string for parameters handling uint offset = 0; uint start = 0; AnyString value; do { offset = query.find_first_of("=&", offset); if (offset >= query.size()) { // ignoring fields with empty value (using default) break; } if (query[offset] == '=') { key.assign(query, offset - start, start); if (key.empty()) // malformed url. aborting return false; ++offset; // FIXME !!!! & are not properly handled !!!!!!!!!!!! uint ampersand = offset; ampersand = query.find('&', ampersand); if (ampersand >= query.size()) { value.adapt(query, query.size() - offset, offset); ampersand = query.size(); } else value.adapt(query, ampersand - offset, offset); if (not value.empty()) { KeyValueStore::iterator i = params.find(key); if (i != params.end()) { // the item has been found ! params[key] = value; } } offset = ampersand; } else { // ignoring fields with empty value (using default) } // updating offsets start = ++offset; } while (true); return true; }
void WString::prepareWString(const AnyString& string, bool uncprefix) { if (string.empty()) { if (uncprefix) { pSize = 4; pWString = (wchar_t*)::realloc(pWString, sizeof(wchar_t) * 5); pWString[0] = L'\\'; pWString[1] = L'\\'; pWString[2] = L'?'; pWString[3] = L'\\'; pWString[4] = L'\0'; } else clear(); return; } if (string.size() > INT_MAX) { clear(); return; } // Offset according to the presence of the UNC prefix const uint offset = (not uncprefix) ? 0 : 4; #ifdef YUNI_OS_WINDOWS { // Allocate and convert the C-String. Several iterations may be required // for allocating enough room for the conversion. const int sizeRequired = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.size(), nullptr, 0); if (sizeRequired <= 0) { clear(); return; } pSize = sizeRequired + offset; pWString = (wchar_t*) realloc(pWString, sizeof(wchar_t) * (pSize + 1)); if (nullptr == pWString) // Impossible to allocate the buffer. Aborting. { clear(); return; } // Converting into Wide String const int n = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), static_cast<int>(string.size()), pWString + offset, static_cast<int>(pSize - offset)); if (n != sizeRequired) { assert(false and "most likely an error"); clear(); return; } } #else { const char* wcstr = string.c_str(); mbstate_t state; memset (&state, '\0', sizeof (state)); size_t sizeRequired = mbsnrtowcs(nullptr, &wcstr, string.size(), 0, &state); if (0 == sizeRequired or (size_t) -1 == sizeRequired) { clear(); return; } pSize = sizeRequired + offset; pWString = (wchar_t*) realloc(pWString, sizeof(wchar_t) * (pSize + 1)); if (nullptr == pWString) // Impossible to allocate the buffer. Aborting. { clear(); return; } memset (&state, '\0', sizeof (state)); size_t written = mbsnrtowcs(pWString + offset, &wcstr, string.size(), pSize - offset, &state); if (0 == written or (size_t) -1 == written) { clear(); return; } } #endif // prepend the Windows UNC prefix if (uncprefix) { pWString[0] = L'\\'; pWString[1] = L'\\'; pWString[2] = L'?'; pWString[3] = L'\\'; } // always ensure that the string is zero terminated pWString[pSize] = L'\0'; }
bool Resize(const AnyString& filename, uint64_t size) { if (not filename.empty()) { if (size < std::numeric_limits<off_t>::max()) { #ifndef YUNI_OS_WINDOWS { assert((filename.c_str())[filename.size()] == '\0'); #ifdef YUNI_OS_MAC int fd = open(filename.c_str(), O_WRONLY|O_CREAT, 0644); #else int fd = open(filename.c_str(), O_WRONLY|O_CREAT|O_LARGEFILE, 0644); #endif if (fd != -1) { bool success = (0 == ftruncate(fd, static_cast<off_t>(size))); close(fd); return success; } } #else { WString wstr(filename, true); if (not wstr.empty()) { HANDLE hndl = CreateFileW(wstr.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hndl) { LARGE_INTEGER li; li.QuadPart = size; DWORD dwPtr = SetFilePointer(hndl, li.LowPart, &li.HighPart, FILE_BEGIN); if (dwPtr != INVALID_SET_FILE_POINTER) SetEndOfFile(hndl); CloseHandle(hndl); return true; } } } #endif } } return false; }