From 265d57651037c02964a9fc7e7bc58a854b2d2ad1 Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Tue, 28 Jun 2016 01:10:55 +0530 Subject: [PATCH 1/6] Replace GPL licensed C/C++ samples --- samples/C++/PackageInfoParser.cpp | 1178 +++++++++++++++++++++++++++++ samples/C++/bcm2835.h | 1129 --------------------------- samples/C++/crypter.cpp | 123 +++ samples/C++/graphics.cpp | 109 +++ samples/C++/json_reader.cpp | 920 ++++++++++++++++++++++ samples/C++/json_writer.cpp | 857 +++++++++++++++++++++ samples/C++/qscicommand.h | 415 ---------- samples/C++/qsciprinter.cp | 116 --- samples/C++/qsciprinter.h | 116 --- samples/C++/srs_app_ingest.cpp | 557 ++++++++++++++ 10 files changed, 3744 insertions(+), 1776 deletions(-) create mode 100644 samples/C++/PackageInfoParser.cpp delete mode 100644 samples/C++/bcm2835.h create mode 100644 samples/C++/crypter.cpp create mode 100644 samples/C++/graphics.cpp create mode 100644 samples/C++/json_reader.cpp create mode 100644 samples/C++/json_writer.cpp delete mode 100644 samples/C++/qscicommand.h delete mode 100644 samples/C++/qsciprinter.cp delete mode 100644 samples/C++/qsciprinter.h create mode 100644 samples/C++/srs_app_ingest.cpp diff --git a/samples/C++/PackageInfoParser.cpp b/samples/C++/PackageInfoParser.cpp new file mode 100644 index 00000000..c6c23048 --- /dev/null +++ b/samples/C++/PackageInfoParser.cpp @@ -0,0 +1,1178 @@ +/* + * Copyright 2011, Oliver Tappe + * Copyright 2016, Andrew Lindesay + * Distributed under the terms of the MIT License. + * + * Source - https://github.com/haiku/haiku/blob/73e180c9b965aaeb034055453e153bc3adf47917/src/kits/package/PackageInfoParser.cpp + */ + + +#include "PackageInfoParser.h" + +#include +#include +#include + +#include +#include + +#include + +namespace BPackageKit { + + +BPackageInfo::ParseErrorListener::~ParseErrorListener() +{ +} + + +BPackageInfo::Parser::Parser(ParseErrorListener* listener) + : + fListener(listener), + fPos(NULL) +{ +} + + +status_t +BPackageInfo::Parser::Parse(const BString& packageInfoString, + BPackageInfo* packageInfo) +{ + if (packageInfo == NULL) + return B_BAD_VALUE; + + fPos = packageInfoString.String(); + + try { + _Parse(packageInfo); + } catch (const ParseError& error) { + if (fListener != NULL) { + // map error position to line and column + int line = 1; + int inLineOffset; + int32 offset = error.pos - packageInfoString.String(); + int32 newlinePos = packageInfoString.FindLast('\n', offset - 1); + if (newlinePos < 0) + inLineOffset = offset; + else { + inLineOffset = offset - newlinePos - 1; + do { + line++; + newlinePos = packageInfoString.FindLast('\n', + newlinePos - 1); + } while (newlinePos >= 0); + } + + int column = 0; + for (int i = 0; i < inLineOffset; i++) { + column++; + if (error.pos[i - inLineOffset] == '\t') + column = (column + 3) / 4 * 4; + } + + fListener->OnError(error.message, line, column + 1); + } + return B_BAD_DATA; + } catch (const std::bad_alloc& e) { + if (fListener != NULL) + fListener->OnError("out of memory", 0, 0); + return B_NO_MEMORY; + } + + return B_OK; +} + + +status_t +BPackageInfo::Parser::ParseVersion(const BString& versionString, + bool revisionIsOptional, BPackageVersion& _version) +{ + fPos = versionString.String(); + + try { + Token token(TOKEN_STRING, fPos, versionString.Length()); + _ParseVersionValue(token, &_version, revisionIsOptional); + } catch (const ParseError& error) { + if (fListener != NULL) { + int32 offset = error.pos - versionString.String(); + fListener->OnError(error.message, 1, offset); + } + return B_BAD_DATA; + } catch (const std::bad_alloc& e) { + if (fListener != NULL) + fListener->OnError("out of memory", 0, 0); + return B_NO_MEMORY; + } + + return B_OK; +} + + +status_t +BPackageInfo::Parser::ParseResolvableExpression(const BString& expressionString, + BPackageResolvableExpression& _expression) +{ + fPos = expressionString.String(); + + try { + Token token(TOKEN_STRING, fPos, expressionString.Length()); + _ParseResolvableExpression(_NextToken(), _expression, NULL); + } catch (const ParseError& error) { + if (fListener != NULL) { + int32 offset = error.pos - expressionString.String(); + fListener->OnError(error.message, 1, offset); + } + return B_BAD_DATA; + } catch (const std::bad_alloc& e) { + if (fListener != NULL) + fListener->OnError("out of memory", 0, 0); + return B_NO_MEMORY; + } + + return B_OK; +} + + +BPackageInfo::Parser::Token +BPackageInfo::Parser::_NextToken() +{ + // Eat any whitespace, comments, or escaped new lines. Also eat ';' -- they + // have the same function as newlines. We remember the last encountered ';' + // or '\n' and return it as a token afterwards. + const char* itemSeparatorPos = NULL; + bool inComment = false; + while ((inComment && *fPos != '\0') || isspace(*fPos) || *fPos == ';' + || *fPos == '#' || *fPos == '\\') { + if (*fPos == '#') { + inComment = true; + } else if (!inComment && *fPos == '\\') { + if (fPos[1] != '\n') + break; + // ignore escaped line breaks + fPos++; + } else if (*fPos == '\n') { + itemSeparatorPos = fPos; + inComment = false; + } else if (!inComment && *fPos == ';') + itemSeparatorPos = fPos; + fPos++; + } + + if (itemSeparatorPos != NULL) { + return Token(TOKEN_ITEM_SEPARATOR, itemSeparatorPos); + } + + const char* tokenPos = fPos; + switch (*fPos) { + case '\0': + return Token(TOKEN_EOF, fPos); + + case '{': + fPos++; + return Token(TOKEN_OPEN_BRACE, tokenPos); + + case '}': + fPos++; + return Token(TOKEN_CLOSE_BRACE, tokenPos); + + case '<': + fPos++; + if (*fPos == '=') { + fPos++; + return Token(TOKEN_OPERATOR_LESS_EQUAL, tokenPos, 2); + } + return Token(TOKEN_OPERATOR_LESS, tokenPos, 1); + + case '=': + fPos++; + if (*fPos == '=') { + fPos++; + return Token(TOKEN_OPERATOR_EQUAL, tokenPos, 2); + } + return Token(TOKEN_OPERATOR_ASSIGN, tokenPos, 1); + + case '!': + if (fPos[1] == '=') { + fPos += 2; + return Token(TOKEN_OPERATOR_NOT_EQUAL, tokenPos, 2); + } + break; + + case '>': + fPos++; + if (*fPos == '=') { + fPos++; + return Token(TOKEN_OPERATOR_GREATER_EQUAL, tokenPos, 2); + } + return Token(TOKEN_OPERATOR_GREATER, tokenPos, 1); + + default: + { + std::string string; + char quoteChar = '\0'; + + for (; *fPos != '\0'; fPos++) { + char c = *fPos; + if (quoteChar != '\0') { + // within a quoted string segment + if (c == quoteChar) { + quoteChar = '\0'; + continue; + } + + if (c == '\\') { + // next char is escaped + c = *++fPos; + if (c == '\0') { + throw ParseError("unterminated quoted-string", + tokenPos); + } + + if (c == 'n') + c = '\n'; + else if (c == 't') + c = '\t'; + } + + string += c; + } else { + // unquoted string segment + switch (c) { + case '"': + case '\'': + // quoted string start + quoteChar = c; + continue; + + case '{': + case '}': + case '<': + case '=': + case '!': + case '>': + // a separator character -- this ends the string + break; + + case '\\': + // next char is escaped + c = *++fPos; + if (c == '\0') { + throw ParseError("'\\' at end of string", + tokenPos); + } + string += c; + continue; + + default: + if (isspace(c)) + break; + string += c; + continue; + } + + break; + } + } + + return Token(TOKEN_STRING, tokenPos, fPos - tokenPos, + string.c_str()); + } + } + + BString error = BString("unknown token '") << *fPos << "' encountered"; + throw ParseError(error.String(), fPos); +} + + +void +BPackageInfo::Parser::_RewindTo(const Token& token) +{ + fPos = token.pos; +} + + +void +BPackageInfo::Parser::_ParseStringValue(BString* value, const char** _tokenPos) +{ + Token string = _NextToken(); + if (string.type != TOKEN_STRING) + throw ParseError("expected string", string.pos); + + *value = string.text; + if (_tokenPos != NULL) + *_tokenPos = string.pos; +} + + +void +BPackageInfo::Parser::_ParseArchitectureValue(BPackageArchitecture* value) +{ + Token arch = _NextToken(); + if (arch.type == TOKEN_STRING) { + for (int i = 0; i < B_PACKAGE_ARCHITECTURE_ENUM_COUNT; ++i) { + if (arch.text.ICompare(BPackageInfo::kArchitectureNames[i]) == 0) { + *value = (BPackageArchitecture)i; + return; + } + } + } + + BString error("architecture must be one of: ["); + for (int i = 0; i < B_PACKAGE_ARCHITECTURE_ENUM_COUNT; ++i) { + if (i > 0) + error << ","; + error << BPackageInfo::kArchitectureNames[i]; + } + error << "]"; + throw ParseError(error, arch.pos); +} + + +void +BPackageInfo::Parser::_ParseVersionValue(BPackageVersion* value, + bool revisionIsOptional) +{ + Token word = _NextToken(); + _ParseVersionValue(word, value, revisionIsOptional); +} + + +/*static*/ void +BPackageInfo::Parser::_ParseVersionValue(Token& word, BPackageVersion* value, + bool revisionIsOptional) +{ + if (word.type != TOKEN_STRING) + throw ParseError("expected string (a version)", word.pos); + + // get the revision number + uint32 revision = 0; + int32 dashPos = word.text.FindLast('-'); + if (dashPos >= 0) { + char* end; + long long number = strtoll(word.text.String() + dashPos + 1, &end, + 0); + if (*end != '\0' || number < 0 || number > UINT_MAX) { + throw ParseError("revision must be a number > 0 and < UINT_MAX", + word.pos + dashPos + 1); + } + + revision = (uint32)number; + word.text.Truncate(dashPos); + } + + if (revision == 0 && !revisionIsOptional) { + throw ParseError("expected revision number (- suffix)", + word.pos + word.text.Length()); + } + + // get the pre-release string + BString preRelease; + int32 tildePos = word.text.FindLast('~'); + if (tildePos >= 0) { + word.text.CopyInto(preRelease, tildePos + 1, + word.text.Length() - tildePos - 1); + word.text.Truncate(tildePos); + + if (preRelease.IsEmpty()) { + throw ParseError("invalid empty pre-release string", + word.pos + tildePos + 1); + } + + int32 errorPos; + if (!_IsAlphaNumUnderscore(preRelease, ".", &errorPos)) { + throw ParseError("invalid character in pre-release string", + word.pos + tildePos + 1 + errorPos); + } + } + + // get major, minor, and micro strings + BString major; + BString minor; + BString micro; + int32 firstDotPos = word.text.FindFirst('.'); + if (firstDotPos < 0) + major = word.text; + else { + word.text.CopyInto(major, 0, firstDotPos); + int32 secondDotPos = word.text.FindFirst('.', firstDotPos + 1); + if (secondDotPos == firstDotPos + 1) + throw ParseError("expected minor version", word.pos + secondDotPos); + + if (secondDotPos < 0) { + word.text.CopyInto(minor, firstDotPos + 1, word.text.Length()); + } else { + word.text.CopyInto(minor, firstDotPos + 1, + secondDotPos - (firstDotPos + 1)); + word.text.CopyInto(micro, secondDotPos + 1, word.text.Length()); + + int32 errorPos; + if (!_IsAlphaNumUnderscore(micro, ".", &errorPos)) { + throw ParseError("invalid character in micro version string", + word.pos + secondDotPos + 1 + errorPos); + } + } + + int32 errorPos; + if (!_IsAlphaNumUnderscore(minor, "", &errorPos)) { + throw ParseError("invalid character in minor version string", + word.pos + firstDotPos + 1 + errorPos); + } + } + + int32 errorPos; + if (!_IsAlphaNumUnderscore(major, "", &errorPos)) { + throw ParseError("invalid character in major version string", + word.pos + errorPos); + } + + value->SetTo(major, minor, micro, preRelease, revision); +} + + +void +BPackageInfo::Parser::_ParseResolvableExpression(const Token& token, + BPackageResolvableExpression& _value, BString* _basePackage) +{ + if (token.type != TOKEN_STRING) { + throw ParseError("expected word (a resolvable name)", + token.pos); + } + + int32 errorPos; + if (!_IsValidResolvableName(token.text, &errorPos)) { + throw ParseError("invalid character in resolvable name", + token.pos + errorPos); + } + + BPackageVersion version; + Token op = _NextToken(); + BPackageResolvableOperator resolvableOperator; + if (op.type == TOKEN_OPERATOR_LESS + || op.type == TOKEN_OPERATOR_LESS_EQUAL + || op.type == TOKEN_OPERATOR_EQUAL + || op.type == TOKEN_OPERATOR_NOT_EQUAL + || op.type == TOKEN_OPERATOR_GREATER_EQUAL + || op.type == TOKEN_OPERATOR_GREATER) { + _ParseVersionValue(&version, true); + + if (_basePackage != NULL) { + Token base = _NextToken(); + if (base.type == TOKEN_STRING && base.text == "base") { + if (!_basePackage->IsEmpty()) { + throw ParseError("multiple packages marked as base package", + token.pos); + } + + *_basePackage = token.text; + } else + _RewindTo(base); + } + + resolvableOperator = (BPackageResolvableOperator) + (op.type - TOKEN_OPERATOR_LESS); + } else if (op.type == TOKEN_ITEM_SEPARATOR + || op.type == TOKEN_CLOSE_BRACE || op.type == TOKEN_EOF) { + _RewindTo(op); + resolvableOperator = B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT; + } else { + throw ParseError( + "expected '<', '<=', '==', '!=', '>=', '>', comma or '}'", + op.pos); + } + + _value.SetTo(token.text, resolvableOperator, version); +} + + +void +BPackageInfo::Parser::_ParseList(ListElementParser& elementParser, + bool allowSingleNonListElement) +{ + Token openBracket = _NextToken(); + if (openBracket.type != TOKEN_OPEN_BRACE) { + if (!allowSingleNonListElement) + throw ParseError("expected start of list ('{')", openBracket.pos); + + elementParser(openBracket); + return; + } + + while (true) { + Token token = _NextToken(); + if (token.type == TOKEN_CLOSE_BRACE) + return; + + if (token.type == TOKEN_ITEM_SEPARATOR) + continue; + + elementParser(token); + } +} + + +void +BPackageInfo::Parser::_ParseStringList(BStringList* value, + bool requireResolvableName, bool convertToLowerCase, + StringValidator* stringValidator) +{ + struct StringParser : public ListElementParser { + BStringList* value; + bool requireResolvableName; + bool convertToLowerCase; + StringValidator* stringValidator; + + StringParser(BStringList* value, bool requireResolvableName, + bool convertToLowerCase, StringValidator* stringValidator) + : + value(value), + requireResolvableName(requireResolvableName), + convertToLowerCase(convertToLowerCase), + stringValidator(stringValidator) + { + } + + virtual void operator()(const Token& token) + { + if (token.type != TOKEN_STRING) + throw ParseError("expected string", token.pos); + + if (requireResolvableName) { + int32 errorPos; + if (!_IsValidResolvableName(token.text, &errorPos)) { + throw ParseError("invalid character in resolvable name", + token.pos + errorPos); + } + } + + BString element(token.text); + if (convertToLowerCase) + element.ToLower(); + + if (stringValidator != NULL) + stringValidator->Validate(element, token.pos); + + value->Add(element); + } + } stringParser(value, requireResolvableName, convertToLowerCase, + stringValidator); + + _ParseList(stringParser, true); +} + + +uint32 +BPackageInfo::Parser::_ParseFlags() +{ + struct FlagParser : public ListElementParser { + uint32 flags; + + FlagParser() + : + flags(0) + { + } + + virtual void operator()(const Token& token) + { + if (token.type != TOKEN_STRING) + throw ParseError("expected word (a flag)", token.pos); + + if (token.text.ICompare("approve_license") == 0) + flags |= B_PACKAGE_FLAG_APPROVE_LICENSE; + else if (token.text.ICompare("system_package") == 0) + flags |= B_PACKAGE_FLAG_SYSTEM_PACKAGE; + else { + throw ParseError( + "expected 'approve_license' or 'system_package'", + token.pos); + } + } + } flagParser; + + _ParseList(flagParser, true); + + return flagParser.flags; +} + + +void +BPackageInfo::Parser::_ParseResolvableList( + BObjectList* value) +{ + struct ResolvableParser : public ListElementParser { + Parser& parser; + BObjectList* value; + + ResolvableParser(Parser& parser_, + BObjectList* value_) + : + parser(parser_), + value(value_) + { + } + + virtual void operator()(const Token& token) + { + if (token.type != TOKEN_STRING) { + throw ParseError("expected word (a resolvable name)", + token.pos); + } + + int32 errorPos; + if (!_IsValidResolvableName(token.text, &errorPos)) { + throw ParseError("invalid character in resolvable name", + token.pos + errorPos); + } + + // parse version + BPackageVersion version; + Token op = parser._NextToken(); + if (op.type == TOKEN_OPERATOR_ASSIGN) { + parser._ParseVersionValue(&version, true); + } else if (op.type == TOKEN_ITEM_SEPARATOR + || op.type == TOKEN_CLOSE_BRACE) { + parser._RewindTo(op); + } else + throw ParseError("expected '=', comma or '}'", op.pos); + + // parse compatible version + BPackageVersion compatibleVersion; + Token compatible = parser._NextToken(); + if (compatible.type == TOKEN_STRING + && (compatible.text == "compat" + || compatible.text == "compatible")) { + op = parser._NextToken(); + if (op.type == TOKEN_OPERATOR_GREATER_EQUAL) { + parser._ParseVersionValue(&compatibleVersion, true); + } else + parser._RewindTo(compatible); + } else + parser._RewindTo(compatible); + + value->AddItem(new BPackageResolvable(token.text, version, + compatibleVersion)); + } + } resolvableParser(*this, value); + + _ParseList(resolvableParser, false); +} + + +void +BPackageInfo::Parser::_ParseResolvableExprList( + BObjectList* value, BString* _basePackage) +{ + struct ResolvableExpressionParser : public ListElementParser { + Parser& parser; + BObjectList* value; + BString* basePackage; + + ResolvableExpressionParser(Parser& parser, + BObjectList* value, + BString* basePackage) + : + parser(parser), + value(value), + basePackage(basePackage) + { + } + + virtual void operator()(const Token& token) + { + BPackageResolvableExpression expression; + parser._ParseResolvableExpression(token, expression, basePackage); + value->AddItem(new BPackageResolvableExpression(expression)); + } + } resolvableExpressionParser(*this, value, _basePackage); + + _ParseList(resolvableExpressionParser, false); +} + + +void +BPackageInfo::Parser::_ParseGlobalWritableFileInfos( + GlobalWritableFileInfoList* infos) +{ + struct GlobalWritableFileInfoParser : public ListElementParser { + Parser& parser; + GlobalWritableFileInfoList* infos; + + GlobalWritableFileInfoParser(Parser& parser, + GlobalWritableFileInfoList* infos) + : + parser(parser), + infos(infos) + { + } + + virtual void operator()(const Token& token) + { + if (token.type != TOKEN_STRING) { + throw ParseError("expected string (a file path)", + token.pos); + } + + BWritableFileUpdateType updateType + = B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT; + bool isDirectory = false; + + Token nextToken = parser._NextToken(); + if (nextToken.type == TOKEN_STRING + && nextToken.text == "directory") { + isDirectory = true; + nextToken = parser._NextToken(); + } + + if (nextToken.type == TOKEN_STRING) { + const char* const* end = kWritableFileUpdateTypes + + B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT; + const char* const* found = std::find(kWritableFileUpdateTypes, + end, nextToken.text); + if (found == end) { + throw ParseError(BString("expected an update type"), + nextToken.pos); + } + updateType = (BWritableFileUpdateType)( + found - kWritableFileUpdateTypes); + } else if (nextToken.type == TOKEN_ITEM_SEPARATOR + || nextToken.type == TOKEN_CLOSE_BRACE) { + parser._RewindTo(nextToken); + } else { + throw ParseError( + "expected 'included', semicolon, new line or '}'", + nextToken.pos); + } + + if (!infos->AddItem(new BGlobalWritableFileInfo(token.text, + updateType, isDirectory))) { + throw std::bad_alloc(); + } + } + } resolvableExpressionParser(*this, infos); + + _ParseList(resolvableExpressionParser, false); +} + + +void +BPackageInfo::Parser::_ParseUserSettingsFileInfos( + UserSettingsFileInfoList* infos) +{ + struct UserSettingsFileInfoParser : public ListElementParser { + Parser& parser; + UserSettingsFileInfoList* infos; + + UserSettingsFileInfoParser(Parser& parser, + UserSettingsFileInfoList* infos) + : + parser(parser), + infos(infos) + { + } + + virtual void operator()(const Token& token) + { + if (token.type != TOKEN_STRING) { + throw ParseError("expected string (a settings file path)", + token.pos); + } + + BString templatePath; + bool isDirectory = false; + + Token nextToken = parser._NextToken(); + if (nextToken.type == TOKEN_STRING + && nextToken.text == "directory") { + isDirectory = true; + } else if (nextToken.type == TOKEN_STRING + && nextToken.text == "template") { + nextToken = parser._NextToken(); + if (nextToken.type != TOKEN_STRING) { + throw ParseError( + "expected string (a settings template file path)", + nextToken.pos); + } + templatePath = nextToken.text; + } else if (nextToken.type == TOKEN_ITEM_SEPARATOR + || nextToken.type == TOKEN_CLOSE_BRACE) { + parser._RewindTo(nextToken); + } else { + throw ParseError( + "expected 'template', semicolon, new line or '}'", + nextToken.pos); + } + + if (isDirectory + ? !infos->AddItem(new BUserSettingsFileInfo(token.text, true)) + : !infos->AddItem(new BUserSettingsFileInfo(token.text, + templatePath))) { + throw std::bad_alloc(); + } + } + } resolvableExpressionParser(*this, infos); + + _ParseList(resolvableExpressionParser, false); +} + + +void +BPackageInfo::Parser::_ParseUsers(UserList* users) +{ + struct UserParser : public ListElementParser { + Parser& parser; + UserList* users; + + UserParser(Parser& parser, UserList* users) + : + parser(parser), + users(users) + { + } + + virtual void operator()(const Token& token) + { + if (token.type != TOKEN_STRING + || !BUser::IsValidUserName(token.text)) { + throw ParseError("expected a user name", token.pos); + } + + BString realName; + BString home; + BString shell; + BStringList groups; + + for (;;) { + Token nextToken = parser._NextToken(); + if (nextToken.type != TOKEN_STRING) { + parser._RewindTo(nextToken); + break; + } + + if (nextToken.text == "real-name") { + nextToken = parser._NextToken(); + if (nextToken.type != TOKEN_STRING) { + throw ParseError("expected string (a user real name)", + nextToken.pos); + } + realName = nextToken.text; + } else if (nextToken.text == "home") { + nextToken = parser._NextToken(); + if (nextToken.type != TOKEN_STRING) { + throw ParseError("expected string (a home path)", + nextToken.pos); + } + home = nextToken.text; + } else if (nextToken.text == "shell") { + nextToken = parser._NextToken(); + if (nextToken.type != TOKEN_STRING) { + throw ParseError("expected string (a shell path)", + nextToken.pos); + } + shell = nextToken.text; + } else if (nextToken.text == "groups") { + for (;;) { + nextToken = parser._NextToken(); + if (nextToken.type == TOKEN_STRING + && BUser::IsValidUserName(nextToken.text)) { + if (!groups.Add(nextToken.text)) + throw std::bad_alloc(); + } else if (nextToken.type == TOKEN_ITEM_SEPARATOR + || nextToken.type == TOKEN_CLOSE_BRACE) { + parser._RewindTo(nextToken); + break; + } else { + throw ParseError("expected a group name", + nextToken.pos); + } + } + break; + } else { + throw ParseError( + "expected 'real-name', 'home', 'shell', or 'groups'", + nextToken.pos); + } + } + + BString templatePath; + + Token nextToken = parser._NextToken(); + if (nextToken.type == TOKEN_STRING + && nextToken.text == "template") { + nextToken = parser._NextToken(); + if (nextToken.type != TOKEN_STRING) { + throw ParseError( + "expected string (a settings template file path)", + nextToken.pos); + } + templatePath = nextToken.text; + } else if (nextToken.type == TOKEN_ITEM_SEPARATOR + || nextToken.type == TOKEN_CLOSE_BRACE) { + parser._RewindTo(nextToken); + } else { + throw ParseError( + "expected 'template', semicolon, new line or '}'", + nextToken.pos); + } + + if (!users->AddItem(new BUser(token.text, realName, home, shell, + groups))) { + throw std::bad_alloc(); + } + } + } resolvableExpressionParser(*this, users); + + _ParseList(resolvableExpressionParser, false); +} + + +void +BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo) +{ + bool seen[B_PACKAGE_INFO_ENUM_COUNT]; + for (int i = 0; i < B_PACKAGE_INFO_ENUM_COUNT; ++i) + seen[i] = false; + + const char* const* names = BPackageInfo::kElementNames; + + while (Token t = _NextToken()) { + if (t.type == TOKEN_ITEM_SEPARATOR) + continue; + + if (t.type != TOKEN_STRING) + throw ParseError("expected string (a variable name)", t.pos); + + BPackageInfoAttributeID attribute = B_PACKAGE_INFO_ENUM_COUNT; + for (int i = 0; i < B_PACKAGE_INFO_ENUM_COUNT; i++) { + if (names[i] != NULL && t.text.ICompare(names[i]) == 0) { + attribute = (BPackageInfoAttributeID)i; + break; + } + } + + if (attribute == B_PACKAGE_INFO_ENUM_COUNT) { + BString error = BString("unknown attribute \"") << t.text << '"'; + throw ParseError(error, t.pos); + } + + if (seen[attribute]) { + BString error = BString(names[attribute]) << " already seen!"; + throw ParseError(error, t.pos); + } + + switch (attribute) { + case B_PACKAGE_INFO_NAME: + { + BString name; + const char* namePos; + _ParseStringValue(&name, &namePos); + + int32 errorPos; + if (!_IsValidResolvableName(name, &errorPos)) { + throw ParseError("invalid character in package name", + namePos + errorPos); + } + + packageInfo->SetName(name); + break; + } + + case B_PACKAGE_INFO_SUMMARY: + { + BString summary; + _ParseStringValue(&summary); + if (summary.FindFirst('\n') >= 0) + throw ParseError("the summary contains linebreaks", t.pos); + packageInfo->SetSummary(summary); + break; + } + + case B_PACKAGE_INFO_DESCRIPTION: + _ParseStringValue(&packageInfo->fDescription); + break; + + case B_PACKAGE_INFO_VENDOR: + _ParseStringValue(&packageInfo->fVendor); + break; + + case B_PACKAGE_INFO_PACKAGER: + _ParseStringValue(&packageInfo->fPackager); + break; + + case B_PACKAGE_INFO_BASE_PACKAGE: + _ParseStringValue(&packageInfo->fBasePackage); + break; + + case B_PACKAGE_INFO_ARCHITECTURE: + _ParseArchitectureValue(&packageInfo->fArchitecture); + break; + + case B_PACKAGE_INFO_VERSION: + _ParseVersionValue(&packageInfo->fVersion, false); + break; + + case B_PACKAGE_INFO_COPYRIGHTS: + _ParseStringList(&packageInfo->fCopyrightList); + break; + + case B_PACKAGE_INFO_LICENSES: + _ParseStringList(&packageInfo->fLicenseList); + break; + + case B_PACKAGE_INFO_URLS: + { + UrlStringValidator stringValidator; + _ParseStringList(&packageInfo->fURLList, + false, false, &stringValidator); + } + break; + + case B_PACKAGE_INFO_SOURCE_URLS: + { + UrlStringValidator stringValidator; + _ParseStringList(&packageInfo->fSourceURLList, + false, false, &stringValidator); + } + break; + + case B_PACKAGE_INFO_GLOBAL_WRITABLE_FILES: + _ParseGlobalWritableFileInfos( + &packageInfo->fGlobalWritableFileInfos); + break; + + case B_PACKAGE_INFO_USER_SETTINGS_FILES: + _ParseUserSettingsFileInfos( + &packageInfo->fUserSettingsFileInfos); + break; + + case B_PACKAGE_INFO_USERS: + _ParseUsers(&packageInfo->fUsers); + break; + + case B_PACKAGE_INFO_GROUPS: + _ParseStringList(&packageInfo->fGroups); + break; + + case B_PACKAGE_INFO_POST_INSTALL_SCRIPTS: + _ParseStringList(&packageInfo->fPostInstallScripts); + break; + + case B_PACKAGE_INFO_PROVIDES: + _ParseResolvableList(&packageInfo->fProvidesList); + break; + + case B_PACKAGE_INFO_REQUIRES: + packageInfo->fBasePackage.Truncate(0); + _ParseResolvableExprList(&packageInfo->fRequiresList, + &packageInfo->fBasePackage); + break; + + case B_PACKAGE_INFO_SUPPLEMENTS: + _ParseResolvableExprList(&packageInfo->fSupplementsList); + break; + + case B_PACKAGE_INFO_CONFLICTS: + _ParseResolvableExprList(&packageInfo->fConflictsList); + break; + + case B_PACKAGE_INFO_FRESHENS: + _ParseResolvableExprList(&packageInfo->fFreshensList); + break; + + case B_PACKAGE_INFO_REPLACES: + _ParseStringList(&packageInfo->fReplacesList, true); + break; + + case B_PACKAGE_INFO_FLAGS: + packageInfo->SetFlags(_ParseFlags()); + break; + + default: + // can never get here + break; + } + + seen[attribute] = true; + } + + // everything up to and including 'provides' is mandatory + for (int i = 0; i <= B_PACKAGE_INFO_PROVIDES; ++i) { + if (!seen[i]) { + BString error = BString(names[i]) << " is not being set anywhere!"; + throw ParseError(error, fPos); + } + } +} + + +/*static*/ inline bool +BPackageInfo::Parser::_IsAlphaNumUnderscore(const BString& string, + const char* additionalChars, int32* _errorPos) +{ + return _IsAlphaNumUnderscore(string.String(), + string.String() + string.Length(), additionalChars, _errorPos); +} + + +/*static*/ inline bool +BPackageInfo::Parser::_IsAlphaNumUnderscore(const char* string, + const char* additionalChars, int32* _errorPos) +{ + return _IsAlphaNumUnderscore(string, string + strlen(string), + additionalChars, _errorPos); +} + + +/*static*/ bool +BPackageInfo::Parser::_IsAlphaNumUnderscore(const char* start, const char* end, + const char* additionalChars, int32* _errorPos) +{ + for (const char* c = start; c < end; c++) { + if (!isalnum(*c) && *c != '_' && strchr(additionalChars, *c) == NULL) { + if (_errorPos != NULL) + *_errorPos = c - start; + return false; + } + } + + return true; +} + + +/*static*/ bool +BPackageInfo::Parser::_IsValidResolvableName(const char* string, + int32* _errorPos) +{ + for (const char* c = string; *c != '\0'; c++) { + switch (*c) { + case '-': + case '/': + case '<': + case '>': + case '=': + case '!': + break; + default: + if (!isspace(*c)) + continue; + break; + } + + if (_errorPos != NULL) + *_errorPos = c - string; + return false; + } + return true; +} + +void +BPackageInfo::Parser::UrlStringValidator::Validate(const BString& urlString, + const char* pos) +{ + BUrl url(urlString); + + if (!url.IsValid()) + throw ParseError("invalid url", pos); +} + + +} // namespace BPackageKit diff --git a/samples/C++/bcm2835.h b/samples/C++/bcm2835.h deleted file mode 100644 index e5330933..00000000 --- a/samples/C++/bcm2835.h +++ /dev/null @@ -1,1129 +0,0 @@ -// bcm2835.h -// -// C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi -// -// Author: Mike McCauley -// Copyright (C) 2011-2013 Mike McCauley -// $Id: bcm2835.h,v 1.8 2013/02/15 22:06:09 mikem Exp mikem $ -// -/// \mainpage C library for Broadcom BCM 2835 as used in Raspberry Pi -/// -/// This is a C library for Raspberry Pi (RPi). It provides access to -/// GPIO and other IO functions on the Broadcom BCM 2835 chip, -/// allowing access to the GPIO pins on the -/// 26 pin IDE plug on the RPi board so you can control and interface with various external devices. -/// -/// It provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, -/// and for accessing the system timers. -/// Pin event detection is supported by polling (interrupts are not supported). -/// -/// It is C++ compatible, and installs as a header file and non-shared library on -/// any Linux-based distro (but clearly is no use except on Raspberry Pi or another board with -/// BCM 2835). -/// -/// The version of the package that this documentation refers to can be downloaded -/// from http://www.airspayce.com/mikem/bcm2835/bcm2835-1.26.tar.gz -/// You can find the latest version at http://www.airspayce.com/mikem/bcm2835 -/// -/// Several example programs are provided. -/// -/// Based on data in http://elinux.org/RPi_Low-level_peripherals and -/// http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf -/// and http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 -/// -/// You can also find online help and discussion at http://groups.google.com/group/bcm2835 -/// Please use that group for all questions and discussions on this topic. -/// Do not contact the author directly, unless it is to discuss commercial licensing. -/// -/// Tested on debian6-19-04-2012, 2012-07-15-wheezy-raspbian and Occidentalisv01 -/// CAUTION: it has been observed that when detect enables such as bcm2835_gpio_len() -/// are used and the pin is pulled LOW -/// it can cause temporary hangs on 2012-07-15-wheezy-raspbian and Occidentalisv01. -/// Reason for this is not yet determined, but suspect that an interrupt handler is -/// hitting a hard loop on those OSs. -/// If you must use bcm2835_gpio_len() and friends, make sure you disable the pins with -/// bcm2835_gpio_cler_len() and friends after use. -/// -/// \par Installation -/// -/// This library consists of a single non-shared library and header file, which will be -/// installed in the usual places by make install -/// -/// \code -/// # download the latest version of the library, say bcm2835-1.xx.tar.gz, then: -/// tar zxvf bcm2835-1.xx.tar.gz -/// cd bcm2835-1.xx -/// ./configure -/// make -/// sudo make check -/// sudo make install -/// \endcode -/// -/// \par Physical Addresses -/// -/// The functions bcm2835_peri_read(), bcm2835_peri_write() and bcm2835_peri_set_bits() -/// are low level peripheral register access functions. They are designed to use -/// physical addresses as described in section 1.2.3 ARM physical addresses -/// of the BCM2835 ARM Peripherals manual. -/// Physical addresses range from 0x20000000 to 0x20FFFFFF for peripherals. The bus -/// addresses for peripherals are set up to map onto the peripheral bus address range starting at -/// 0x7E000000. Thus a peripheral advertised in the manual at bus address 0x7Ennnnnn is available at -/// physical address 0x20nnnnnn. -/// -/// The base address of the various peripheral registers are available with the following -/// externals: -/// bcm2835_gpio -/// bcm2835_pwm -/// bcm2835_clk -/// bcm2835_pads -/// bcm2835_spio0 -/// bcm2835_st -/// bcm2835_bsc0 -/// bcm2835_bsc1 -/// -/// \par Pin Numbering -/// -/// The GPIO pin numbering as used by RPi is different to and inconsistent with the underlying -/// BCM 2835 chip pin numbering. http://elinux.org/RPi_BCM2835_GPIOs -/// -/// RPi has a 26 pin IDE header that provides access to some of the GPIO pins on the BCM 2835, -/// as well as power and ground pins. Not all GPIO pins on the BCM 2835 are available on the -/// IDE header. -/// -/// RPi Version 2 also has a P5 connector with 4 GPIO pins, 5V, 3.3V and Gnd. -/// -/// The functions in this library are designed to be passed the BCM 2835 GPIO pin number and _not_ -/// the RPi pin number. There are symbolic definitions for each of the available pins -/// that you should use for convenience. See \ref RPiGPIOPin. -/// -/// \par SPI Pins -/// -/// The bcm2835_spi_* functions allow you to control the BCM 2835 SPI0 interface, -/// allowing you to send and received data by SPI (Serial Peripheral Interface). -/// For more information about SPI, see http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus -/// -/// When bcm2835_spi_begin() is called it changes the bahaviour of the SPI interface pins from their -/// default GPIO behaviour in order to support SPI. While SPI is in use, you will not be able -/// to control the state of the SPI pins through the usual bcm2835_spi_gpio_write(). -/// When bcm2835_spi_end() is called, the SPI pins will all revert to inputs, and can then be -/// configured and controled with the usual bcm2835_gpio_* calls. -/// -/// The Raspberry Pi GPIO pins used for SPI are: -/// -/// - P1-19 (MOSI) -/// - P1-21 (MISO) -/// - P1-23 (CLK) -/// - P1-24 (CE0) -/// - P1-26 (CE1) -/// -/// \par I2C Pins -/// -/// The bcm2835_i2c_* functions allow you to control the BCM 2835 BSC interface, -/// allowing you to send and received data by I2C ("eye-squared cee"; generically referred to as "two-wire interface") . -/// For more information about I?C, see http://en.wikipedia.org/wiki/I%C2%B2C -/// -/// The Raspberry Pi V2 GPIO pins used for I2C are: -/// -/// - P1-03 (SDA) -/// - P1-05 (SLC) -/// -/// \par Real Time performance constraints -/// -/// The bcm2835 is a library for user programs (i.e. they run in 'userland'). -/// Such programs are not part of the kernel and are usually -/// subject to paging and swapping by the kernel while it does other things besides running your program. -/// This means that you should not expect to get real-time performance or -/// real-time timing constraints from such programs. In particular, there is no guarantee that the -/// bcm2835_delay() and bcm2835_delayMicroseconds() will return after exactly the time requested. -/// In fact, depending on other activity on the host, IO etc, you might get significantly longer delay times -/// than the one you asked for. So please dont expect to get exactly the time delay you request. -/// -/// Arjan reports that you can prevent swapping on Linux with the following code fragment: -/// -/// \code -/// struct sched_param sp; -/// memset(&sp, 0, sizeof(sp)); -/// sp.sched_priority = sched_get_priority_max(SCHED_FIFO); -/// sched_setscheduler(0, SCHED_FIFO, &sp); -/// mlockall(MCL_CURRENT | MCL_FUTURE); -/// \endcode -/// -/// \par Open Source Licensing GPL V2 -/// -/// This is the appropriate option if you want to share the source code of your -/// application with everyone you distribute it to, and you also want to give them -/// the right to share who uses it. If you wish to use this software under Open -/// Source Licensing, you must contribute all your source code to the open source -/// community in accordance with the GPL Version 2 when your application is -/// distributed. See http://www.gnu.org/copyleft/gpl.html and COPYING -/// -/// \par Acknowledgements -/// -/// Some of this code has been inspired by Dom and Gert. -/// The I2C code has been inspired by Alan Barr. -/// -/// \par Revision History -/// -/// \version 1.0 Initial release -/// \version 1.1 Minor bug fixes -/// \version 1.2 Added support for SPI -/// \version 1.3 Added bcm2835_spi_transfern() -/// \version 1.4 Fixed a problem that prevented SPI CE1 being used. Reported by David Robinson. -/// \version 1.5 Added bcm2835_close() to deinit the library. Suggested by C?sar Ortiz -/// \version 1.6 Document testing on 2012-07-15-wheezy-raspbian and Occidentalisv01 -/// Functions bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen() -/// bcm2835_gpio_len(), bcm2835_gpio_aren() and bcm2835_gpio_afen() now -/// changes only the pin specified. Other pins that were already previously -/// enabled stay enabled. -/// Added bcm2835_gpio_clr_ren(), bcm2835_gpio_clr_fen(), bcm2835_gpio_clr_hen() -/// bcm2835_gpio_clr_len(), bcm2835_gpio_clr_aren(), bcm2835_gpio_clr_afen() -/// to clear the enable for individual pins, suggested by Andreas Sundstrom. -/// \version 1.7 Added bcm2835_spi_transfernb to support different buffers for read and write. -/// \version 1.8 Improvements to read barrier, as suggested by maddin. -/// \version 1.9 Improvements contributed by mikew: -/// I noticed that it was mallocing memory for the mmaps on /dev/mem. -/// It's not necessary to do that, you can just mmap the file directly, -/// so I've removed the mallocs (and frees). -/// I've also modified delayMicroseconds() to use nanosleep() for long waits, -/// and a busy wait on a high resolution timer for the rest. This is because -/// I've found that calling nanosleep() takes at least 100-200 us. -/// You need to link using '-lrt' using this version. -/// I've added some unsigned casts to the debug prints to silence compiler -/// warnings I was getting, fixed some typos, and changed the value of -/// BCM2835_PAD_HYSTERESIS_ENABLED to 0x08 as per Gert van Loo's doc at -/// http://www.scribd.com/doc/101830961/GPIO-Pads-Control2 -/// Also added a define for the passwrd value that Gert says is needed to -/// change pad control settings. -/// \version 1.10 Changed the names of the delay functions to bcm2835_delay() -/// and bcm2835_delayMicroseconds() to prevent collisions with wiringPi. -/// Macros to map delay()-> bcm2835_delay() and -/// Macros to map delayMicroseconds()-> bcm2835_delayMicroseconds(), which -/// can be disabled by defining BCM2835_NO_DELAY_COMPATIBILITY -/// \version 1.11 Fixed incorrect link to download file -/// \version 1.12 New GPIO pin definitions for RPi version 2 (which has a different GPIO mapping) -/// \version 1.13 New GPIO pin definitions for RPi version 2 plug P5 -/// Hardware base pointers are now available (after initialisation) externally as bcm2835_gpio -/// bcm2835_pwm bcm2835_clk bcm2835_pads bcm2835_spi0. -/// \version 1.14 Now compiles even if CLOCK_MONOTONIC_RAW is not available, uses CLOCK_MONOTONIC instead. -/// Fixed errors in documentation of SPI divider frequencies based on 250MHz clock. -/// Reported by Ben Simpson. -/// \version 1.15 Added bcm2835_close() to end of examples as suggested by Mark Wolfe. -/// \version 1.16 Added bcm2835_gpio_set_multi, bcm2835_gpio_clr_multi and bcm2835_gpio_write_multi -/// to allow a mask of pins to be set all at once. Requested by Sebastian Loncar. -/// \version 1.17 Added bcm2835_gpio_write_mask. Requested by Sebastian Loncar. -/// \version 1.18 Added bcm2835_i2c_* functions. Changes to bcm2835_delayMicroseconds: -/// now uses the RPi system timer counter, instead of clock_gettime, for improved accuracy. -/// No need to link with -lrt now. Contributed by Arjan van Vught. -/// \version 1.19 Removed inlines added by previous patch since they don't seem to work everywhere. -/// Reported by olly. -/// \version 1.20 Patch from Mark Dootson to close /dev/mem after access to the peripherals has been granted. -/// \version 1.21 delayMicroseconds is now not susceptible to 32 bit timer overruns. -/// Patch courtesy Jeremy Mortis. -/// \version 1.22 Fixed incorrect definition of BCM2835_GPFEN0 which broke the ability to set -/// falling edge events. Reported by Mark Dootson. -/// \version 1.23 Added bcm2835_i2c_set_baudrate and bcm2835_i2c_read_register_rs. -/// Improvements to bcm2835_i2c_read and bcm2835_i2c_write functions -/// to fix ocasional reads not completing. Patched by Mark Dootson. -/// \version 1.24 Mark Dootson p[atched a problem with his previously submitted code -/// under high load from other processes. -/// \version 1.25 Updated author and distribution location details to airspayce.com -/// \version 1.26 Added missing unmapmem for pads in bcm2835_close to prevent a memory leak. -/// Reported by Hartmut Henkel. -/// \author Mike McCauley (mikem@airspayce.com) DO NOT CONTACT THE AUTHOR DIRECTLY: USE THE LISTS - - - -// Defines for BCM2835 -#ifndef BCM2835_H -#define BCM2835_H - -#include - -/// \defgroup constants Constants for passing to and from library functions -/// The values here are designed to be passed to various functions in the bcm2835 library. -/// @{ - - -/// This means pin HIGH, true, 3.3volts on a pin. -#define HIGH 0x1 -/// This means pin LOW, false, 0volts on a pin. -#define LOW 0x0 - -/// Speed of the core clock core_clk -#define BCM2835_CORE_CLK_HZ 250000000 ///< 250 MHz - -// Physical addresses for various peripheral register sets -/// Base Physical Address of the BCM 2835 peripheral registers -#define BCM2835_PERI_BASE 0x20000000 -/// Base Physical Address of the System Timer registers -#define BCM2835_ST_BASE (BCM2835_PERI_BASE + 0x3000) -/// Base Physical Address of the Pads registers -#define BCM2835_GPIO_PADS (BCM2835_PERI_BASE + 0x100000) -/// Base Physical Address of the Clock/timer registers -#define BCM2835_CLOCK_BASE (BCM2835_PERI_BASE + 0x101000) -/// Base Physical Address of the GPIO registers -#define BCM2835_GPIO_BASE (BCM2835_PERI_BASE + 0x200000) -/// Base Physical Address of the SPI0 registers -#define BCM2835_SPI0_BASE (BCM2835_PERI_BASE + 0x204000) -/// Base Physical Address of the BSC0 registers -#define BCM2835_BSC0_BASE (BCM2835_PERI_BASE + 0x205000) -/// Base Physical Address of the PWM registers -#define BCM2835_GPIO_PWM (BCM2835_PERI_BASE + 0x20C000) - /// Base Physical Address of the BSC1 registers -#define BCM2835_BSC1_BASE (BCM2835_PERI_BASE + 0x804000) - - -/// Base of the ST (System Timer) registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_st; - -/// Base of the GPIO registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_gpio; - -/// Base of the PWM registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_pwm; - -/// Base of the CLK registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_clk; - -/// Base of the PADS registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_pads; - -/// Base of the SPI0 registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_spi0; - -/// Base of the BSC0 registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_bsc0; - -/// Base of the BSC1 registers. -/// Available after bcm2835_init has been called -extern volatile uint32_t *bcm2835_bsc1; - -/// Size of memory page on RPi -#define BCM2835_PAGE_SIZE (4*1024) -/// Size of memory block on RPi -#define BCM2835_BLOCK_SIZE (4*1024) - - -// Defines for GPIO -// The BCM2835 has 54 GPIO pins. -// BCM2835 data sheet, Page 90 onwards. -/// GPIO register offsets from BCM2835_GPIO_BASE. Offsets into the GPIO Peripheral block in bytes per 6.1 Register View -#define BCM2835_GPFSEL0 0x0000 ///< GPIO Function Select 0 -#define BCM2835_GPFSEL1 0x0004 ///< GPIO Function Select 1 -#define BCM2835_GPFSEL2 0x0008 ///< GPIO Function Select 2 -#define BCM2835_GPFSEL3 0x000c ///< GPIO Function Select 3 -#define BCM2835_GPFSEL4 0x0010 ///< GPIO Function Select 4 -#define BCM2835_GPFSEL5 0x0014 ///< GPIO Function Select 5 -#define BCM2835_GPSET0 0x001c ///< GPIO Pin Output Set 0 -#define BCM2835_GPSET1 0x0020 ///< GPIO Pin Output Set 1 -#define BCM2835_GPCLR0 0x0028 ///< GPIO Pin Output Clear 0 -#define BCM2835_GPCLR1 0x002c ///< GPIO Pin Output Clear 1 -#define BCM2835_GPLEV0 0x0034 ///< GPIO Pin Level 0 -#define BCM2835_GPLEV1 0x0038 ///< GPIO Pin Level 1 -#define BCM2835_GPEDS0 0x0040 ///< GPIO Pin Event Detect Status 0 -#define BCM2835_GPEDS1 0x0044 ///< GPIO Pin Event Detect Status 1 -#define BCM2835_GPREN0 0x004c ///< GPIO Pin Rising Edge Detect Enable 0 -#define BCM2835_GPREN1 0x0050 ///< GPIO Pin Rising Edge Detect Enable 1 -#define BCM2835_GPFEN0 0x0058 ///< GPIO Pin Falling Edge Detect Enable 0 -#define BCM2835_GPFEN1 0x005c ///< GPIO Pin Falling Edge Detect Enable 1 -#define BCM2835_GPHEN0 0x0064 ///< GPIO Pin High Detect Enable 0 -#define BCM2835_GPHEN1 0x0068 ///< GPIO Pin High Detect Enable 1 -#define BCM2835_GPLEN0 0x0070 ///< GPIO Pin Low Detect Enable 0 -#define BCM2835_GPLEN1 0x0074 ///< GPIO Pin Low Detect Enable 1 -#define BCM2835_GPAREN0 0x007c ///< GPIO Pin Async. Rising Edge Detect 0 -#define BCM2835_GPAREN1 0x0080 ///< GPIO Pin Async. Rising Edge Detect 1 -#define BCM2835_GPAFEN0 0x0088 ///< GPIO Pin Async. Falling Edge Detect 0 -#define BCM2835_GPAFEN1 0x008c ///< GPIO Pin Async. Falling Edge Detect 1 -#define BCM2835_GPPUD 0x0094 ///< GPIO Pin Pull-up/down Enable -#define BCM2835_GPPUDCLK0 0x0098 ///< GPIO Pin Pull-up/down Enable Clock 0 -#define BCM2835_GPPUDCLK1 0x009c ///< GPIO Pin Pull-up/down Enable Clock 1 - -/// \brief bcm2835PortFunction -/// Port function select modes for bcm2835_gpio_fsel() -typedef enum -{ - BCM2835_GPIO_FSEL_INPT = 0b000, ///< Input - BCM2835_GPIO_FSEL_OUTP = 0b001, ///< Output - BCM2835_GPIO_FSEL_ALT0 = 0b100, ///< Alternate function 0 - BCM2835_GPIO_FSEL_ALT1 = 0b101, ///< Alternate function 1 - BCM2835_GPIO_FSEL_ALT2 = 0b110, ///< Alternate function 2 - BCM2835_GPIO_FSEL_ALT3 = 0b111, ///< Alternate function 3 - BCM2835_GPIO_FSEL_ALT4 = 0b011, ///< Alternate function 4 - BCM2835_GPIO_FSEL_ALT5 = 0b010, ///< Alternate function 5 - BCM2835_GPIO_FSEL_MASK = 0b111 ///< Function select bits mask -} bcm2835FunctionSelect; - -/// \brief bcm2835PUDControl -/// Pullup/Pulldown defines for bcm2835_gpio_pud() -typedef enum -{ - BCM2835_GPIO_PUD_OFF = 0b00, ///< Off ? disable pull-up/down - BCM2835_GPIO_PUD_DOWN = 0b01, ///< Enable Pull Down control - BCM2835_GPIO_PUD_UP = 0b10 ///< Enable Pull Up control -} bcm2835PUDControl; - -/// Pad control register offsets from BCM2835_GPIO_PADS -#define BCM2835_PADS_GPIO_0_27 0x002c ///< Pad control register for pads 0 to 27 -#define BCM2835_PADS_GPIO_28_45 0x0030 ///< Pad control register for pads 28 to 45 -#define BCM2835_PADS_GPIO_46_53 0x0034 ///< Pad control register for pads 46 to 53 - -/// Pad Control masks -#define BCM2835_PAD_PASSWRD (0x5A << 24) ///< Password to enable setting pad mask -#define BCM2835_PAD_SLEW_RATE_UNLIMITED 0x10 ///< Slew rate unlimited -#define BCM2835_PAD_HYSTERESIS_ENABLED 0x08 ///< Hysteresis enabled -#define BCM2835_PAD_DRIVE_2mA 0x00 ///< 2mA drive current -#define BCM2835_PAD_DRIVE_4mA 0x01 ///< 4mA drive current -#define BCM2835_PAD_DRIVE_6mA 0x02 ///< 6mA drive current -#define BCM2835_PAD_DRIVE_8mA 0x03 ///< 8mA drive current -#define BCM2835_PAD_DRIVE_10mA 0x04 ///< 10mA drive current -#define BCM2835_PAD_DRIVE_12mA 0x05 ///< 12mA drive current -#define BCM2835_PAD_DRIVE_14mA 0x06 ///< 14mA drive current -#define BCM2835_PAD_DRIVE_16mA 0x07 ///< 16mA drive current - -/// \brief bcm2835PadGroup -/// Pad group specification for bcm2835_gpio_pad() -typedef enum -{ - BCM2835_PAD_GROUP_GPIO_0_27 = 0, ///< Pad group for GPIO pads 0 to 27 - BCM2835_PAD_GROUP_GPIO_28_45 = 1, ///< Pad group for GPIO pads 28 to 45 - BCM2835_PAD_GROUP_GPIO_46_53 = 2 ///< Pad group for GPIO pads 46 to 53 -} bcm2835PadGroup; - -/// \brief GPIO Pin Numbers -/// -/// Here we define Raspberry Pin GPIO pins on P1 in terms of the underlying BCM GPIO pin numbers. -/// These can be passed as a pin number to any function requiring a pin. -/// Not all pins on the RPi 26 bin IDE plug are connected to GPIO pins -/// and some can adopt an alternate function. -/// RPi version 2 has some slightly different pinouts, and these are values RPI_V2_*. -/// At bootup, pins 8 and 10 are set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively -/// When SPI0 is in use (ie after bcm2835_spi_begin()), pins 19, 21, 23, 24, 26 are dedicated to SPI -/// and cant be controlled independently -typedef enum -{ - RPI_GPIO_P1_03 = 0, ///< Version 1, Pin P1-03 - RPI_GPIO_P1_05 = 1, ///< Version 1, Pin P1-05 - RPI_GPIO_P1_07 = 4, ///< Version 1, Pin P1-07 - RPI_GPIO_P1_08 = 14, ///< Version 1, Pin P1-08, defaults to alt function 0 UART0_TXD - RPI_GPIO_P1_10 = 15, ///< Version 1, Pin P1-10, defaults to alt function 0 UART0_RXD - RPI_GPIO_P1_11 = 17, ///< Version 1, Pin P1-11 - RPI_GPIO_P1_12 = 18, ///< Version 1, Pin P1-12 - RPI_GPIO_P1_13 = 21, ///< Version 1, Pin P1-13 - RPI_GPIO_P1_15 = 22, ///< Version 1, Pin P1-15 - RPI_GPIO_P1_16 = 23, ///< Version 1, Pin P1-16 - RPI_GPIO_P1_18 = 24, ///< Version 1, Pin P1-18 - RPI_GPIO_P1_19 = 10, ///< Version 1, Pin P1-19, MOSI when SPI0 in use - RPI_GPIO_P1_21 = 9, ///< Version 1, Pin P1-21, MISO when SPI0 in use - RPI_GPIO_P1_22 = 25, ///< Version 1, Pin P1-22 - RPI_GPIO_P1_23 = 11, ///< Version 1, Pin P1-23, CLK when SPI0 in use - RPI_GPIO_P1_24 = 8, ///< Version 1, Pin P1-24, CE0 when SPI0 in use - RPI_GPIO_P1_26 = 7, ///< Version 1, Pin P1-26, CE1 when SPI0 in use - - // RPi Version 2 - RPI_V2_GPIO_P1_03 = 2, ///< Version 2, Pin P1-03 - RPI_V2_GPIO_P1_05 = 3, ///< Version 2, Pin P1-05 - RPI_V2_GPIO_P1_07 = 4, ///< Version 2, Pin P1-07 - RPI_V2_GPIO_P1_08 = 14, ///< Version 2, Pin P1-08, defaults to alt function 0 UART0_TXD - RPI_V2_GPIO_P1_10 = 15, ///< Version 2, Pin P1-10, defaults to alt function 0 UART0_RXD - RPI_V2_GPIO_P1_11 = 17, ///< Version 2, Pin P1-11 - RPI_V2_GPIO_P1_12 = 18, ///< Version 2, Pin P1-12 - RPI_V2_GPIO_P1_13 = 27, ///< Version 2, Pin P1-13 - RPI_V2_GPIO_P1_15 = 22, ///< Version 2, Pin P1-15 - RPI_V2_GPIO_P1_16 = 23, ///< Version 2, Pin P1-16 - RPI_V2_GPIO_P1_18 = 24, ///< Version 2, Pin P1-18 - RPI_V2_GPIO_P1_19 = 10, ///< Version 2, Pin P1-19, MOSI when SPI0 in use - RPI_V2_GPIO_P1_21 = 9, ///< Version 2, Pin P1-21, MISO when SPI0 in use - RPI_V2_GPIO_P1_22 = 25, ///< Version 2, Pin P1-22 - RPI_V2_GPIO_P1_23 = 11, ///< Version 2, Pin P1-23, CLK when SPI0 in use - RPI_V2_GPIO_P1_24 = 8, ///< Version 2, Pin P1-24, CE0 when SPI0 in use - RPI_V2_GPIO_P1_26 = 7, ///< Version 2, Pin P1-26, CE1 when SPI0 in use - - // RPi Version 2, new plug P5 - RPI_V2_GPIO_P5_03 = 28, ///< Version 2, Pin P5-03 - RPI_V2_GPIO_P5_04 = 29, ///< Version 2, Pin P5-04 - RPI_V2_GPIO_P5_05 = 30, ///< Version 2, Pin P5-05 - RPI_V2_GPIO_P5_06 = 31, ///< Version 2, Pin P5-06 - -} RPiGPIOPin; - -// Defines for SPI -// GPIO register offsets from BCM2835_SPI0_BASE. -// Offsets into the SPI Peripheral block in bytes per 10.5 SPI Register Map -#define BCM2835_SPI0_CS 0x0000 ///< SPI Master Control and Status -#define BCM2835_SPI0_FIFO 0x0004 ///< SPI Master TX and RX FIFOs -#define BCM2835_SPI0_CLK 0x0008 ///< SPI Master Clock Divider -#define BCM2835_SPI0_DLEN 0x000c ///< SPI Master Data Length -#define BCM2835_SPI0_LTOH 0x0010 ///< SPI LOSSI mode TOH -#define BCM2835_SPI0_DC 0x0014 ///< SPI DMA DREQ Controls - -// Register masks for SPI0_CS -#define BCM2835_SPI0_CS_LEN_LONG 0x02000000 ///< Enable Long data word in Lossi mode if DMA_LEN is set -#define BCM2835_SPI0_CS_DMA_LEN 0x01000000 ///< Enable DMA mode in Lossi mode -#define BCM2835_SPI0_CS_CSPOL2 0x00800000 ///< Chip Select 2 Polarity -#define BCM2835_SPI0_CS_CSPOL1 0x00400000 ///< Chip Select 1 Polarity -#define BCM2835_SPI0_CS_CSPOL0 0x00200000 ///< Chip Select 0 Polarity -#define BCM2835_SPI0_CS_RXF 0x00100000 ///< RXF - RX FIFO Full -#define BCM2835_SPI0_CS_RXR 0x00080000 ///< RXR RX FIFO needs Reading ( full) -#define BCM2835_SPI0_CS_TXD 0x00040000 ///< TXD TX FIFO can accept Data -#define BCM2835_SPI0_CS_RXD 0x00020000 ///< RXD RX FIFO contains Data -#define BCM2835_SPI0_CS_DONE 0x00010000 ///< Done transfer Done -#define BCM2835_SPI0_CS_TE_EN 0x00008000 ///< Unused -#define BCM2835_SPI0_CS_LMONO 0x00004000 ///< Unused -#define BCM2835_SPI0_CS_LEN 0x00002000 ///< LEN LoSSI enable -#define BCM2835_SPI0_CS_REN 0x00001000 ///< REN Read Enable -#define BCM2835_SPI0_CS_ADCS 0x00000800 ///< ADCS Automatically Deassert Chip Select -#define BCM2835_SPI0_CS_INTR 0x00000400 ///< INTR Interrupt on RXR -#define BCM2835_SPI0_CS_INTD 0x00000200 ///< INTD Interrupt on Done -#define BCM2835_SPI0_CS_DMAEN 0x00000100 ///< DMAEN DMA Enable -#define BCM2835_SPI0_CS_TA 0x00000080 ///< Transfer Active -#define BCM2835_SPI0_CS_CSPOL 0x00000040 ///< Chip Select Polarity -#define BCM2835_SPI0_CS_CLEAR 0x00000030 ///< Clear FIFO Clear RX and TX -#define BCM2835_SPI0_CS_CLEAR_RX 0x00000020 ///< Clear FIFO Clear RX -#define BCM2835_SPI0_CS_CLEAR_TX 0x00000010 ///< Clear FIFO Clear TX -#define BCM2835_SPI0_CS_CPOL 0x00000008 ///< Clock Polarity -#define BCM2835_SPI0_CS_CPHA 0x00000004 ///< Clock Phase -#define BCM2835_SPI0_CS_CS 0x00000003 ///< Chip Select - -/// \brief bcm2835SPIBitOrder SPI Bit order -/// Specifies the SPI data bit ordering for bcm2835_spi_setBitOrder() -typedef enum -{ - BCM2835_SPI_BIT_ORDER_LSBFIRST = 0, ///< LSB First - BCM2835_SPI_BIT_ORDER_MSBFIRST = 1 ///< MSB First -}bcm2835SPIBitOrder; - -/// \brief SPI Data mode -/// Specify the SPI data mode to be passed to bcm2835_spi_setDataMode() -typedef enum -{ - BCM2835_SPI_MODE0 = 0, ///< CPOL = 0, CPHA = 0 - BCM2835_SPI_MODE1 = 1, ///< CPOL = 0, CPHA = 1 - BCM2835_SPI_MODE2 = 2, ///< CPOL = 1, CPHA = 0 - BCM2835_SPI_MODE3 = 3, ///< CPOL = 1, CPHA = 1 -}bcm2835SPIMode; - -/// \brief bcm2835SPIChipSelect -/// Specify the SPI chip select pin(s) -typedef enum -{ - BCM2835_SPI_CS0 = 0, ///< Chip Select 0 - BCM2835_SPI_CS1 = 1, ///< Chip Select 1 - BCM2835_SPI_CS2 = 2, ///< Chip Select 2 (ie pins CS1 and CS2 are asserted) - BCM2835_SPI_CS_NONE = 3, ///< No CS, control it yourself -} bcm2835SPIChipSelect; - -/// \brief bcm2835SPIClockDivider -/// Specifies the divider used to generate the SPI clock from the system clock. -/// Figures below give the divider, clock period and clock frequency. -/// Clock divided is based on nominal base clock rate of 250MHz -/// It is reported that (contrary to the documentation) any even divider may used. -/// The frequencies shown for each divider have been confirmed by measurement -typedef enum -{ - BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, ///< 65536 = 262.144us = 3.814697260kHz - BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, ///< 32768 = 131.072us = 7.629394531kHz - BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, ///< 16384 = 65.536us = 15.25878906kHz - BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, ///< 8192 = 32.768us = 30/51757813kHz - BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, ///< 4096 = 16.384us = 61.03515625kHz - BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, ///< 2048 = 8.192us = 122.0703125kHz - BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, ///< 1024 = 4.096us = 244.140625kHz - BCM2835_SPI_CLOCK_DIVIDER_512 = 512, ///< 512 = 2.048us = 488.28125kHz - BCM2835_SPI_CLOCK_DIVIDER_256 = 256, ///< 256 = 1.024us = 976.5625MHz - BCM2835_SPI_CLOCK_DIVIDER_128 = 128, ///< 128 = 512ns = = 1.953125MHz - BCM2835_SPI_CLOCK_DIVIDER_64 = 64, ///< 64 = 256ns = 3.90625MHz - BCM2835_SPI_CLOCK_DIVIDER_32 = 32, ///< 32 = 128ns = 7.8125MHz - BCM2835_SPI_CLOCK_DIVIDER_16 = 16, ///< 16 = 64ns = 15.625MHz - BCM2835_SPI_CLOCK_DIVIDER_8 = 8, ///< 8 = 32ns = 31.25MHz - BCM2835_SPI_CLOCK_DIVIDER_4 = 4, ///< 4 = 16ns = 62.5MHz - BCM2835_SPI_CLOCK_DIVIDER_2 = 2, ///< 2 = 8ns = 125MHz, fastest you can get - BCM2835_SPI_CLOCK_DIVIDER_1 = 1, ///< 0 = 262.144us = 3.814697260kHz, same as 0/65536 -} bcm2835SPIClockDivider; - -// Defines for I2C -// GPIO register offsets from BCM2835_BSC*_BASE. -// Offsets into the BSC Peripheral block in bytes per 3.1 BSC Register Map -#define BCM2835_BSC_C 0x0000 ///< BSC Master Control -#define BCM2835_BSC_S 0x0004 ///< BSC Master Status -#define BCM2835_BSC_DLEN 0x0008 ///< BSC Master Data Length -#define BCM2835_BSC_A 0x000c ///< BSC Master Slave Address -#define BCM2835_BSC_FIFO 0x0010 ///< BSC Master Data FIFO -#define BCM2835_BSC_DIV 0x0014 ///< BSC Master Clock Divider -#define BCM2835_BSC_DEL 0x0018 ///< BSC Master Data Delay -#define BCM2835_BSC_CLKT 0x001c ///< BSC Master Clock Stretch Timeout - -// Register masks for BSC_C -#define BCM2835_BSC_C_I2CEN 0x00008000 ///< I2C Enable, 0 = disabled, 1 = enabled -#define BCM2835_BSC_C_INTR 0x00000400 ///< Interrupt on RX -#define BCM2835_BSC_C_INTT 0x00000200 ///< Interrupt on TX -#define BCM2835_BSC_C_INTD 0x00000100 ///< Interrupt on DONE -#define BCM2835_BSC_C_ST 0x00000080 ///< Start transfer, 1 = Start a new transfer -#define BCM2835_BSC_C_CLEAR_1 0x00000020 ///< Clear FIFO Clear -#define BCM2835_BSC_C_CLEAR_2 0x00000010 ///< Clear FIFO Clear -#define BCM2835_BSC_C_READ 0x00000001 ///< Read transfer - -// Register masks for BSC_S -#define BCM2835_BSC_S_CLKT 0x00000200 ///< Clock stretch timeout -#define BCM2835_BSC_S_ERR 0x00000100 ///< ACK error -#define BCM2835_BSC_S_RXF 0x00000080 ///< RXF FIFO full, 0 = FIFO is not full, 1 = FIFO is full -#define BCM2835_BSC_S_TXE 0x00000040 ///< TXE FIFO full, 0 = FIFO is not full, 1 = FIFO is full -#define BCM2835_BSC_S_RXD 0x00000020 ///< RXD FIFO contains data -#define BCM2835_BSC_S_TXD 0x00000010 ///< TXD FIFO can accept data -#define BCM2835_BSC_S_RXR 0x00000008 ///< RXR FIFO needs reading (full) -#define BCM2835_BSC_S_TXW 0x00000004 ///< TXW FIFO needs writing (full) -#define BCM2835_BSC_S_DONE 0x00000002 ///< Transfer DONE -#define BCM2835_BSC_S_TA 0x00000001 ///< Transfer Active - -#define BCM2835_BSC_FIFO_SIZE 16 ///< BSC FIFO size - -/// \brief bcm2835I2CClockDivider -/// Specifies the divider used to generate the I2C clock from the system clock. -/// Clock divided is based on nominal base clock rate of 250MHz -typedef enum -{ - BCM2835_I2C_CLOCK_DIVIDER_2500 = 2500, ///< 2500 = 10us = 100 kHz - BCM2835_I2C_CLOCK_DIVIDER_626 = 626, ///< 622 = 2.504us = 399.3610 kHz - BCM2835_I2C_CLOCK_DIVIDER_150 = 150, ///< 150 = 60ns = 1.666 MHz (default at reset) - BCM2835_I2C_CLOCK_DIVIDER_148 = 148, ///< 148 = 59ns = 1.689 MHz -} bcm2835I2CClockDivider; - -/// \brief bcm2835I2CReasonCodes -/// Specifies the reason codes for the bcm2835_i2c_write and bcm2835_i2c_read functions. -typedef enum -{ - BCM2835_I2C_REASON_OK = 0x00, ///< Success - BCM2835_I2C_REASON_ERROR_NACK = 0x01, ///< Received a NACK - BCM2835_I2C_REASON_ERROR_CLKT = 0x02, ///< Received Clock Stretch Timeout - BCM2835_I2C_REASON_ERROR_DATA = 0x04, ///< Not all data is sent / received -} bcm2835I2CReasonCodes; - -// Defines for ST -// GPIO register offsets from BCM2835_ST_BASE. -// Offsets into the ST Peripheral block in bytes per 12.1 System Timer Registers -// The System Timer peripheral provides four 32-bit timer channels and a single 64-bit free running counter. -// BCM2835_ST_CLO is the System Timer Counter Lower bits register. -// The system timer free-running counter lower register is a read-only register that returns the current value -// of the lower 32-bits of the free running counter. -// BCM2835_ST_CHI is the System Timer Counter Upper bits register. -// The system timer free-running counter upper register is a read-only register that returns the current value -// of the upper 32-bits of the free running counter. -#define BCM2835_ST_CS 0x0000 ///< System Timer Control/Status -#define BCM2835_ST_CLO 0x0004 ///< System Timer Counter Lower 32 bits -#define BCM2835_ST_CHI 0x0008 ///< System Timer Counter Upper 32 bits - -/// @} - - -// Defines for PWM -#define BCM2835_PWM_CONTROL 0 -#define BCM2835_PWM_STATUS 1 -#define BCM2835_PWM0_RANGE 4 -#define BCM2835_PWM0_DATA 5 -#define BCM2835_PWM1_RANGE 8 -#define BCM2835_PWM1_DATA 9 - -#define BCM2835_PWMCLK_CNTL 40 -#define BCM2835_PWMCLK_DIV 41 - -#define BCM2835_PWM1_MS_MODE 0x8000 /// Run in MS mode -#define BCM2835_PWM1_USEFIFO 0x2000 /// Data from FIFO -#define BCM2835_PWM1_REVPOLAR 0x1000 /// Reverse polarity -#define BCM2835_PWM1_OFFSTATE 0x0800 /// Ouput Off state -#define BCM2835_PWM1_REPEATFF 0x0400 /// Repeat last value if FIFO empty -#define BCM2835_PWM1_SERIAL 0x0200 /// Run in serial mode -#define BCM2835_PWM1_ENABLE 0x0100 /// Channel Enable - -#define BCM2835_PWM0_MS_MODE 0x0080 /// Run in MS mode -#define BCM2835_PWM0_USEFIFO 0x0020 /// Data from FIFO -#define BCM2835_PWM0_REVPOLAR 0x0010 /// Reverse polarity -#define BCM2835_PWM0_OFFSTATE 0x0008 /// Ouput Off state -#define BCM2835_PWM0_REPEATFF 0x0004 /// Repeat last value if FIFO empty -#define BCM2835_PWM0_SERIAL 0x0002 /// Run in serial mode -#define BCM2835_PWM0_ENABLE 0x0001 /// Channel Enable - -// Historical name compatibility -#ifndef BCM2835_NO_DELAY_COMPATIBILITY -#define delay(x) bcm2835_delay(x) -#define delayMicroseconds(x) bcm2835_delayMicroseconds(x) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - /// \defgroup init Library initialisation and management - /// These functions allow you to intialise and control the bcm2835 library - /// @{ - - /// Initialise the library by opening /dev/mem and getting pointers to the - /// internal memory for BCM 2835 device registers. You must call this (successfully) - /// before calling any other - /// functions in this library (except bcm2835_set_debug). - /// If bcm2835_init() fails by returning 0, - /// calling any other function may result in crashes or other failures. - /// Prints messages to stderr in case of errors. - /// \return 1 if successful else 0 - extern int bcm2835_init(void); - - /// Close the library, deallocating any allocated memory and closing /dev/mem - /// \return 1 if successful else 0 - extern int bcm2835_close(void); - - /// Sets the debug level of the library. - /// A value of 1 prevents mapping to /dev/mem, and makes the library print out - /// what it would do, rather than accessing the GPIO registers. - /// A value of 0, the default, causes normal operation. - /// Call this before calling bcm2835_init(); - /// \param[in] debug The new debug level. 1 means debug - extern void bcm2835_set_debug(uint8_t debug); - - /// @} // end of init - - /// \defgroup lowlevel Low level register access - /// These functions provide low level register access, and should not generally - /// need to be used - /// - /// @{ - - /// Reads 32 bit value from a peripheral address - /// The read is done twice, and is therefore always safe in terms of - /// manual section 1.3 Peripheral access precautions for correct memory ordering - /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - /// \return the value read from the 32 bit register - /// \sa Physical Addresses - extern uint32_t bcm2835_peri_read(volatile uint32_t* paddr); - - - /// Reads 32 bit value from a peripheral address without the read barrier - /// You should only use this when your code has previously called bcm2835_peri_read() - /// within the same peripheral, and no other peripheral access has occurred since. - /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - /// \return the value read from the 32 bit register - /// \sa Physical Addresses - extern uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr); - - - /// Writes 32 bit value from a peripheral address - /// The write is done twice, and is therefore always safe in terms of - /// manual section 1.3 Peripheral access precautions for correct memory ordering - /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - /// \param[in] value The 32 bit value to write - /// \sa Physical Addresses - extern void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value); - - /// Writes 32 bit value from a peripheral address without the write barrier - /// You should only use this when your code has previously called bcm2835_peri_write() - /// within the same peripheral, and no other peripheral access has occurred since. - /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - /// \param[in] value The 32 bit value to write - /// \sa Physical Addresses - extern void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value); - - /// Alters a number of bits in a 32 peripheral regsiter. - /// It reads the current valu and then alters the bits deines as 1 in mask, - /// according to the bit value in value. - /// All other bits that are 0 in the mask are unaffected. - /// Use this to alter a subset of the bits in a register. - /// The write is done twice, and is therefore always safe in terms of - /// manual section 1.3 Peripheral access precautions for correct memory ordering - /// \param[in] paddr Physical address to read from. See BCM2835_GPIO_BASE etc. - /// \param[in] value The 32 bit value to write, masked in by mask. - /// \param[in] mask Bitmask that defines the bits that will be altered in the register. - /// \sa Physical Addresses - extern void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask); - /// @} // end of lowlevel - - /// \defgroup gpio GPIO register access - /// These functions allow you to control the GPIO interface. You can set the - /// function of each GPIO pin, read the input state and set the output state. - /// @{ - - /// Sets the Function Select register for the given pin, which configures - /// the pin as Input, Output or one of the 6 alternate functions. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from RPiGPIOPin. - /// \param[in] mode Mode to set the pin to, one of BCM2835_GPIO_FSEL_* from \ref bcm2835FunctionSelect - extern void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode); - - /// Sets the specified pin output to - /// HIGH. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \sa bcm2835_gpio_write() - extern void bcm2835_gpio_set(uint8_t pin); - - /// Sets the specified pin output to - /// LOW. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \sa bcm2835_gpio_write() - extern void bcm2835_gpio_clr(uint8_t pin); - - /// Sets any of the first 32 GPIO output pins specified in the mask to - /// HIGH. - /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - /// \sa bcm2835_gpio_write_multi() - extern void bcm2835_gpio_set_multi(uint32_t mask); - - /// Sets any of the first 32 GPIO output pins specified in the mask to - /// LOW. - /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - /// \sa bcm2835_gpio_write_multi() - extern void bcm2835_gpio_clr_multi(uint32_t mask); - - /// Reads the current level on the specified - /// pin and returns either HIGH or LOW. Works whether or not the pin - /// is an input or an output. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \return the current level either HIGH or LOW - extern uint8_t bcm2835_gpio_lev(uint8_t pin); - - /// Event Detect Status. - /// Tests whether the specified pin has detected a level or edge - /// as requested by bcm2835_gpio_ren(), bcm2835_gpio_fen(), bcm2835_gpio_hen(), - /// bcm2835_gpio_len(), bcm2835_gpio_aren(), bcm2835_gpio_afen(). - /// Clear the flag for a given pin by calling bcm2835_gpio_set_eds(pin); - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \return HIGH if the event detect status for th given pin is true. - extern uint8_t bcm2835_gpio_eds(uint8_t pin); - - /// Sets the Event Detect Status register for a given pin to 1, - /// which has the effect of clearing the flag. Use this afer seeing - /// an Event Detect Status on the pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_set_eds(uint8_t pin); - - /// Enable Rising Edge Detect Enable for the specified pin. - /// When a rising edge is detected, sets the appropriate pin in Event Detect Status. - /// The GPRENn registers use - /// synchronous edge detection. This means the input signal is sampled using the - /// system clock and then it is looking for a ?011? pattern on the sampled signal. This - /// has the effect of suppressing glitches. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_ren(uint8_t pin); - - /// Disable Rising Edge Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_clr_ren(uint8_t pin); - - /// Enable Falling Edge Detect Enable for the specified pin. - /// When a falling edge is detected, sets the appropriate pin in Event Detect Status. - /// The GPRENn registers use - /// synchronous edge detection. This means the input signal is sampled using the - /// system clock and then it is looking for a ?100? pattern on the sampled signal. This - /// has the effect of suppressing glitches. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_fen(uint8_t pin); - - /// Disable Falling Edge Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_clr_fen(uint8_t pin); - - /// Enable High Detect Enable for the specified pin. - /// When a HIGH level is detected on the pin, sets the appropriate pin in Event Detect Status. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_hen(uint8_t pin); - - /// Disable High Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_clr_hen(uint8_t pin); - - /// Enable Low Detect Enable for the specified pin. - /// When a LOW level is detected on the pin, sets the appropriate pin in Event Detect Status. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_len(uint8_t pin); - - /// Disable Low Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_clr_len(uint8_t pin); - - /// Enable Asynchronous Rising Edge Detect Enable for the specified pin. - /// When a rising edge is detected, sets the appropriate pin in Event Detect Status. - /// Asynchronous means the incoming signal is not sampled by the system clock. As such - /// rising edges of very short duration can be detected. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_aren(uint8_t pin); - - /// Disable Asynchronous Rising Edge Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_clr_aren(uint8_t pin); - - /// Enable Asynchronous Falling Edge Detect Enable for the specified pin. - /// When a falling edge is detected, sets the appropriate pin in Event Detect Status. - /// Asynchronous means the incoming signal is not sampled by the system clock. As such - /// falling edges of very short duration can be detected. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_afen(uint8_t pin); - - /// Disable Asynchronous Falling Edge Detect Enable for the specified pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - extern void bcm2835_gpio_clr_afen(uint8_t pin); - - /// Sets the Pull-up/down register for the given pin. This is - /// used with bcm2835_gpio_pudclk() to set the Pull-up/down resistor for the given pin. - /// However, it is usually more convenient to use bcm2835_gpio_set_pud(). - /// \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - /// \sa bcm2835_gpio_set_pud() - extern void bcm2835_gpio_pud(uint8_t pud); - - /// Clocks the Pull-up/down value set earlier by bcm2835_gpio_pud() into the pin. - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \param[in] on HIGH to clock the value from bcm2835_gpio_pud() into the pin. - /// LOW to remove the clock. - /// \sa bcm2835_gpio_set_pud() - extern void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on); - - /// Reads and returns the Pad Control for the given GPIO group. - /// \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - /// \return Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup - extern uint32_t bcm2835_gpio_pad(uint8_t group); - - /// Sets the Pad Control for the given GPIO group. - /// \param[in] group The GPIO pad group number, one of BCM2835_PAD_GROUP_GPIO_* - /// \param[in] control Mask of bits from BCM2835_PAD_* from \ref bcm2835PadGroup - extern void bcm2835_gpio_set_pad(uint8_t group, uint32_t control); - - /// Delays for the specified number of milliseconds. - /// Uses nanosleep(), and therefore does not use CPU until the time is up. - /// However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - /// If the interval specified in req is not an exact multiple of the granularity - /// underlying clock (see time(7)), then the interval will be - /// rounded up to the next multiple. Furthermore, after the sleep completes, - /// there may still be a delay before the CPU becomes free to once - /// again execute the calling thread. - /// \param[in] millis Delay in milliseconds - extern void bcm2835_delay (unsigned int millis); - - /// Delays for the specified number of microseconds. - /// Uses a combination of nanosleep() and a busy wait loop on the BCM2835 system timers, - /// However, you are at the mercy of nanosleep(). From the manual for nanosleep(): - /// If the interval specified in req is not an exact multiple of the granularity - /// underlying clock (see time(7)), then the interval will be - /// rounded up to the next multiple. Furthermore, after the sleep completes, - /// there may still be a delay before the CPU becomes free to once - /// again execute the calling thread. - /// For times less than about 450 microseconds, uses a busy wait on the System Timer. - /// It is reported that a delay of 0 microseconds on RaspberryPi will in fact - /// result in a delay of about 80 microseconds. Your mileage may vary. - /// \param[in] micros Delay in microseconds - extern void bcm2835_delayMicroseconds (uint64_t micros); - - /// Sets the output state of the specified pin - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \param[in] on HIGH sets the output to HIGH and LOW to LOW. - extern void bcm2835_gpio_write(uint8_t pin, uint8_t on); - - /// Sets any of the first 32 GPIO output pins specified in the mask to the state given by on - /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - /// \param[in] on HIGH sets the output to HIGH and LOW to LOW. - extern void bcm2835_gpio_write_multi(uint32_t mask, uint8_t on); - - /// Sets the first 32 GPIO output pins specified in the mask to the value given by value - /// \param[in] value values required for each bit masked in by mask, eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - /// \param[in] mask Mask of pins to affect. Use eg: (1 << RPI_GPIO_P1_03) | (1 << RPI_GPIO_P1_05) - extern void bcm2835_gpio_write_mask(uint32_t value, uint32_t mask); - - /// Sets the Pull-up/down mode for the specified pin. This is more convenient than - /// clocking the mode in with bcm2835_gpio_pud() and bcm2835_gpio_pudclk(). - /// \param[in] pin GPIO number, or one of RPI_GPIO_P1_* from \ref RPiGPIOPin. - /// \param[in] pud The desired Pull-up/down mode. One of BCM2835_GPIO_PUD_* from bcm2835PUDControl - extern void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud); - - /// @} - - /// \defgroup spi SPI access - /// These functions let you use SPI0 (Serial Peripheral Interface) to - /// interface with an external SPI device. - /// @{ - - /// Start SPI operations. - /// Forces RPi SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - /// to alternate function ALT0, which enables those pins for SPI interface. - /// You should call bcm2835_spi_end() when all SPI funcitons are complete to return the pins to - /// their default functions - /// \sa bcm2835_spi_end() - extern void bcm2835_spi_begin(void); - - /// End SPI operations. - /// SPI0 pins P1-19 (MOSI), P1-21 (MISO), P1-23 (CLK), P1-24 (CE0) and P1-26 (CE1) - /// are returned to their default INPUT behaviour. - extern void bcm2835_spi_end(void); - - /// Sets the SPI bit order - /// NOTE: has no effect. Not supported by SPI0. - /// Defaults to - /// \param[in] order The desired bit order, one of BCM2835_SPI_BIT_ORDER_*, - /// see \ref bcm2835SPIBitOrder - extern void bcm2835_spi_setBitOrder(uint8_t order); - - /// Sets the SPI clock divider and therefore the - /// SPI clock speed. - /// \param[in] divider The desired SPI clock divider, one of BCM2835_SPI_CLOCK_DIVIDER_*, - /// see \ref bcm2835SPIClockDivider - extern void bcm2835_spi_setClockDivider(uint16_t divider); - - /// Sets the SPI data mode - /// Sets the clock polariy and phase - /// \param[in] mode The desired data mode, one of BCM2835_SPI_MODE*, - /// see \ref bcm2835SPIMode - extern void bcm2835_spi_setDataMode(uint8_t mode); - - /// Sets the chip select pin(s) - /// When an bcm2835_spi_transfer() is made, the selected pin(s) will be asserted during the - /// transfer. - /// \param[in] cs Specifies the CS pins(s) that are used to activate the desired slave. - /// One of BCM2835_SPI_CS*, see \ref bcm2835SPIChipSelect - extern void bcm2835_spi_chipSelect(uint8_t cs); - - /// Sets the chip select pin polarity for a given pin - /// When an bcm2835_spi_transfer() occurs, the currently selected chip select pin(s) - /// will be asserted to the - /// value given by active. When transfers are not happening, the chip select pin(s) - /// return to the complement (inactive) value. - /// \param[in] cs The chip select pin to affect - /// \param[in] active Whether the chip select pin is to be active HIGH - extern void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active); - - /// Transfers one byte to and from the currently selected SPI slave. - /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - /// during the transfer. - /// Clocks the 8 bit value out on MOSI, and simultaneously clocks in data from MISO. - /// Returns the read data byte from the slave. - /// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - /// \param[in] value The 8 bit data byte to write to MOSI - /// \return The 8 bit byte simultaneously read from MISO - /// \sa bcm2835_spi_transfern() - extern uint8_t bcm2835_spi_transfer(uint8_t value); - - /// Transfers any number of bytes to and from the currently selected SPI slave. - /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - /// during the transfer. - /// Clocks the len 8 bit bytes out on MOSI, and simultaneously clocks in data from MISO. - /// The data read read from the slave is placed into rbuf. rbuf must be at least len bytes long - /// Uses polled transfer as per section 10.6.1 of the BCM 2835 ARM Peripherls manual - /// \param[in] tbuf Buffer of bytes to send. - /// \param[out] rbuf Received bytes will by put in this buffer - /// \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send/received - /// \sa bcm2835_spi_transfer() - extern void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len); - - /// Transfers any number of bytes to and from the currently selected SPI slave - /// using bcm2835_spi_transfernb. - /// The returned data from the slave replaces the transmitted data in the buffer. - /// \param[in,out] buf Buffer of bytes to send. Received bytes will replace the contents - /// \param[in] len Number of bytes int eh buffer, and the number of bytes to send/received - /// \sa bcm2835_spi_transfer() - extern void bcm2835_spi_transfern(char* buf, uint32_t len); - - /// Transfers any number of bytes to the currently selected SPI slave. - /// Asserts the currently selected CS pins (as previously set by bcm2835_spi_chipSelect) - /// during the transfer. - /// \param[in] buf Buffer of bytes to send. - /// \param[in] len Number of bytes in the tbuf buffer, and the number of bytes to send - extern void bcm2835_spi_writenb(char* buf, uint32_t len); - - /// @} - - /// \defgroup i2c I2C access - /// These functions let you use I2C (The Broadcom Serial Control bus with the Philips - /// I2C bus/interface version 2.1 January 2000.) to interface with an external I2C device. - /// @{ - - /// Start I2C operations. - /// Forces RPi I2C pins P1-03 (SDA) and P1-05 (SCL) - /// to alternate function ALT0, which enables those pins for I2C interface. - /// You should call bcm2835_i2c_end() when all I2C functions are complete to return the pins to - /// their default functions - /// \sa bcm2835_i2c_end() - extern void bcm2835_i2c_begin(void); - - /// End I2C operations. - /// I2C pins P1-03 (SDA) and P1-05 (SCL) - /// are returned to their default INPUT behaviour. - extern void bcm2835_i2c_end(void); - - /// Sets the I2C slave address. - /// \param[in] addr The I2C slave address. - extern void bcm2835_i2c_setSlaveAddress(uint8_t addr); - - /// Sets the I2C clock divider and therefore the I2C clock speed. - /// \param[in] divider The desired I2C clock divider, one of BCM2835_I2C_CLOCK_DIVIDER_*, - /// see \ref bcm2835I2CClockDivider - extern void bcm2835_i2c_setClockDivider(uint16_t divider); - - /// Sets the I2C clock divider by converting the baudrate parameter to - /// the equivalent I2C clock divider. ( see \sa bcm2835_i2c_setClockDivider) - /// For the I2C standard 100khz you would set baudrate to 100000 - /// The use of baudrate corresponds to its use in the I2C kernel device - /// driver. (Of course, bcm2835 has nothing to do with the kernel driver) - extern void bcm2835_i2c_set_baudrate(uint32_t baudrate); - - /// Transfers any number of bytes to the currently selected I2C slave. - /// (as previously set by \sa bcm2835_i2c_setSlaveAddress) - /// \param[in] buf Buffer of bytes to send. - /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to send. - /// \return reason see \ref bcm2835I2CReasonCodes - extern uint8_t bcm2835_i2c_write(const char * buf, uint32_t len); - - /// Transfers any number of bytes from the currently selected I2C slave. - /// (as previously set by \sa bcm2835_i2c_setSlaveAddress) - /// \param[in] buf Buffer of bytes to receive. - /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - /// \return reason see \ref bcm2835I2CReasonCodes - extern uint8_t bcm2835_i2c_read(char* buf, uint32_t len); - - /// Allows reading from I2C slaves that require a repeated start (without any prior stop) - /// to read after the required slave register has been set. For example, the popular - /// MPL3115A2 pressure and temperature sensor. Note that your device must support or - /// require this mode. If your device does not require this mode then the standard - /// combined: - /// \sa bcm2835_i2c_write - /// \sa bcm2835_i2c_read - /// are a better choice. - /// Will read from the slave previously set by \sa bcm2835_i2c_setSlaveAddress - /// \param[in] regaddr Buffer containing the slave register you wish to read from. - /// \param[in] buf Buffer of bytes to receive. - /// \param[in] len Number of bytes in the buf buffer, and the number of bytes to received. - /// \return reason see \ref bcm2835I2CReasonCodes - extern uint8_t bcm2835_i2c_read_register_rs(char* regaddr, char* buf, uint32_t len); - - /// @} - - /// \defgroup st System Timer access - /// Allows access to and delays using the System Timer Counter. - /// @{ - - /// Read the System Timer Counter register. - /// \return the value read from the System Timer Counter Lower 32 bits register - uint64_t bcm2835_st_read(void); - - /// Delays for the specified number of microseconds with offset. - /// \param[in] offset_micros Offset in microseconds - /// \param[in] micros Delay in microseconds - extern void bcm2835_st_delay(uint64_t offset_micros, uint64_t micros); - - /// @} - -#ifdef __cplusplus -} -#endif - -#endif // BCM2835_H - -/// @example blink.c -/// Blinks RPi GPIO pin 11 on and off - -/// @example input.c -/// Reads the state of an RPi input pin - -/// @example event.c -/// Shows how to use event detection on an input pin - -/// @example spi.c -/// Shows how to use SPI interface to transfer a byte to and from an SPI device - -/// @example spin.c -/// Shows how to use SPI interface to transfer a number of bytes to and from an SPI device diff --git a/samples/C++/crypter.cpp b/samples/C++/crypter.cpp new file mode 100644 index 00000000..255bdf11 --- /dev/null +++ b/samples/C++/crypter.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2009-2012 The Bitcoin Developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +// Source - https://github.com/Bradfrogger/Marvelous/blob/master/src/crypter.cpp + +#include +#include +#include +#include +#ifdef WIN32 +#include +#endif + +#include "crypter.h" + +bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod) +{ + if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE) + return false; + + int i = 0; + if (nDerivationMethod == 0) + i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], + (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV); + + if (i != (int)WALLET_CRYPTO_KEY_SIZE) + { + OPENSSL_cleanse(chKey, sizeof(chKey)); + OPENSSL_cleanse(chIV, sizeof(chIV)); + return false; + } + + fKeySet = true; + return true; +} + +bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector& chNewIV) +{ + if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE) + return false; + + memcpy(&chKey[0], &chNewKey[0], sizeof chKey); + memcpy(&chIV[0], &chNewIV[0], sizeof chIV); + + fKeySet = true; + return true; +} + +bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector &vchCiphertext) +{ + if (!fKeySet) + return false; + + // max ciphertext len for a n bytes of plaintext is + // n + AES_BLOCK_SIZE - 1 bytes + int nLen = vchPlaintext.size(); + int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0; + vchCiphertext = std::vector (nCLen); + + EVP_CIPHER_CTX ctx; + + bool fOk = true; + + EVP_CIPHER_CTX_init(&ctx); + if (fOk) fOk = EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); + if (fOk) fOk = EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen); + if (fOk) fOk = EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen); + EVP_CIPHER_CTX_cleanup(&ctx); + + if (!fOk) return false; + + vchCiphertext.resize(nCLen + nFLen); + return true; +} + +bool CCrypter::Decrypt(const std::vector& vchCiphertext, CKeyingMaterial& vchPlaintext) +{ + if (!fKeySet) + return false; + + // plaintext will always be equal to or lesser than length of ciphertext + int nLen = vchCiphertext.size(); + int nPLen = nLen, nFLen = 0; + + vchPlaintext = CKeyingMaterial(nPLen); + + EVP_CIPHER_CTX ctx; + + bool fOk = true; + + EVP_CIPHER_CTX_init(&ctx); + if (fOk) fOk = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); + if (fOk) fOk = EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); + if (fOk) fOk = EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen); + EVP_CIPHER_CTX_cleanup(&ctx); + + if (!fOk) return false; + + vchPlaintext.resize(nPLen + nFLen); + return true; +} + + +bool EncryptSecret(const CKeyingMaterial& vMasterKey, const CKeyingMaterial &vchPlaintext, const uint256& nIV, std::vector &vchCiphertext) +{ + CCrypter cKeyCrypter; + std::vector chIV(WALLET_CRYPTO_KEY_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + if(!cKeyCrypter.SetKey(vMasterKey, chIV)) + return false; + return cKeyCrypter.Encrypt(*((const CKeyingMaterial*)&vchPlaintext), vchCiphertext); +} + +bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector& vchCiphertext, const uint256& nIV, CKeyingMaterial& vchPlaintext) +{ + CCrypter cKeyCrypter; + std::vector chIV(WALLET_CRYPTO_KEY_SIZE); + memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); + if(!cKeyCrypter.SetKey(vMasterKey, chIV)) + return false; + return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)); +} diff --git a/samples/C++/graphics.cpp b/samples/C++/graphics.cpp new file mode 100644 index 00000000..b4ba9444 --- /dev/null +++ b/samples/C++/graphics.cpp @@ -0,0 +1,109 @@ +// License - https://github.com/TurtleP/Flask/blob/master/LICENSE + +#include + +int currentR = 0xFF; +int currentG = 0xFF; +int currentB = 0xFF; +int currentA = 0xFF; + +int currentScreen = GFX_BOTTOM; + +float transX = 0; +float transY = 0; +bool isPushed = false; + +u32 getCurrentColor() +{ + return RGBA8(currentR, currentG, currentB, currentA); +} + +void setColor(int r, int g, int b) +{ + currentR = r; + currentG = g; + currentB = b; + currentA = currentA; +} + +void setColor(int r, int g, int b, int a) +{ + currentR = r; + currentG = g; + currentB = b; + currentA = a; +} + +void setScreen(int screen) +{ + currentScreen = screen; +} + +int getCurrentScreen() +{ + return currentScreen; +} + +void screenShot() //for showing stuff being done +{ + FILE * topScreen = fopen("sdmc:/framebuffer_top.rgb", "w+"); + + fwrite(gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 288000, 1, topScreen); + + fclose(topScreen); + + FILE * bottomScreen = fopen("sdmc:/framebuffer_bottom.rgb", "w+");; + + fwrite(gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL), 230400, 1, bottomScreen); + + fclose(bottomScreen); +} + +void translateCoords(float * x, float * y) { + if (isPushed) + { + *x += transX; + *y += transY; + } +} + +void translate(float dx, float dy) +{ + if (sf2d_get_current_screen() == getCurrentScreen()) + { + transX = transX + dx; + transY = transY + dy; + } +} + +void push() +{ + if (sf2d_get_current_screen() == getCurrentScreen()) + { + isPushed = true; + } +} + +void pop() +{ + if (sf2d_get_current_screen() == getCurrentScreen()) + { + transX = 0; + transY = 0; + isPushed = false; + } +} + +void setScissor(u32 x, u32 y, u32 width, u32 height) +{ + if (sf2d_get_current_screen() == getCurrentScreen()) + { + GPU_SCISSORMODE mode = GPU_SCISSOR_NORMAL; + + if (!x && !y && !width && !height) { + mode = GPU_SCISSOR_DISABLE; + } + + sf2d_set_scissor_test(mode, x, y, width, height); + } +} \ No newline at end of file diff --git a/samples/C++/json_reader.cpp b/samples/C++/json_reader.cpp new file mode 100644 index 00000000..d8943887 --- /dev/null +++ b/samples/C++/json_reader.cpp @@ -0,0 +1,920 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +/* +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: + +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. +*/ + +// Source - https://github.com/Ij888/ApacheCordovaRecipes/blob/6e8a2c1d9de7302f74bc3dbac54a021f0499bbb3/jqmsandbox/plugins/cordova-plugin-globalization/src/blackberry10/native/public/json_reader.cpp + +#include +#include +#include +#include +#include +#include +#include +#include + +#if _MSC_VER >= 1400 // VC++ 8.0 +#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. +#endif + +namespace Json { + +// QNX is strict about declaring C symbols in the std namespace. +#ifdef __QNXNTO__ +using std::memcpy; +using std::sprintf; +using std::sscanf; +#endif + +// Implementation of class Features +// //////////////////////////////// + +Features::Features() + : allowComments_( true ) + , strictRoot_( false ) +{ +} + + +Features +Features::all() +{ + return Features(); +} + + +Features +Features::strictMode() +{ + Features features; + features.allowComments_ = false; + features.strictRoot_ = true; + return features; +} + +// Implementation of class Reader +// //////////////////////////////// + + +static inline bool +in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 ) +{ + return c == c1 || c == c2 || c == c3 || c == c4; +} + +static inline bool +in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 ) +{ + return c == c1 || c == c2 || c == c3 || c == c4 || c == c5; +} + + +static bool +containsNewLine( Reader::Location begin, + Reader::Location end ) +{ + for ( ;begin < end; ++begin ) + if ( *begin == '\n' || *begin == '\r' ) + return true; + return false; +} + +static std::string codePointToUTF8(unsigned int cp) +{ + std::string result; + + // based on description from http://en.wikipedia.org/wiki/UTF-8 + + if (cp <= 0x7f) + { + result.resize(1); + result[0] = static_cast(cp); + } + else if (cp <= 0x7FF) + { + result.resize(2); + result[1] = static_cast(0x80 | (0x3f & cp)); + result[0] = static_cast(0xC0 | (0x1f & (cp >> 6))); + } + else if (cp <= 0xFFFF) + { + result.resize(3); + result[2] = static_cast(0x80 | (0x3f & cp)); + result[1] = 0x80 | static_cast((0x3f & (cp >> 6))); + result[0] = 0xE0 | static_cast((0xf & (cp >> 12))); + } + else if (cp <= 0x10FFFF) + { + result.resize(4); + result[3] = static_cast(0x80 | (0x3f & cp)); + result[2] = static_cast(0x80 | (0x3f & (cp >> 6))); + result[1] = static_cast(0x80 | (0x3f & (cp >> 12))); + result[0] = static_cast(0xF0 | (0x7 & (cp >> 18))); + } + + return result; +} + + +// Class Reader +// ////////////////////////////////////////////////////////////////// + +Reader::Reader() + : features_( Features::all() ) +{ +} + + +Reader::Reader( const Features &features ) + : features_( features ) +{ +} + + +bool +Reader::parse( const std::string &document, + Value &root, + bool collectComments ) +{ + document_ = document; + const char *begin = document_.c_str(); + const char *end = begin + document_.length(); + return parse( begin, end, root, collectComments ); +} + + +bool +Reader::parse( std::istream& sin, + Value &root, + bool collectComments ) +{ + //std::istream_iterator begin(sin); + //std::istream_iterator end; + // Those would allow streamed input from a file, if parse() were a + // template function. + + // Since std::string is reference-counted, this at least does not + // create an extra copy. + std::string doc; + std::getline(sin, doc, (char)EOF); + return parse( doc, root, collectComments ); +} + +bool +Reader::parse( const char *beginDoc, const char *endDoc, + Value &root, + bool collectComments ) +{ + if ( !features_.allowComments_ ) + { + collectComments = false; + } + + begin_ = beginDoc; + end_ = endDoc; + collectComments_ = collectComments; + current_ = begin_; + lastValueEnd_ = 0; + lastValue_ = 0; + commentsBefore_ = ""; + errors_.clear(); + while ( !nodes_.empty() ) + nodes_.pop(); + nodes_.push( &root ); + + bool successful = readValue(); + Token token; + skipCommentTokens( token ); + if ( collectComments_ && !commentsBefore_.empty() ) + root.setComment( commentsBefore_, commentAfter ); + if ( features_.strictRoot_ ) + { + if ( !root.isArray() && !root.isObject() ) + { + // Set error location to start of doc, ideally should be first token found in doc + token.type_ = tokenError; + token.start_ = beginDoc; + token.end_ = endDoc; + addError( "A valid JSON document must be either an array or an object value.", + token ); + return false; + } + } + return successful; +} + + +bool +Reader::readValue() +{ + Token token; + skipCommentTokens( token ); + bool successful = true; + + if ( collectComments_ && !commentsBefore_.empty() ) + { + currentValue().setComment( commentsBefore_, commentBefore ); + commentsBefore_ = ""; + } + + + switch ( token.type_ ) + { + case tokenObjectBegin: + successful = readObject( token ); + break; + case tokenArrayBegin: + successful = readArray( token ); + break; + case tokenNumber: + successful = decodeNumber( token ); + break; + case tokenString: + successful = decodeString( token ); + break; + case tokenTrue: + currentValue() = true; + break; + case tokenFalse: + currentValue() = false; + break; + case tokenNull: + currentValue() = Value(); + break; + default: + return addError( "Syntax error: value, object or array expected.", token ); + } + + if ( collectComments_ ) + { + lastValueEnd_ = current_; + lastValue_ = ¤tValue(); + } + + return successful; +} + + +void +Reader::skipCommentTokens( Token &token ) +{ + if ( features_.allowComments_ ) + { + do + { + readToken( token ); + } + while ( token.type_ == tokenComment ); + } + else + { + readToken( token ); + } +} + + +bool +Reader::expectToken( TokenType type, Token &token, const char *message ) +{ + readToken( token ); + if ( token.type_ != type ) + return addError( message, token ); + return true; +} + + +bool +Reader::readToken( Token &token ) +{ + skipSpaces(); + token.start_ = current_; + Char c = getNextChar(); + bool ok = true; + switch ( c ) + { + case '{': + token.type_ = tokenObjectBegin; + break; + case '}': + token.type_ = tokenObjectEnd; + break; + case '[': + token.type_ = tokenArrayBegin; + break; + case ']': + token.type_ = tokenArrayEnd; + break; + case '"': + token.type_ = tokenString; + ok = readString(); + break; + case '/': + token.type_ = tokenComment; + ok = readComment(); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + token.type_ = tokenNumber; + readNumber(); + break; + case 't': + token.type_ = tokenTrue; + ok = match( "rue", 3 ); + break; + case 'f': + token.type_ = tokenFalse; + ok = match( "alse", 4 ); + break; + case 'n': + token.type_ = tokenNull; + ok = match( "ull", 3 ); + break; + case ',': + token.type_ = tokenArraySeparator; + break; + case ':': + token.type_ = tokenMemberSeparator; + break; + case 0: + token.type_ = tokenEndOfStream; + break; + default: + ok = false; + break; + } + if ( !ok ) + token.type_ = tokenError; + token.end_ = current_; + return true; +} + + +void +Reader::skipSpaces() +{ + while ( current_ != end_ ) + { + Char c = *current_; + if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ) + ++current_; + else + break; + } +} + + +bool +Reader::match( Location pattern, + int patternLength ) +{ + if ( end_ - current_ < patternLength ) + return false; + int index = patternLength; + while ( index-- ) + if ( current_[index] != pattern[index] ) + return false; + current_ += patternLength; + return true; +} + + +bool +Reader::readComment() +{ + Location commentBegin = current_ - 1; + Char c = getNextChar(); + bool successful = false; + if ( c == '*' ) + successful = readCStyleComment(); + else if ( c == '/' ) + successful = readCppStyleComment(); + if ( !successful ) + return false; + + if ( collectComments_ ) + { + CommentPlacement placement = commentBefore; + if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) ) + { + if ( c != '*' || !containsNewLine( commentBegin, current_ ) ) + placement = commentAfterOnSameLine; + } + + addComment( commentBegin, current_, placement ); + } + return true; +} + + +void +Reader::addComment( Location begin, + Location end, + CommentPlacement placement ) +{ + assert( collectComments_ ); + if ( placement == commentAfterOnSameLine ) + { + assert( lastValue_ != 0 ); + lastValue_->setComment( std::string( begin, end ), placement ); + } + else + { + if ( !commentsBefore_.empty() ) + commentsBefore_ += "\n"; + commentsBefore_ += std::string( begin, end ); + } +} + + +bool +Reader::readCStyleComment() +{ + while ( current_ != end_ ) + { + Char c = getNextChar(); + if ( c == '*' && *current_ == '/' ) + break; + } + return getNextChar() == '/'; +} + + +bool +Reader::readCppStyleComment() +{ + while ( current_ != end_ ) + { + Char c = getNextChar(); + if ( c == '\r' || c == '\n' ) + break; + } + return true; +} + + +void +Reader::readNumber() +{ + while ( current_ != end_ ) + { + if ( !(*current_ >= '0' && *current_ <= '9') && + !in( *current_, '.', 'e', 'E', '+', '-' ) ) + break; + ++current_; + } +} + +bool +Reader::readString() +{ + Char c = 0; + while ( current_ != end_ ) + { + c = getNextChar(); + if ( c == '\\' ) + getNextChar(); + else if ( c == '"' ) + break; + } + return c == '"'; +} + + +bool +Reader::readObject( Token &tokenStart ) +{ + Token tokenName; + std::string name; + currentValue() = Value( objectValue ); + while ( readToken( tokenName ) ) + { + bool initialTokenOk = true; + while ( tokenName.type_ == tokenComment && initialTokenOk ) + initialTokenOk = readToken( tokenName ); + if ( !initialTokenOk ) + break; + if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object + return true; + if ( tokenName.type_ != tokenString ) + break; + + name = ""; + if ( !decodeString( tokenName, name ) ) + return recoverFromError( tokenObjectEnd ); + + Token colon; + if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator ) + { + return addErrorAndRecover( "Missing ':' after object member name", + colon, + tokenObjectEnd ); + } + Value &value = currentValue()[ name ]; + nodes_.push( &value ); + bool ok = readValue(); + nodes_.pop(); + if ( !ok ) // error already set + return recoverFromError( tokenObjectEnd ); + + Token comma; + if ( !readToken( comma ) + || ( comma.type_ != tokenObjectEnd && + comma.type_ != tokenArraySeparator && + comma.type_ != tokenComment ) ) + { + return addErrorAndRecover( "Missing ',' or '}' in object declaration", + comma, + tokenObjectEnd ); + } + bool finalizeTokenOk = true; + while ( comma.type_ == tokenComment && + finalizeTokenOk ) + finalizeTokenOk = readToken( comma ); + if ( comma.type_ == tokenObjectEnd ) + return true; + } + return addErrorAndRecover( "Missing '}' or object member name", + tokenName, + tokenObjectEnd ); +} + + +bool +Reader::readArray( Token &tokenStart ) +{ + currentValue() = Value( arrayValue ); + skipSpaces(); + if ( *current_ == ']' ) // empty array + { + Token endArray; + readToken( endArray ); + return true; + } + int index = 0; + while ( true ) + { + Value &value = currentValue()[ index++ ]; + nodes_.push( &value ); + bool ok = readValue(); + nodes_.pop(); + if ( !ok ) // error already set + return recoverFromError( tokenArrayEnd ); + + Token token; + // Accept Comment after last item in the array. + ok = readToken( token ); + while ( token.type_ == tokenComment && ok ) + { + ok = readToken( token ); + } + bool badTokenType = ( token.type_ == tokenArraySeparator && + token.type_ == tokenArrayEnd ); + if ( !ok || badTokenType ) + { + return addErrorAndRecover( "Missing ',' or ']' in array declaration", + token, + tokenArrayEnd ); + } + if ( token.type_ == tokenArrayEnd ) + break; + } + return true; +} + + +bool +Reader::decodeNumber( Token &token ) +{ + bool isDouble = false; + for ( Location inspect = token.start_; inspect != token.end_; ++inspect ) + { + isDouble = isDouble + || in( *inspect, '.', 'e', 'E', '+' ) + || ( *inspect == '-' && inspect != token.start_ ); + } + if ( isDouble ) + return decodeDouble( token ); + Location current = token.start_; + bool isNegative = *current == '-'; + if ( isNegative ) + ++current; + Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt) + : Value::maxUInt) / 10; + Value::UInt value = 0; + while ( current < token.end_ ) + { + Char c = *current++; + if ( c < '0' || c > '9' ) + return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); + if ( value >= threshold ) + return decodeDouble( token ); + value = value * 10 + Value::UInt(c - '0'); + } + if ( isNegative ) + currentValue() = -Value::Int( value ); + else if ( value <= Value::UInt(Value::maxInt) ) + currentValue() = Value::Int( value ); + else + currentValue() = value; + return true; +} + + +bool +Reader::decodeDouble( Token &token ) +{ + double value = 0; + const int bufferSize = 32; + int count; + int length = int(token.end_ - token.start_); + if ( length <= bufferSize ) + { + Char buffer[bufferSize]; + memcpy( buffer, token.start_, length ); + buffer[length] = 0; + count = sscanf( buffer, "%lf", &value ); + } + else + { + std::string buffer( token.start_, token.end_ ); + count = sscanf( buffer.c_str(), "%lf", &value ); + } + + if ( count != 1 ) + return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token ); + currentValue() = value; + return true; +} + + +bool +Reader::decodeString( Token &token ) +{ + std::string decoded; + if ( !decodeString( token, decoded ) ) + return false; + currentValue() = decoded; + return true; +} + + +bool +Reader::decodeString( Token &token, std::string &decoded ) +{ + decoded.reserve( token.end_ - token.start_ - 2 ); + Location current = token.start_ + 1; // skip '"' + Location end = token.end_ - 1; // do not include '"' + while ( current != end ) + { + Char c = *current++; + if ( c == '"' ) + break; + else if ( c == '\\' ) + { + if ( current == end ) + return addError( "Empty escape sequence in string", token, current ); + Char escape = *current++; + switch ( escape ) + { + case '"': decoded += '"'; break; + case '/': decoded += '/'; break; + case '\\': decoded += '\\'; break; + case 'b': decoded += '\b'; break; + case 'f': decoded += '\f'; break; + case 'n': decoded += '\n'; break; + case 'r': decoded += '\r'; break; + case 't': decoded += '\t'; break; + case 'u': + { + unsigned int unicode; + if ( !decodeUnicodeCodePoint( token, current, end, unicode ) ) + return false; + decoded += codePointToUTF8(unicode); + } + break; + default: + return addError( "Bad escape sequence in string", token, current ); + } + } + else + { + decoded += c; + } + } + return true; +} + +bool +Reader::decodeUnicodeCodePoint( Token &token, + Location ¤t, + Location end, + unsigned int &unicode ) +{ + + if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) ) + return false; + if (unicode >= 0xD800 && unicode <= 0xDBFF) + { + // surrogate pairs + if (end - current < 6) + return addError( "additional six characters expected to parse unicode surrogate pair.", token, current ); + unsigned int surrogatePair; + if (*(current++) == '\\' && *(current++)== 'u') + { + if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair )) + { + unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); + } + else + return false; + } + else + return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current ); + } + return true; +} + +bool +Reader::decodeUnicodeEscapeSequence( Token &token, + Location ¤t, + Location end, + unsigned int &unicode ) +{ + if ( end - current < 4 ) + return addError( "Bad unicode escape sequence in string: four digits expected.", token, current ); + unicode = 0; + for ( int index =0; index < 4; ++index ) + { + Char c = *current++; + unicode *= 16; + if ( c >= '0' && c <= '9' ) + unicode += c - '0'; + else if ( c >= 'a' && c <= 'f' ) + unicode += c - 'a' + 10; + else if ( c >= 'A' && c <= 'F' ) + unicode += c - 'A' + 10; + else + return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current ); + } + return true; +} + + +bool +Reader::addError( const std::string &message, + Token &token, + Location extra ) +{ + ErrorInfo info; + info.token_ = token; + info.message_ = message; + info.extra_ = extra; + errors_.push_back( info ); + return false; +} + + +bool +Reader::recoverFromError( TokenType skipUntilToken ) +{ + int errorCount = int(errors_.size()); + Token skip; + while ( true ) + { + if ( !readToken(skip) ) + errors_.resize( errorCount ); // discard errors caused by recovery + if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream ) + break; + } + errors_.resize( errorCount ); + return false; +} + + +bool +Reader::addErrorAndRecover( const std::string &message, + Token &token, + TokenType skipUntilToken ) +{ + addError( message, token ); + return recoverFromError( skipUntilToken ); +} + + +Value & +Reader::currentValue() +{ + return *(nodes_.top()); +} + + +Reader::Char +Reader::getNextChar() +{ + if ( current_ == end_ ) + return 0; + return *current_++; +} + + +void +Reader::getLocationLineAndColumn( Location location, + int &line, + int &column ) const +{ + Location current = begin_; + Location lastLineStart = current; + line = 0; + while ( current < location && current != end_ ) + { + Char c = *current++; + if ( c == '\r' ) + { + if ( *current == '\n' ) + ++current; + lastLineStart = current; + ++line; + } + else if ( c == '\n' ) + { + lastLineStart = current; + ++line; + } + } + // column & line start at 1 + column = int(location - lastLineStart) + 1; + ++line; +} + + +std::string +Reader::getLocationLineAndColumn( Location location ) const +{ + int line, column; + getLocationLineAndColumn( location, line, column ); + char buffer[18+16+16+1]; + sprintf( buffer, "Line %d, Column %d", line, column ); + return buffer; +} + + +std::string +Reader::getFormatedErrorMessages() const +{ + std::string formattedMessage; + for ( Errors::const_iterator itError = errors_.begin(); + itError != errors_.end(); + ++itError ) + { + const ErrorInfo &error = *itError; + formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n"; + formattedMessage += " " + error.message_ + "\n"; + if ( error.extra_ ) + formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n"; + } + return formattedMessage; +} + + +std::istream& operator>>( std::istream &sin, Value &root ) +{ + Json::Reader reader; + bool ok = reader.parse(sin, root, true); + //JSON_ASSERT( ok ); + if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages()); + return sin; +} + + +} // namespace Json diff --git a/samples/C++/json_writer.cpp b/samples/C++/json_writer.cpp new file mode 100644 index 00000000..6c18d29c --- /dev/null +++ b/samples/C++/json_writer.cpp @@ -0,0 +1,857 @@ +// Copyright 2007-2010 Baptiste Lepilleur +// Distributed under MIT license, or public domain if desired and +// recognized in your jurisdiction. +// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE + +/* +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: + +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. +*/ + +// Source - https://github.com/Ij888/ApacheCordovaRecipes/blob/6e8a2c1d9de7302f74bc3dbac54a021f0499bbb3/jqmsandbox/plugins/cordova-plugin-globalization/src/blackberry10/native/public/json_writer.cpp + +#include +#include +#include +#include +#include +#include +#include +#include + +#if _MSC_VER >= 1400 // VC++ 8.0 +#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated. +#endif + +namespace Json { + +static bool isControlCharacter(char ch) +{ + return ch > 0 && ch <= 0x1F; +} + +static bool containsControlCharacter( const char* str ) +{ + while ( *str ) + { + if ( isControlCharacter( *(str++) ) ) + return true; + } + return false; +} +static void uintToString( unsigned int value, + char *¤t ) +{ + *--current = 0; + do + { + *--current = (value % 10) + '0'; + value /= 10; + } + while ( value != 0 ); +} + +std::string valueToString( Int value ) +{ + char buffer[32]; + char *current = buffer + sizeof(buffer); + bool isNegative = value < 0; + if ( isNegative ) + value = -value; + uintToString( UInt(value), current ); + if ( isNegative ) + *--current = '-'; + assert( current >= buffer ); + return current; +} + + +std::string valueToString( UInt value ) +{ + char buffer[32]; + char *current = buffer + sizeof(buffer); + uintToString( value, current ); + assert( current >= buffer ); + return current; +} + +std::string valueToString( double value ) +{ + char buffer[32]; +#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning. + sprintf_s(buffer, sizeof(buffer), "%#.16g", value); +#else + sprintf(buffer, "%#.16g", value); +#endif + char* ch = buffer + strlen(buffer) - 1; + if (*ch != '0') return buffer; // nothing to truncate, so save time + while(ch > buffer && *ch == '0'){ + --ch; + } + char* last_nonzero = ch; + while(ch >= buffer){ + switch(*ch){ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + --ch; + continue; + case '.': + // Truncate zeroes to save bytes in output, but keep one. + *(last_nonzero+2) = '\0'; + return buffer; + default: + return buffer; + } + } + return buffer; +} + + +std::string valueToString( bool value ) +{ + return value ? "true" : "false"; +} + +std::string valueToQuotedString( const char *value ) +{ + // Not sure how to handle unicode... + if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value )) + return std::string("\"") + value + "\""; + // We have to walk value and escape any special characters. + // Appending to std::string is not efficient, but this should be rare. + // (Note: forward slashes are *not* rare, but I am not escaping them.) + unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL + std::string result; + result.reserve(maxsize); // to avoid lots of mallocs + result += "\""; + for (const char* c=value; *c != 0; ++c) + { + switch(*c) + { + case '\"': + result += "\\\""; + break; + case '\\': + result += "\\\\"; + break; + case '\b': + result += "\\b"; + break; + case '\f': + result += "\\f"; + break; + case '\n': + result += "\\n"; + break; + case '\r': + result += "\\r"; + break; + case '\t': + result += "\\t"; + break; + //case '/': + // Even though \/ is considered a legal escape in JSON, a bare + // slash is also legal, so I see no reason to escape it. + // (I hope I am not misunderstanding something. + // blep notes: actually escaping \/ may be useful in javascript to avoid (*c); + result += oss.str(); + } + else + { + result += *c; + } + break; + } + } + result += "\""; + return result; +} + +// Class Writer +// ////////////////////////////////////////////////////////////////// +Writer::~Writer() +{ +} + + +// Class FastWriter +// ////////////////////////////////////////////////////////////////// + +FastWriter::FastWriter() + : yamlCompatiblityEnabled_( false ) +{ +} + + +void +FastWriter::enableYAMLCompatibility() +{ + yamlCompatiblityEnabled_ = true; +} + + +std::string +FastWriter::write( const Value &root ) +{ + document_ = ""; + writeValue( root ); + document_ += "\n"; + return document_; +} + + +void +FastWriter::writeValue( const Value &value ) +{ + switch ( value.type() ) + { + case nullValue: + document_ += "null"; + break; + case intValue: + document_ += valueToString( value.asInt() ); + break; + case uintValue: + document_ += valueToString( value.asUInt() ); + break; + case realValue: + document_ += valueToString( value.asDouble() ); + break; + case stringValue: + document_ += valueToQuotedString( value.asCString() ); + break; + case booleanValue: + document_ += valueToString( value.asBool() ); + break; + case arrayValue: + { + document_ += "["; + int size = value.size(); + for ( int index =0; index < size; ++index ) + { + if ( index > 0 ) + document_ += ","; + writeValue( value[index] ); + } + document_ += "]"; + } + break; + case objectValue: + { + Value::Members members( value.getMemberNames() ); + document_ += "{"; + for ( Value::Members::iterator it = members.begin(); + it != members.end(); + ++it ) + { + const std::string &name = *it; + if ( it != members.begin() ) + document_ += ","; + document_ += valueToQuotedString( name.c_str() ); + document_ += yamlCompatiblityEnabled_ ? ": " + : ":"; + writeValue( value[name] ); + } + document_ += "}"; + } + break; + } +} + + +// Class StyledWriter +// ////////////////////////////////////////////////////////////////// + +StyledWriter::StyledWriter() + : rightMargin_( 74 ) + , indentSize_( 3 ) +{ +} + + +std::string +StyledWriter::write( const Value &root ) +{ + document_ = ""; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue( root ); + writeValue( root ); + writeCommentAfterValueOnSameLine( root ); + document_ += "\n"; + return document_; +} + + +void +StyledWriter::writeValue( const Value &value ) +{ + switch ( value.type() ) + { + case nullValue: + pushValue( "null" ); + break; + case intValue: + pushValue( valueToString( value.asInt() ) ); + break; + case uintValue: + pushValue( valueToString( value.asUInt() ) ); + break; + case realValue: + pushValue( valueToString( value.asDouble() ) ); + break; + case stringValue: + pushValue( valueToQuotedString( value.asCString() ) ); + break; + case booleanValue: + pushValue( valueToString( value.asBool() ) ); + break; + case arrayValue: + writeArrayValue( value); + break; + case objectValue: + { + Value::Members members( value.getMemberNames() ); + if ( members.empty() ) + pushValue( "{}" ); + else + { + writeWithIndent( "{" ); + indent(); + Value::Members::iterator it = members.begin(); + while ( true ) + { + const std::string &name = *it; + const Value &childValue = value[name]; + writeCommentBeforeValue( childValue ); + writeWithIndent( valueToQuotedString( name.c_str() ) ); + document_ += " : "; + writeValue( childValue ); + if ( ++it == members.end() ) + { + writeCommentAfterValueOnSameLine( childValue ); + break; + } + document_ += ","; + writeCommentAfterValueOnSameLine( childValue ); + } + unindent(); + writeWithIndent( "}" ); + } + } + break; + } +} + + +void +StyledWriter::writeArrayValue( const Value &value ) +{ + unsigned size = value.size(); + if ( size == 0 ) + pushValue( "[]" ); + else + { + bool isArrayMultiLine = isMultineArray( value ); + if ( isArrayMultiLine ) + { + writeWithIndent( "[" ); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index =0; + while ( true ) + { + const Value &childValue = value[index]; + writeCommentBeforeValue( childValue ); + if ( hasChildValue ) + writeWithIndent( childValues_[index] ); + else + { + writeIndent(); + writeValue( childValue ); + } + if ( ++index == size ) + { + writeCommentAfterValueOnSameLine( childValue ); + break; + } + document_ += ","; + writeCommentAfterValueOnSameLine( childValue ); + } + unindent(); + writeWithIndent( "]" ); + } + else // output on a single line + { + assert( childValues_.size() == size ); + document_ += "[ "; + for ( unsigned index =0; index < size; ++index ) + { + if ( index > 0 ) + document_ += ", "; + document_ += childValues_[index]; + } + document_ += " ]"; + } + } +} + + +bool +StyledWriter::isMultineArray( const Value &value ) +{ + int size = value.size(); + bool isMultiLine = size*3 >= rightMargin_ ; + childValues_.clear(); + for ( int index =0; index < size && !isMultiLine; ++index ) + { + const Value &childValue = value[index]; + isMultiLine = isMultiLine || + ( (childValue.isArray() || childValue.isObject()) && + childValue.size() > 0 ); + } + if ( !isMultiLine ) // check if line length > max line length + { + childValues_.reserve( size ); + addChildValues_ = true; + int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' + for ( int index =0; index < size && !isMultiLine; ++index ) + { + writeValue( value[index] ); + lineLength += int( childValues_[index].length() ); + isMultiLine = isMultiLine && hasCommentForValue( value[index] ); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + + +void +StyledWriter::pushValue( const std::string &value ) +{ + if ( addChildValues_ ) + childValues_.push_back( value ); + else + document_ += value; +} + + +void +StyledWriter::writeIndent() +{ + if ( !document_.empty() ) + { + char last = document_[document_.length()-1]; + if ( last == ' ' ) // already indented + return; + if ( last != '\n' ) // Comments may add new-line + document_ += '\n'; + } + document_ += indentString_; +} + + +void +StyledWriter::writeWithIndent( const std::string &value ) +{ + writeIndent(); + document_ += value; +} + + +void +StyledWriter::indent() +{ + indentString_ += std::string( indentSize_, ' ' ); +} + + +void +StyledWriter::unindent() +{ + assert( int(indentString_.size()) >= indentSize_ ); + indentString_.resize( indentString_.size() - indentSize_ ); +} + + +void +StyledWriter::writeCommentBeforeValue( const Value &root ) +{ + if ( !root.hasComment( commentBefore ) ) + return; + document_ += normalizeEOL( root.getComment( commentBefore ) ); + document_ += "\n"; +} + + +void +StyledWriter::writeCommentAfterValueOnSameLine( const Value &root ) +{ + if ( root.hasComment( commentAfterOnSameLine ) ) + document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); + + if ( root.hasComment( commentAfter ) ) + { + document_ += "\n"; + document_ += normalizeEOL( root.getComment( commentAfter ) ); + document_ += "\n"; + } +} + + +bool +StyledWriter::hasCommentForValue( const Value &value ) +{ + return value.hasComment( commentBefore ) + || value.hasComment( commentAfterOnSameLine ) + || value.hasComment( commentAfter ); +} + + +std::string +StyledWriter::normalizeEOL( const std::string &text ) +{ + std::string normalized; + normalized.reserve( text.length() ); + const char *begin = text.c_str(); + const char *end = begin + text.length(); + const char *current = begin; + while ( current != end ) + { + char c = *current++; + if ( c == '\r' ) // mac or dos EOL + { + if ( *current == '\n' ) // convert dos EOL + ++current; + normalized += '\n'; + } + else // handle unix EOL & other char + normalized += c; + } + return normalized; +} + + +// Class StyledStreamWriter +// ////////////////////////////////////////////////////////////////// + +StyledStreamWriter::StyledStreamWriter( std::string indentation ) + : document_(NULL) + , rightMargin_( 74 ) + , indentation_( indentation ) +{ +} + + +void +StyledStreamWriter::write( std::ostream &out, const Value &root ) +{ + document_ = &out; + addChildValues_ = false; + indentString_ = ""; + writeCommentBeforeValue( root ); + writeValue( root ); + writeCommentAfterValueOnSameLine( root ); + *document_ << "\n"; + document_ = NULL; // Forget the stream, for safety. +} + + +void +StyledStreamWriter::writeValue( const Value &value ) +{ + switch ( value.type() ) + { + case nullValue: + pushValue( "null" ); + break; + case intValue: + pushValue( valueToString( value.asInt() ) ); + break; + case uintValue: + pushValue( valueToString( value.asUInt() ) ); + break; + case realValue: + pushValue( valueToString( value.asDouble() ) ); + break; + case stringValue: + pushValue( valueToQuotedString( value.asCString() ) ); + break; + case booleanValue: + pushValue( valueToString( value.asBool() ) ); + break; + case arrayValue: + writeArrayValue( value); + break; + case objectValue: + { + Value::Members members( value.getMemberNames() ); + if ( members.empty() ) + pushValue( "{}" ); + else + { + writeWithIndent( "{" ); + indent(); + Value::Members::iterator it = members.begin(); + while ( true ) + { + const std::string &name = *it; + const Value &childValue = value[name]; + writeCommentBeforeValue( childValue ); + writeWithIndent( valueToQuotedString( name.c_str() ) ); + *document_ << " : "; + writeValue( childValue ); + if ( ++it == members.end() ) + { + writeCommentAfterValueOnSameLine( childValue ); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine( childValue ); + } + unindent(); + writeWithIndent( "}" ); + } + } + break; + } +} + + +void +StyledStreamWriter::writeArrayValue( const Value &value ) +{ + unsigned size = value.size(); + if ( size == 0 ) + pushValue( "[]" ); + else + { + bool isArrayMultiLine = isMultineArray( value ); + if ( isArrayMultiLine ) + { + writeWithIndent( "[" ); + indent(); + bool hasChildValue = !childValues_.empty(); + unsigned index =0; + while ( true ) + { + const Value &childValue = value[index]; + writeCommentBeforeValue( childValue ); + if ( hasChildValue ) + writeWithIndent( childValues_[index] ); + else + { + writeIndent(); + writeValue( childValue ); + } + if ( ++index == size ) + { + writeCommentAfterValueOnSameLine( childValue ); + break; + } + *document_ << ","; + writeCommentAfterValueOnSameLine( childValue ); + } + unindent(); + writeWithIndent( "]" ); + } + else // output on a single line + { + assert( childValues_.size() == size ); + *document_ << "[ "; + for ( unsigned index =0; index < size; ++index ) + { + if ( index > 0 ) + *document_ << ", "; + *document_ << childValues_[index]; + } + *document_ << " ]"; + } + } +} + + +bool +StyledStreamWriter::isMultineArray( const Value &value ) +{ + int size = value.size(); + bool isMultiLine = size*3 >= rightMargin_ ; + childValues_.clear(); + for ( int index =0; index < size && !isMultiLine; ++index ) + { + const Value &childValue = value[index]; + isMultiLine = isMultiLine || + ( (childValue.isArray() || childValue.isObject()) && + childValue.size() > 0 ); + } + if ( !isMultiLine ) // check if line length > max line length + { + childValues_.reserve( size ); + addChildValues_ = true; + int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]' + for ( int index =0; index < size && !isMultiLine; ++index ) + { + writeValue( value[index] ); + lineLength += int( childValues_[index].length() ); + isMultiLine = isMultiLine && hasCommentForValue( value[index] ); + } + addChildValues_ = false; + isMultiLine = isMultiLine || lineLength >= rightMargin_; + } + return isMultiLine; +} + + +void +StyledStreamWriter::pushValue( const std::string &value ) +{ + if ( addChildValues_ ) + childValues_.push_back( value ); + else + *document_ << value; +} + + +void +StyledStreamWriter::writeIndent() +{ + /* + Some comments in this method would have been nice. ;-) + + if ( !document_.empty() ) + { + char last = document_[document_.length()-1]; + if ( last == ' ' ) // already indented + return; + if ( last != '\n' ) // Comments may add new-line + *document_ << '\n'; + } + */ + *document_ << '\n' << indentString_; +} + + +void +StyledStreamWriter::writeWithIndent( const std::string &value ) +{ + writeIndent(); + *document_ << value; +} + + +void +StyledStreamWriter::indent() +{ + indentString_ += indentation_; +} + + +void +StyledStreamWriter::unindent() +{ + assert( indentString_.size() >= indentation_.size() ); + indentString_.resize( indentString_.size() - indentation_.size() ); +} + + +void +StyledStreamWriter::writeCommentBeforeValue( const Value &root ) +{ + if ( !root.hasComment( commentBefore ) ) + return; + *document_ << normalizeEOL( root.getComment( commentBefore ) ); + *document_ << "\n"; +} + + +void +StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root ) +{ + if ( root.hasComment( commentAfterOnSameLine ) ) + *document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) ); + + if ( root.hasComment( commentAfter ) ) + { + *document_ << "\n"; + *document_ << normalizeEOL( root.getComment( commentAfter ) ); + *document_ << "\n"; + } +} + + +bool +StyledStreamWriter::hasCommentForValue( const Value &value ) +{ + return value.hasComment( commentBefore ) + || value.hasComment( commentAfterOnSameLine ) + || value.hasComment( commentAfter ); +} + + +std::string +StyledStreamWriter::normalizeEOL( const std::string &text ) +{ + std::string normalized; + normalized.reserve( text.length() ); + const char *begin = text.c_str(); + const char *end = begin + text.length(); + const char *current = begin; + while ( current != end ) + { + char c = *current++; + if ( c == '\r' ) // mac or dos EOL + { + if ( *current == '\n' ) // convert dos EOL + ++current; + normalized += '\n'; + } + else // handle unix EOL & other char + normalized += c; + } + return normalized; +} + + +std::ostream& operator<<( std::ostream &sout, const Value &root ) +{ + Json::StyledStreamWriter writer; + writer.write(sout, root); + return sout; +} + + +} // namespace Json diff --git a/samples/C++/qscicommand.h b/samples/C++/qscicommand.h deleted file mode 100644 index f8ecbc86..00000000 --- a/samples/C++/qscicommand.h +++ /dev/null @@ -1,415 +0,0 @@ -// This defines the interface to the QsciCommand class. -// -// Copyright (c) 2011 Riverbank Computing Limited -// -// This file is part of QScintilla. -// -// This file may be used under the terms of the GNU General Public -// License versions 2.0 or 3.0 as published by the Free Software -// Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 -// included in the packaging of this file. Alternatively you may (at -// your option) use any later version of the GNU General Public -// License if such license has been publicly approved by Riverbank -// Computing Limited (or its successors, if any) and the KDE Free Qt -// Foundation. In addition, as a special exception, Riverbank gives you -// certain additional rights. These rights are described in the Riverbank -// GPL Exception version 1.1, which can be found in the file -// GPL_EXCEPTION.txt in this package. -// -// If you are unsure which license is appropriate for your use, please -// contact the sales department at sales@riverbankcomputing.com. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - -#ifndef QSCICOMMAND_H -#define QSCICOMMAND_H - -#ifdef __APPLE__ -extern "C++" { -#endif - -#include - -#include -#include - - -class QsciScintilla; - - -//! \brief The QsciCommand class represents an internal editor command that may -//! have one or two keys bound to it. -//! -//! Methods are provided to change the keys bound to the command and to remove -//! a key binding. Each command has a user friendly description of the command -//! for use in key mapping dialogs. -class QSCINTILLA_EXPORT QsciCommand -{ -public: - //! This enum defines the different commands that can be assigned to a key. - enum Command { - //! Move down one line. - LineDown = QsciScintillaBase::SCI_LINEDOWN, - - //! Extend the selection down one line. - LineDownExtend = QsciScintillaBase::SCI_LINEDOWNEXTEND, - - //! Extend the rectangular selection down one line. - LineDownRectExtend = QsciScintillaBase::SCI_LINEDOWNRECTEXTEND, - - //! Scroll the view down one line. - LineScrollDown = QsciScintillaBase::SCI_LINESCROLLDOWN, - - //! Move up one line. - LineUp = QsciScintillaBase::SCI_LINEUP, - - //! Extend the selection up one line. - LineUpExtend = QsciScintillaBase::SCI_LINEUPEXTEND, - - //! Extend the rectangular selection up one line. - LineUpRectExtend = QsciScintillaBase::SCI_LINEUPRECTEXTEND, - - //! Scroll the view up one line. - LineScrollUp = QsciScintillaBase::SCI_LINESCROLLUP, - - //! Scroll to the start of the document. - ScrollToStart = QsciScintillaBase::SCI_SCROLLTOSTART, - - //! Scroll to the end of the document. - ScrollToEnd = QsciScintillaBase::SCI_SCROLLTOEND, - - //! Scroll vertically to centre the current line. - VerticalCentreCaret = QsciScintillaBase::SCI_VERTICALCENTRECARET, - - //! Move down one paragraph. - ParaDown = QsciScintillaBase::SCI_PARADOWN, - - //! Extend the selection down one paragraph. - ParaDownExtend = QsciScintillaBase::SCI_PARADOWNEXTEND, - - //! Move up one paragraph. - ParaUp = QsciScintillaBase::SCI_PARAUP, - - //! Extend the selection up one paragraph. - ParaUpExtend = QsciScintillaBase::SCI_PARAUPEXTEND, - - //! Move left one character. - CharLeft = QsciScintillaBase::SCI_CHARLEFT, - - //! Extend the selection left one character. - CharLeftExtend = QsciScintillaBase::SCI_CHARLEFTEXTEND, - - //! Extend the rectangular selection left one character. - CharLeftRectExtend = QsciScintillaBase::SCI_CHARLEFTRECTEXTEND, - - //! Move right one character. - CharRight = QsciScintillaBase::SCI_CHARRIGHT, - - //! Extend the selection right one character. - CharRightExtend = QsciScintillaBase::SCI_CHARRIGHTEXTEND, - - //! Extend the rectangular selection right one character. - CharRightRectExtend = QsciScintillaBase::SCI_CHARRIGHTRECTEXTEND, - - //! Move left one word. - WordLeft = QsciScintillaBase::SCI_WORDLEFT, - - //! Extend the selection left one word. - WordLeftExtend = QsciScintillaBase::SCI_WORDLEFTEXTEND, - - //! Move right one word. - WordRight = QsciScintillaBase::SCI_WORDRIGHT, - - //! Extend the selection right one word. - WordRightExtend = QsciScintillaBase::SCI_WORDRIGHTEXTEND, - - //! Move to the end of the previous word. - WordLeftEnd = QsciScintillaBase::SCI_WORDLEFTEND, - - //! Extend the selection to the end of the previous word. - WordLeftEndExtend = QsciScintillaBase::SCI_WORDLEFTENDEXTEND, - - //! Move to the end of the next word. - WordRightEnd = QsciScintillaBase::SCI_WORDRIGHTEND, - - //! Extend the selection to the end of the next word. - WordRightEndExtend = QsciScintillaBase::SCI_WORDRIGHTENDEXTEND, - - //! Move left one word part. - WordPartLeft = QsciScintillaBase::SCI_WORDPARTLEFT, - - //! Extend the selection left one word part. - WordPartLeftExtend = QsciScintillaBase::SCI_WORDPARTLEFTEXTEND, - - //! Move right one word part. - WordPartRight = QsciScintillaBase::SCI_WORDPARTRIGHT, - - //! Extend the selection right one word part. - WordPartRightExtend = QsciScintillaBase::SCI_WORDPARTRIGHTEXTEND, - - //! Move to the start of the document line. - Home = QsciScintillaBase::SCI_HOME, - - //! Extend the selection to the start of the document line. - HomeExtend = QsciScintillaBase::SCI_HOMEEXTEND, - - //! Extend the rectangular selection to the start of the document line. - HomeRectExtend = QsciScintillaBase::SCI_HOMERECTEXTEND, - - //! Move to the start of the displayed line. - HomeDisplay = QsciScintillaBase::SCI_HOMEDISPLAY, - - //! Extend the selection to the start of the displayed line. - HomeDisplayExtend = QsciScintillaBase::SCI_HOMEDISPLAYEXTEND, - - //! Move to the start of the displayed or document line. - HomeWrap = QsciScintillaBase::SCI_HOMEWRAP, - - //! Extend the selection to the start of the displayed or document - //! line. - HomeWrapExtend = QsciScintillaBase::SCI_HOMEWRAPEXTEND, - - //! Move to the first visible character in the document line. - VCHome = QsciScintillaBase::SCI_VCHOME, - - //! Extend the selection to the first visible character in the document - //! line. - VCHomeExtend = QsciScintillaBase::SCI_VCHOMEEXTEND, - - //! Extend the rectangular selection to the first visible character in - //! the document line. - VCHomeRectExtend = QsciScintillaBase::SCI_VCHOMERECTEXTEND, - - //! Move to the first visible character of the displayed or document - //! line. - VCHomeWrap = QsciScintillaBase::SCI_VCHOMEWRAP, - - //! Extend the selection to the first visible character of the - //! displayed or document line. - VCHomeWrapExtend = QsciScintillaBase::SCI_VCHOMEWRAPEXTEND, - - //! Move to the end of the document line. - LineEnd = QsciScintillaBase::SCI_LINEEND, - - //! Extend the selection to the end of the document line. - LineEndExtend = QsciScintillaBase::SCI_LINEENDEXTEND, - - //! Extend the rectangular selection to the end of the document line. - LineEndRectExtend = QsciScintillaBase::SCI_LINEENDRECTEXTEND, - - //! Move to the end of the displayed line. - LineEndDisplay = QsciScintillaBase::SCI_LINEENDDISPLAY, - - //! Extend the selection to the end of the displayed line. - LineEndDisplayExtend = QsciScintillaBase::SCI_LINEENDDISPLAYEXTEND, - - //! Move to the end of the displayed or document line. - LineEndWrap = QsciScintillaBase::SCI_LINEENDWRAP, - - //! Extend the selection to the end of the displayed or document line. - LineEndWrapExtend = QsciScintillaBase::SCI_LINEENDWRAPEXTEND, - - //! Move to the start of the document. - DocumentStart = QsciScintillaBase::SCI_DOCUMENTSTART, - - //! Extend the selection to the start of the document. - DocumentStartExtend = QsciScintillaBase::SCI_DOCUMENTSTARTEXTEND, - - //! Move to the end of the document. - DocumentEnd = QsciScintillaBase::SCI_DOCUMENTEND, - - //! Extend the selection to the end of the document. - DocumentEndExtend = QsciScintillaBase::SCI_DOCUMENTENDEXTEND, - - //! Move up one page. - PageUp = QsciScintillaBase::SCI_PAGEUP, - - //! Extend the selection up one page. - PageUpExtend = QsciScintillaBase::SCI_PAGEUPEXTEND, - - //! Extend the rectangular selection up one page. - PageUpRectExtend = QsciScintillaBase::SCI_PAGEUPRECTEXTEND, - - //! Move down one page. - PageDown = QsciScintillaBase::SCI_PAGEDOWN, - - //! Extend the selection down one page. - PageDownExtend = QsciScintillaBase::SCI_PAGEDOWNEXTEND, - - //! Extend the rectangular selection down one page. - PageDownRectExtend = QsciScintillaBase::SCI_PAGEDOWNRECTEXTEND, - - //! Stuttered move up one page. - StutteredPageUp = QsciScintillaBase::SCI_STUTTEREDPAGEUP, - - //! Stuttered extend the selection up one page. - StutteredPageUpExtend = QsciScintillaBase::SCI_STUTTEREDPAGEUPEXTEND, - - //! Stuttered move down one page. - StutteredPageDown = QsciScintillaBase::SCI_STUTTEREDPAGEDOWN, - - //! Stuttered extend the selection down one page. - StutteredPageDownExtend = QsciScintillaBase::SCI_STUTTEREDPAGEDOWNEXTEND, - - //! Delete the current character. - Delete = QsciScintillaBase::SCI_CLEAR, - - //! Delete the previous character. - DeleteBack = QsciScintillaBase::SCI_DELETEBACK, - - //! Delete the previous character if not at start of line. - DeleteBackNotLine = QsciScintillaBase::SCI_DELETEBACKNOTLINE, - - //! Delete the word to the left. - DeleteWordLeft = QsciScintillaBase::SCI_DELWORDLEFT, - - //! Delete the word to the right. - DeleteWordRight = QsciScintillaBase::SCI_DELWORDRIGHT, - - //! Delete right to the end of the next word. - DeleteWordRightEnd = QsciScintillaBase::SCI_DELWORDRIGHTEND, - - //! Delete the line to the left. - DeleteLineLeft = QsciScintillaBase::SCI_DELLINELEFT, - - //! Delete the line to the right. - DeleteLineRight = QsciScintillaBase::SCI_DELLINERIGHT, - - //! Delete the current line. - LineDelete = QsciScintillaBase::SCI_LINEDELETE, - - //! Cut the current line to the clipboard. - LineCut = QsciScintillaBase::SCI_LINECUT, - - //! Copy the current line to the clipboard. - LineCopy = QsciScintillaBase::SCI_LINECOPY, - - //! Transpose the current and previous lines. - LineTranspose = QsciScintillaBase::SCI_LINETRANSPOSE, - - //! Duplicate the current line. - LineDuplicate = QsciScintillaBase::SCI_LINEDUPLICATE, - - //! Select the whole document. - SelectAll = QsciScintillaBase::SCI_SELECTALL, - - //! Move the selected lines up one line. - MoveSelectedLinesUp = QsciScintillaBase::SCI_MOVESELECTEDLINESUP, - - //! Move the selected lines down one line. - MoveSelectedLinesDown = QsciScintillaBase::SCI_MOVESELECTEDLINESDOWN, - - //! Duplicate the selection. - SelectionDuplicate = QsciScintillaBase::SCI_SELECTIONDUPLICATE, - - //! Convert the selection to lower case. - SelectionLowerCase = QsciScintillaBase::SCI_LOWERCASE, - - //! Convert the selection to upper case. - SelectionUpperCase = QsciScintillaBase::SCI_UPPERCASE, - - //! Cut the selection to the clipboard. - SelectionCut = QsciScintillaBase::SCI_CUT, - - //! Copy the selection to the clipboard. - SelectionCopy = QsciScintillaBase::SCI_COPY, - - //! Paste from the clipboard. - Paste = QsciScintillaBase::SCI_PASTE, - - //! Toggle insert/overtype. - EditToggleOvertype = QsciScintillaBase::SCI_EDITTOGGLEOVERTYPE, - - //! Insert a platform dependent newline. - Newline = QsciScintillaBase::SCI_NEWLINE, - - //! Insert a formfeed. - Formfeed = QsciScintillaBase::SCI_FORMFEED, - - //! Indent one level. - Tab = QsciScintillaBase::SCI_TAB, - - //! De-indent one level. - Backtab = QsciScintillaBase::SCI_BACKTAB, - - //! Cancel any current operation. - Cancel = QsciScintillaBase::SCI_CANCEL, - - //! Undo the last command. - Undo = QsciScintillaBase::SCI_UNDO, - - //! Redo the last command. - Redo = QsciScintillaBase::SCI_REDO, - - //! Zoom in. - ZoomIn = QsciScintillaBase::SCI_ZOOMIN, - - //! Zoom out. - ZoomOut = QsciScintillaBase::SCI_ZOOMOUT, - }; - - //! Return the command that will be executed by this instance. - Command command() const {return scicmd;} - - //! Execute the command. - void execute(); - - //! Binds the key \a key to the command. If \a key is 0 then the key - //! binding is removed. If \a key is invalid then the key binding is - //! unchanged. Valid keys are any visible or control character or any - //! of \c Key_Down, \c Key_Up, \c Key_Left, \c Key_Right, \c Key_Home, - //! \c Key_End, \c Key_PageUp, \c Key_PageDown, \c Key_Delete, - //! \c Key_Insert, \c Key_Escape, \c Key_Backspace, \c Key_Tab and - //! \c Key_Return. Keys may be modified with any combination of \c SHIFT, - //! \c CTRL, \c ALT and \c META. - //! - //! \sa key(), setAlternateKey(), validKey() - void setKey(int key); - - //! Binds the alternate key \a altkey to the command. If \a key is 0 - //! then the alternate key binding is removed. - //! - //! \sa alternateKey(), setKey(), validKey() - void setAlternateKey(int altkey); - - //! The key that is currently bound to the command is returned. - //! - //! \sa setKey(), alternateKey() - int key() const {return qkey;} - - //! The alternate key that is currently bound to the command is - //! returned. - //! - //! \sa setAlternateKey(), key() - int alternateKey() const {return qaltkey;} - - //! If the key \a key is valid then true is returned. - static bool validKey(int key); - - //! The user friendly description of the command is returned. - QString description() const; - -private: - friend class QsciCommandSet; - - QsciCommand(QsciScintilla *qs, Command cmd, int key, int altkey, - const char *desc); - - void bindKey(int key,int &qk,int &scik); - - QsciScintilla *qsCmd; - Command scicmd; - int qkey, scikey, qaltkey, scialtkey; - const char *descCmd; - - QsciCommand(const QsciCommand &); - QsciCommand &operator=(const QsciCommand &); -}; - -#ifdef __APPLE__ -} -#endif - -#endif diff --git a/samples/C++/qsciprinter.cp b/samples/C++/qsciprinter.cp deleted file mode 100644 index f30d6454..00000000 --- a/samples/C++/qsciprinter.cp +++ /dev/null @@ -1,116 +0,0 @@ -// This module defines interface to the QsciPrinter class. -// -// Copyright (c) 2011 Riverbank Computing Limited -// -// This file is part of QScintilla. -// -// This file may be used under the terms of the GNU General Public -// License versions 2.0 or 3.0 as published by the Free Software -// Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 -// included in the packaging of this file. Alternatively you may (at -// your option) use any later version of the GNU General Public -// License if such license has been publicly approved by Riverbank -// Computing Limited (or its successors, if any) and the KDE Free Qt -// Foundation. In addition, as a special exception, Riverbank gives you -// certain additional rights. These rights are described in the Riverbank -// GPL Exception version 1.1, which can be found in the file -// GPL_EXCEPTION.txt in this package. -// -// If you are unsure which license is appropriate for your use, please -// contact the sales department at sales@riverbankcomputing.com. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - -#ifndef QSCIPRINTER_H -#define QSCIPRINTER_H - -#ifdef __APPLE__ -extern "C++" { -#endif - -#include - -#include -#include - - -QT_BEGIN_NAMESPACE -class QRect; -class QPainter; -QT_END_NAMESPACE - -class QsciScintillaBase; - - -//! \brief The QsciPrinter class is a sub-class of the Qt QPrinter class that -//! is able to print the text of a Scintilla document. -//! -//! The class can be further sub-classed to alter to layout of the text, adding -//! headers and footers for example. -class QSCINTILLA_EXPORT QsciPrinter : public QPrinter -{ -public: - //! Constructs a printer paint device with mode \a mode. - QsciPrinter(PrinterMode mode = ScreenResolution); - - //! Destroys the QsciPrinter instance. - virtual ~QsciPrinter(); - - //! Format a page, by adding headers and footers for example, before the - //! document text is drawn on it. \a painter is the painter to be used to - //! add customised text and graphics. \a drawing is true if the page is - //! actually being drawn rather than being sized. \a painter drawing - //! methods must only be called when \a drawing is true. \a area is the - //! area of the page that will be used to draw the text. This should be - //! modified if it is necessary to reserve space for any customised text or - //! graphics. By default the area is relative to the printable area of the - //! page. Use QPrinter::setFullPage() because calling printRange() if you - //! want to try and print over the whole page. \a pagenr is the number of - //! the page. The first page is numbered 1. - virtual void formatPage(QPainter &painter, bool drawing, QRect &area, - int pagenr); - - //! Return the number of points to add to each font when printing. - //! - //! \sa setMagnification() - int magnification() const {return mag;} - - //! Sets the number of points to add to each font when printing to \a - //! magnification. - //! - //! \sa magnification() - virtual void setMagnification(int magnification); - - //! Print a range of lines from the Scintilla instance \a qsb. \a from is - //! the first line to print and a negative value signifies the first line - //! of text. \a to is the last line to print and a negative value - //! signifies the last line of text. true is returned if there was no - //! error. - virtual int printRange(QsciScintillaBase *qsb, int from = -1, int to = -1); - - //! Return the line wrap mode used when printing. The default is - //! QsciScintilla::WrapWord. - //! - //! \sa setWrapMode() - QsciScintilla::WrapMode wrapMode() const {return wrap;} - - //! Sets the line wrap mode used when printing to \a wmode. - //! - //! \sa wrapMode() - virtual void setWrapMode(QsciScintilla::WrapMode wmode); - -private: - int mag; - QsciScintilla::WrapMode wrap; - - QsciPrinter(const QsciPrinter &); - QsciPrinter &operator=(const QsciPrinter &); -}; - -#ifdef __APPLE__ -} -#endif - -#endif diff --git a/samples/C++/qsciprinter.h b/samples/C++/qsciprinter.h deleted file mode 100644 index f30d6454..00000000 --- a/samples/C++/qsciprinter.h +++ /dev/null @@ -1,116 +0,0 @@ -// This module defines interface to the QsciPrinter class. -// -// Copyright (c) 2011 Riverbank Computing Limited -// -// This file is part of QScintilla. -// -// This file may be used under the terms of the GNU General Public -// License versions 2.0 or 3.0 as published by the Free Software -// Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3 -// included in the packaging of this file. Alternatively you may (at -// your option) use any later version of the GNU General Public -// License if such license has been publicly approved by Riverbank -// Computing Limited (or its successors, if any) and the KDE Free Qt -// Foundation. In addition, as a special exception, Riverbank gives you -// certain additional rights. These rights are described in the Riverbank -// GPL Exception version 1.1, which can be found in the file -// GPL_EXCEPTION.txt in this package. -// -// If you are unsure which license is appropriate for your use, please -// contact the sales department at sales@riverbankcomputing.com. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - -#ifndef QSCIPRINTER_H -#define QSCIPRINTER_H - -#ifdef __APPLE__ -extern "C++" { -#endif - -#include - -#include -#include - - -QT_BEGIN_NAMESPACE -class QRect; -class QPainter; -QT_END_NAMESPACE - -class QsciScintillaBase; - - -//! \brief The QsciPrinter class is a sub-class of the Qt QPrinter class that -//! is able to print the text of a Scintilla document. -//! -//! The class can be further sub-classed to alter to layout of the text, adding -//! headers and footers for example. -class QSCINTILLA_EXPORT QsciPrinter : public QPrinter -{ -public: - //! Constructs a printer paint device with mode \a mode. - QsciPrinter(PrinterMode mode = ScreenResolution); - - //! Destroys the QsciPrinter instance. - virtual ~QsciPrinter(); - - //! Format a page, by adding headers and footers for example, before the - //! document text is drawn on it. \a painter is the painter to be used to - //! add customised text and graphics. \a drawing is true if the page is - //! actually being drawn rather than being sized. \a painter drawing - //! methods must only be called when \a drawing is true. \a area is the - //! area of the page that will be used to draw the text. This should be - //! modified if it is necessary to reserve space for any customised text or - //! graphics. By default the area is relative to the printable area of the - //! page. Use QPrinter::setFullPage() because calling printRange() if you - //! want to try and print over the whole page. \a pagenr is the number of - //! the page. The first page is numbered 1. - virtual void formatPage(QPainter &painter, bool drawing, QRect &area, - int pagenr); - - //! Return the number of points to add to each font when printing. - //! - //! \sa setMagnification() - int magnification() const {return mag;} - - //! Sets the number of points to add to each font when printing to \a - //! magnification. - //! - //! \sa magnification() - virtual void setMagnification(int magnification); - - //! Print a range of lines from the Scintilla instance \a qsb. \a from is - //! the first line to print and a negative value signifies the first line - //! of text. \a to is the last line to print and a negative value - //! signifies the last line of text. true is returned if there was no - //! error. - virtual int printRange(QsciScintillaBase *qsb, int from = -1, int to = -1); - - //! Return the line wrap mode used when printing. The default is - //! QsciScintilla::WrapWord. - //! - //! \sa setWrapMode() - QsciScintilla::WrapMode wrapMode() const {return wrap;} - - //! Sets the line wrap mode used when printing to \a wmode. - //! - //! \sa wrapMode() - virtual void setWrapMode(QsciScintilla::WrapMode wmode); - -private: - int mag; - QsciScintilla::WrapMode wrap; - - QsciPrinter(const QsciPrinter &); - QsciPrinter &operator=(const QsciPrinter &); -}; - -#ifdef __APPLE__ -} -#endif - -#endif diff --git a/samples/C++/srs_app_ingest.cpp b/samples/C++/srs_app_ingest.cpp new file mode 100644 index 00000000..3419877a --- /dev/null +++ b/samples/C++/srs_app_ingest.cpp @@ -0,0 +1,557 @@ +/* +The MIT License (MIT) + +Copyright (c) 2013-2015 SRS(ossrs) + +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: + +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. +*/ + +// Source - https://github.com/REN-I/srs/blob/3aae7854702a37955bce706fcd8122b02ac07f53/trunk/src/app/srs_app_ingest.cpp + +#include + +#ifdef SRS_AUTO_INGEST + +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include + +// when error, ingester sleep for a while and retry. +// ingest never sleep a long time, for we must start the stream ASAP. +#define SRS_AUTO_INGESTER_SLEEP_US (int64_t)(3*1000*1000LL) + +SrsIngesterFFMPEG::SrsIngesterFFMPEG() +{ + ffmpeg = NULL; +} + +SrsIngesterFFMPEG::~SrsIngesterFFMPEG() +{ + srs_freep(ffmpeg); +} + +int SrsIngesterFFMPEG::initialize(SrsFFMPEG* ff, string v, string i) +{ + int ret = ERROR_SUCCESS; + + ffmpeg = ff; + vhost = v; + id = i; + starttime = srs_get_system_time_ms(); + + return ret; +} + +string SrsIngesterFFMPEG::uri() +{ + return vhost + "/" + id; +} + +int SrsIngesterFFMPEG::alive() +{ + return (int)(srs_get_system_time_ms() - starttime); +} + +bool SrsIngesterFFMPEG::equals(string v) +{ + return vhost == v; +} + +bool SrsIngesterFFMPEG::equals(string v, string i) +{ + return vhost == v && id == i; +} + +int SrsIngesterFFMPEG::start() +{ + return ffmpeg->start(); +} + +void SrsIngesterFFMPEG::stop() +{ + ffmpeg->stop(); +} + +int SrsIngesterFFMPEG::cycle() +{ + return ffmpeg->cycle(); +} + +void SrsIngesterFFMPEG::fast_stop() +{ + ffmpeg->fast_stop(); +} + +SrsIngester::SrsIngester() +{ + _srs_config->subscribe(this); + + pthread = new SrsReusableThread("ingest", this, SRS_AUTO_INGESTER_SLEEP_US); + pprint = SrsPithyPrint::create_ingester(); +} + +SrsIngester::~SrsIngester() +{ + _srs_config->unsubscribe(this); + + srs_freep(pthread); + clear_engines(); +} + +int SrsIngester::start() +{ + int ret = ERROR_SUCCESS; + + if ((ret = parse()) != ERROR_SUCCESS) { + clear_engines(); + ret = ERROR_SUCCESS; + return ret; + } + + // even no ingesters, we must also start it, + // for the reload may add more ingesters. + + // start thread to run all encoding engines. + if ((ret = pthread->start()) != ERROR_SUCCESS) { + srs_error("st_thread_create failed. ret=%d", ret); + return ret; + } + srs_trace("ingest thread cid=%d, current_cid=%d", pthread->cid(), _srs_context->get_id()); + + return ret; +} + +int SrsIngester::parse_ingesters(SrsConfDirective* vhost) +{ + int ret = ERROR_SUCCESS; + + std::vector ingesters = _srs_config->get_ingesters(vhost->arg0()); + + // create engine + for (int i = 0; i < (int)ingesters.size(); i++) { + SrsConfDirective* ingest = ingesters[i]; + if ((ret = parse_engines(vhost, ingest)) != ERROR_SUCCESS) { + return ret; + } + } + + return ret; +} + +int SrsIngester::parse_engines(SrsConfDirective* vhost, SrsConfDirective* ingest) +{ + int ret = ERROR_SUCCESS; + + if (!_srs_config->get_ingest_enabled(ingest)) { + return ret; + } + + std::string ffmpeg_bin = _srs_config->get_ingest_ffmpeg(ingest); + if (ffmpeg_bin.empty()) { + ret = ERROR_ENCODER_PARSE; + srs_trace("empty ffmpeg ret=%d", ret); + return ret; + } + + // get all engines. + std::vector engines = _srs_config->get_transcode_engines(ingest); + + // create ingesters without engines. + if (engines.empty()) { + SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin); + if ((ret = initialize_ffmpeg(ffmpeg, vhost, ingest, NULL)) != ERROR_SUCCESS) { + srs_freep(ffmpeg); + if (ret != ERROR_ENCODER_LOOP) { + srs_error("invalid ingest engine. ret=%d", ret); + } + return ret; + } + + SrsIngesterFFMPEG* ingester = new SrsIngesterFFMPEG(); + if ((ret = ingester->initialize(ffmpeg, vhost->arg0(), ingest->arg0())) != ERROR_SUCCESS) { + srs_freep(ingester); + return ret; + } + + ingesters.push_back(ingester); + return ret; + } + + // create ingesters with engine + for (int i = 0; i < (int)engines.size(); i++) { + SrsConfDirective* engine = engines[i]; + SrsFFMPEG* ffmpeg = new SrsFFMPEG(ffmpeg_bin); + if ((ret = initialize_ffmpeg(ffmpeg, vhost, ingest, engine)) != ERROR_SUCCESS) { + srs_freep(ffmpeg); + if (ret != ERROR_ENCODER_LOOP) { + srs_error("invalid ingest engine: %s %s, ret=%d", + ingest->arg0().c_str(), engine->arg0().c_str(), ret); + } + return ret; + } + + SrsIngesterFFMPEG* ingester = new SrsIngesterFFMPEG(); + if ((ret = ingester->initialize(ffmpeg, vhost->arg0(), ingest->arg0())) != ERROR_SUCCESS) { + srs_freep(ingester); + return ret; + } + + ingesters.push_back(ingester); + } + + return ret; +} + +void SrsIngester::dispose() +{ + // first, use fast stop to notice all FFMPEG to quit gracefully. + std::vector::iterator it; + for (it = ingesters.begin(); it != ingesters.end(); ++it) { + SrsIngesterFFMPEG* ingester = *it; + ingester->fast_stop(); + } + + if (!ingesters.empty()) { + srs_trace("fast stop all ingesters ok."); + } + + // then, use stop to wait FFMPEG quit one by one and send SIGKILL if needed. + stop(); +} + +void SrsIngester::stop() +{ + pthread->stop(); + clear_engines(); +} + +int SrsIngester::cycle() +{ + int ret = ERROR_SUCCESS; + + std::vector::iterator it; + for (it = ingesters.begin(); it != ingesters.end(); ++it) { + SrsIngesterFFMPEG* ingester = *it; + + // start all ffmpegs. + if ((ret = ingester->start()) != ERROR_SUCCESS) { + srs_error("ingest ffmpeg start failed. ret=%d", ret); + return ret; + } + + // check ffmpeg status. + if ((ret = ingester->cycle()) != ERROR_SUCCESS) { + srs_error("ingest ffmpeg cycle failed. ret=%d", ret); + return ret; + } + } + + // pithy print + show_ingest_log_message(); + + return ret; +} + +void SrsIngester::on_thread_stop() +{ +} + +void SrsIngester::clear_engines() +{ + std::vector::iterator it; + + for (it = ingesters.begin(); it != ingesters.end(); ++it) { + SrsIngesterFFMPEG* ingester = *it; + srs_freep(ingester); + } + + ingesters.clear(); +} + +int SrsIngester::parse() +{ + int ret = ERROR_SUCCESS; + + // parse ingesters + std::vector vhosts; + _srs_config->get_vhosts(vhosts); + + for (int i = 0; i < (int)vhosts.size(); i++) { + SrsConfDirective* vhost = vhosts[i]; + if ((ret = parse_ingesters(vhost)) != ERROR_SUCCESS) { + return ret; + } + } + + return ret; +} + +int SrsIngester::initialize_ffmpeg(SrsFFMPEG* ffmpeg, SrsConfDirective* vhost, SrsConfDirective* ingest, SrsConfDirective* engine) +{ + int ret = ERROR_SUCCESS; + + std::string port; + if (true) { + std::vector ip_ports = _srs_config->get_listens(); + srs_assert(ip_ports.size() > 0); + + std::string ep = ip_ports[0]; + std::string ip; + srs_parse_endpoint(ep, ip, port); + } + + std::string output = _srs_config->get_engine_output(engine); + // output stream, to other/self server + // ie. rtmp://localhost:1935/live/livestream_sd + output = srs_string_replace(output, "[vhost]", vhost->arg0()); + output = srs_string_replace(output, "[port]", port); + if (output.empty()) { + ret = ERROR_ENCODER_NO_OUTPUT; + srs_trace("empty output url, ingest=%s. ret=%d", ingest->arg0().c_str(), ret); + return ret; + } + + // find the app and stream in rtmp url + std::string url = output; + std::string app, stream; + size_t pos = std::string::npos; + if ((pos = url.rfind("/")) != std::string::npos) { + stream = url.substr(pos + 1); + url = url.substr(0, pos); + } + if ((pos = url.rfind("/")) != std::string::npos) { + app = url.substr(pos + 1); + url = url.substr(0, pos); + } + if ((pos = app.rfind("?")) != std::string::npos) { + app = app.substr(0, pos); + } + + std::string log_file = SRS_CONSTS_NULL_FILE; // disabled + // write ffmpeg info to log file. + if (_srs_config->get_ffmpeg_log_enabled()) { + log_file = _srs_config->get_ffmpeg_log_dir(); + log_file += "/"; + log_file += "ffmpeg-ingest"; + log_file += "-"; + log_file += vhost->arg0(); + log_file += "-"; + log_file += app; + log_file += "-"; + log_file += stream; + log_file += ".log"; + } + + // input + std::string input_type = _srs_config->get_ingest_input_type(ingest); + if (input_type.empty()) { + ret = ERROR_ENCODER_NO_INPUT; + srs_trace("empty intput type, ingest=%s. ret=%d", ingest->arg0().c_str(), ret); + return ret; + } + + if (srs_config_ingest_is_file(input_type)) { + std::string input_url = _srs_config->get_ingest_input_url(ingest); + if (input_url.empty()) { + ret = ERROR_ENCODER_NO_INPUT; + srs_trace("empty intput url, ingest=%s. ret=%d", ingest->arg0().c_str(), ret); + return ret; + } + + // for file, set re. + ffmpeg->set_iparams("-re"); + + if ((ret = ffmpeg->initialize(input_url, output, log_file)) != ERROR_SUCCESS) { + return ret; + } + } else if (srs_config_ingest_is_stream(input_type)) { + std::string input_url = _srs_config->get_ingest_input_url(ingest); + if (input_url.empty()) { + ret = ERROR_ENCODER_NO_INPUT; + srs_trace("empty intput url, ingest=%s. ret=%d", ingest->arg0().c_str(), ret); + return ret; + } + + // for stream, no re. + ffmpeg->set_iparams(""); + + if ((ret = ffmpeg->initialize(input_url, output, log_file)) != ERROR_SUCCESS) { + return ret; + } + } else { + ret = ERROR_ENCODER_INPUT_TYPE; + srs_error("invalid ingest=%s type=%s, ret=%d", + ingest->arg0().c_str(), input_type.c_str(), ret); + } + + // set output format to flv for RTMP + ffmpeg->set_oformat("flv"); + + std::string vcodec = _srs_config->get_engine_vcodec(engine); + std::string acodec = _srs_config->get_engine_acodec(engine); + // whatever the engine config, use copy as default. + bool engine_disabled = !engine || !_srs_config->get_engine_enabled(engine); + if (engine_disabled || vcodec.empty() || acodec.empty()) { + if ((ret = ffmpeg->initialize_copy()) != ERROR_SUCCESS) { + return ret; + } + } else { + if ((ret = ffmpeg->initialize_transcode(engine)) != ERROR_SUCCESS) { + return ret; + } + } + + srs_trace("parse success, ingest=%s, vhost=%s", + ingest->arg0().c_str(), vhost->arg0().c_str()); + + return ret; +} + +void SrsIngester::show_ingest_log_message() +{ + pprint->elapse(); + + if ((int)ingesters.size() <= 0) { + return; + } + + // random choose one ingester to report. + int index = rand() % (int)ingesters.size(); + SrsIngesterFFMPEG* ingester = ingesters.at(index); + + // reportable + if (pprint->can_print()) { + srs_trace("-> "SRS_CONSTS_LOG_INGESTER" time=%"PRId64", ingesters=%d, #%d(alive=%ds, %s)", + pprint->age(), (int)ingesters.size(), index, ingester->alive() / 1000, ingester->uri().c_str()); + } +} + +int SrsIngester::on_reload_vhost_added(string vhost) +{ + int ret = ERROR_SUCCESS; + + SrsConfDirective* _vhost = _srs_config->get_vhost(vhost); + if ((ret = parse_ingesters(_vhost)) != ERROR_SUCCESS) { + return ret; + } + + srs_trace("reload add vhost ingesters, vhost=%s", vhost.c_str()); + + return ret; +} + +int SrsIngester::on_reload_vhost_removed(string vhost) +{ + int ret = ERROR_SUCCESS; + + std::vector::iterator it; + + for (it = ingesters.begin(); it != ingesters.end();) { + SrsIngesterFFMPEG* ingester = *it; + + if (!ingester->equals(vhost)) { + ++it; + continue; + } + + // stop the ffmpeg and free it. + ingester->stop(); + + srs_trace("reload stop ingester, vhost=%s, id=%s", vhost.c_str(), ingester->uri().c_str()); + + srs_freep(ingester); + + // remove the item from ingesters. + it = ingesters.erase(it); + } + + return ret; +} + +int SrsIngester::on_reload_ingest_removed(string vhost, string ingest_id) +{ + int ret = ERROR_SUCCESS; + + std::vector::iterator it; + + for (it = ingesters.begin(); it != ingesters.end();) { + SrsIngesterFFMPEG* ingester = *it; + + if (!ingester->equals(vhost, ingest_id)) { + ++it; + continue; + } + + // stop the ffmpeg and free it. + ingester->stop(); + + srs_trace("reload stop ingester, vhost=%s, id=%s", vhost.c_str(), ingester->uri().c_str()); + + srs_freep(ingester); + + // remove the item from ingesters. + it = ingesters.erase(it); + } + + return ret; +} + +int SrsIngester::on_reload_ingest_added(string vhost, string ingest_id) +{ + int ret = ERROR_SUCCESS; + + SrsConfDirective* _vhost = _srs_config->get_vhost(vhost); + SrsConfDirective* _ingester = _srs_config->get_ingest_by_id(vhost, ingest_id); + + if ((ret = parse_engines(_vhost, _ingester)) != ERROR_SUCCESS) { + return ret; + } + + srs_trace("reload add ingester, " + "vhost=%s, id=%s", vhost.c_str(), ingest_id.c_str()); + + return ret; +} + +int SrsIngester::on_reload_ingest_updated(string vhost, string ingest_id) +{ + int ret = ERROR_SUCCESS; + + if ((ret = on_reload_ingest_removed(vhost, ingest_id)) != ERROR_SUCCESS) { + return ret; + } + + if ((ret = on_reload_ingest_added(vhost, ingest_id)) != ERROR_SUCCESS) { + return ret; + } + + srs_trace("reload updated ingester, " + "vhost=%s, id=%s", vhost.c_str(), ingest_id.c_str()); + + return ret; +} + +#endif + From ead63163b4e4507cac352a0600de3e1039e53b76 Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Tue, 28 Jun 2016 01:11:38 +0530 Subject: [PATCH 2/6] Remove another GPL licensed C sample --- samples/C/dynarray.cats | 56 ----------------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 samples/C/dynarray.cats diff --git a/samples/C/dynarray.cats b/samples/C/dynarray.cats deleted file mode 100644 index 95ee54ba..00000000 --- a/samples/C/dynarray.cats +++ /dev/null @@ -1,56 +0,0 @@ -/* ******************************************************************* */ -/* */ -/* Applied Type System */ -/* */ -/* ******************************************************************* */ - -/* -** ATS/Postiats - Unleashing the Potential of Types! -** Copyright (C) 2011-20?? Hongwei Xi, ATS Trustful Software, Inc. -** All rights reserved -** -** ATS is free software; you can redistribute it and/or modify it under -** the terms of the GNU GENERAL PUBLIC LICENSE (GPL) as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** ATS 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 General Public License -** for more details. -** -** You should have received a copy of the GNU General Public License -** along with ATS; see the file COPYING. If not, please write to the -** Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -** 02110-1301, USA. -*/ - -/* ****** ****** */ - -/* -(* Author: Hongwei Xi *) -(* Authoremail: hwxi AT cs DOT bu DOT edu *) -(* Start time: March, 2013 *) -*/ - -/* ****** ****** */ - -#ifndef ATSHOME_LIBATS_DYNARRAY_CATS -#define ATSHOME_LIBATS_DYNARRAY_CATS - -/* ****** ****** */ - -#include - -/* ****** ****** */ - -#define atslib_dynarray_memcpy memcpy -#define atslib_dynarray_memmove memmove - -/* ****** ****** */ - -#endif // ifndef ATSHOME_LIBATS_DYNARRAY_CATS - -/* ****** ****** */ - -/* end of [dynarray.cats] */ From 94928bc78f70799b6af5db7f3e5a7ae977d911b3 Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Tue, 28 Jun 2016 01:58:44 +0530 Subject: [PATCH 3/6] Added MIT licensed .cp sample --- samples/C++/program.cp | 170 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 samples/C++/program.cp diff --git a/samples/C++/program.cp b/samples/C++/program.cp new file mode 100644 index 00000000..2473e01b --- /dev/null +++ b/samples/C++/program.cp @@ -0,0 +1,170 @@ +/** +The MIT License (MIT) + +Copyright (c) 2016 Sahil Dua ( sahildua2305 | http://sahildua.com ) + +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: + +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.*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +typedef long long ll; +#define DEBUG +#define mod 1000000007 +#define pb push_back + +int r2, c2, n, m; + +bool dfs(vector graph, int r, int c){ + //cout<0){ + if(dfs(graph, r-1, c)) + return true; + } + if(c>0){ + if(dfs(graph, r, c-1)) + return true; + } + if(r<(n-1)){ + if(dfs(graph, r+1, c)) + return true; + } + if(c<(m-1)){ + if(dfs(graph, r, c+1)) + return true; + } + return false; +} + +struct point{ + int r,c; + point(int rr, int cc){ + r = rr; + c = cc; + } +}; + +stack st; + +// if(r>0){ +// if(dfs(graph, r-1, c)) +// return true; +// } +// if(c>0){ +// if(dfs(graph, r, c-1)) +// return true; +// } +// if(r<(n-1)){ +// if(dfs(graph, r+1, c)) +// return true; +// } +// if(c<(m-1)){ +// if(dfs(graph, r, c+1)) +// return true; +// } + +bool search(vector graph, int rr, int cc){ + point t; + t.r=rr; + t.c=cc; + st.push(t); + + while(!st.empty()){ + point u = st.top(); + st.pop(); + int r = u.r, c = u.c; + cout<0){ + t.r=r-1; + t.c=c; + st.push(t); + } + if(c>0){ + t.r=r; + t.c=c-1; + st.push(t); + } + if(r<(n-1)){ + t.r=r+1; + t.c=c; + st.push(t); + } + if(c<(m-1)){ + t.r=r; + t.c=c+1; + st.push(t); + } + } + return false; +} + +int main(){ + ios::sync_with_stdio(false); + #ifdef DEBUG + freopen("input.txt", "r", stdin); + #endif // DEBUG + + cin>>n>>m; + string temp; + vector graph; + for(int i=0;i>temp; + graph.pb(temp); + } + int r1,c1; + cin>>r1>>c1; + cin>>r2>>c2; + r2--; + c2--; + r1--; + c1--; + graph[r1][c1] = '.'; + if(search(graph, r1, c1)) + cout<<"YES\n"; + else + cout<<"NO\n"; + + return 0; +} From b8892250d5b9bba3019971060fd5f3d5ca19bff6 Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Tue, 28 Jun 2016 02:11:54 +0530 Subject: [PATCH 4/6] Remove deleted file name from tests --- test/test_heuristics.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_heuristics.rb b/test/test_heuristics.rb index f73ef7b8..c4ece753 100644 --- a/test/test_heuristics.rb +++ b/test/test_heuristics.rb @@ -147,7 +147,7 @@ class TestHeuristcs < Minitest::Test # Only calling out '.h' filenames as these are the ones causing issues assert_heuristics({ "Objective-C" => all_fixtures("Objective-C", "*.h"), - "C++" => ["C++/scanner.h", "C++/qscicommand.h", "C++/v8.h", "C++/gdsdbreader.h"], + "C++" => ["C++/scanner.h", "C++/v8.h", "C++/gdsdbreader.h"], "C" => nil }) end From 4361ccda32569714020b510d5fe0ef658f4bda64 Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Thu, 30 Jun 2016 20:04:55 +0530 Subject: [PATCH 5/6] Updating tests corresponding to changes in samples --- test/test_heuristics.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_heuristics.rb b/test/test_heuristics.rb index c4ece753..e37da44b 100644 --- a/test/test_heuristics.rb +++ b/test/test_heuristics.rb @@ -147,7 +147,7 @@ class TestHeuristcs < Minitest::Test # Only calling out '.h' filenames as these are the ones causing issues assert_heuristics({ "Objective-C" => all_fixtures("Objective-C", "*.h"), - "C++" => ["C++/scanner.h", "C++/v8.h", "C++/gdsdbreader.h"], + "C++" => ["C++/scanner.h", "C++/protocol-buffer.pb.h", "C++/v8.h", "C++/gdsdbreader.h"], "C" => nil }) end From 68728bcc949304387c6ca43adb3c167e1ddaac4f Mon Sep 17 00:00:00 2001 From: Sahil Dua Date: Sat, 2 Jul 2016 03:25:28 +0530 Subject: [PATCH 6/6] Add .cats sample file --- samples/C/Arduino.cats | 60 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 samples/C/Arduino.cats diff --git a/samples/C/Arduino.cats b/samples/C/Arduino.cats new file mode 100644 index 00000000..fee72ca4 --- /dev/null +++ b/samples/C/Arduino.cats @@ -0,0 +1,60 @@ +/** The MIT License (MIT) + +Copyright (c) 2014 Hongwei Xi + +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: + +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.*/ + +// Source: https://github.com/githwxi/ATS-Postiats-contrib/blob/master/contrib/arduino/CATS/Arduino.cats + + +/* +** The prelude for Ardunio +*/ + +/* ****** ****** */ + +#ifndef ARDUINO_CATS_ARDUINO +#define ARDUINO_CATS_ARDUINO + +/* ****** ****** */ + +#include + +/* ****** ****** */ + +#define delay_int(ms) delay(ms) +#define delay_ulint(ms) delay(ms) + +/* ****** ****** */ +// +#define random_int_1(x) random(x) +#define random_int_2(x, y) random(x, y) +#define random_lint_1(x) random(x) +#define random_lint_2(x, y) random(x, y) +// +#define randomSeed_int(x) randomSeed(x) +#define randomSeed_uint(x) randomSeed(x) +// +/* ****** ****** */ + +#endif // #ifndef(ARDUINO_CATS_ARDUINO) + +/* ****** ****** */ + +/* end of [Arduino.cats] */