40 Commits

Author SHA1 Message Date
6ed7befa47 Doxygen generated by local qwen3-coder-next 2026-02-28 18:32:00 +03:00
0878891cd8 more ai generated doc with human review 2026-02-28 12:29:00 +03:00
077f12c9e5 Merge branch 'master' into doc_ai 2026-02-27 23:59:05 +03:00
9588b48105 PIVector2D - add funcs, optimize, tests, fixes, doxygen (#194)
Reviewed-on: #194
Co-authored-by: andrey.bychkov <andrey@signalmodelling.ru>
Co-committed-by: andrey.bychkov <andrey@signalmodelling.ru>
2026-02-27 23:58:44 +03:00
b53ef184dc add doxygen via opencode 2026-02-27 23:54:48 +03:00
1739836a18 fix pistatistic mean calc 2026-02-25 17:50:56 +03:00
7195734765 add more tests 2026-02-17 21:53:18 +03:00
8ecec6b914 add more funcs 2026-02-17 21:40:36 +03:00
9029bcf099 Vibecoding PIVector2D - add funcs and doc
Добавь в файл pivector2d.h комментарии для Doxygen ко всем классам и
всем функциям.
Комментарии должны быть в таком же стиле как в файле pivector.h.

Проанализируй функциональность классов pivector2d в файле pivector2d.h и
класс pivector в файле pivector.h и добавь недостающую функциональность
в pivector2d по аналогии с pivector.
2026-02-17 21:04:40 +03:00
6f1660fd9e version 5.5.5
fix PIHIDevice enumeration for Windows
2026-02-13 18:47:33 +03:00
f50a3abc8e PIString::buildData for ICU fix according to official doc 2026-02-08 17:01:52 +03:00
8c15113cb0 fix PIHTTPClient with queryArguments 2026-02-08 02:50:54 +03:00
4253acb72b rename override to override_vt 2026-02-03 20:33:23 +03:00
e22630b1bd version 5.5.4
add PIValueTree::merge
PIValueTreeConversions::from*File supports .override files (replace or add values)
empty JSON arrays now 0 size
2026-02-03 18:56:58 +03:00
563d9c5487 value_tree_translator: add toolTip 2026-01-22 11:48:29 +03:00
34bc322b9b version 5.5.3
force using '.' instead of ',' in PIString::fromNumber()
2025-10-22 15:24:10 +03:00
6c3c763934 try fix old mingw 2025-10-17 11:30:41 +03:00
4d841787fc version 5.5.2
PIVariant complex(f,d,ld) full support
2025-10-16 11:47:55 +03:00
790246afea add miss files, add PIUnits::Distance and PIUnits::Mass 2025-10-10 19:47:25 +03:00
978e350722 version 5.5.1
add SipHash and HalfSipHash for PIDigest
2025-10-08 21:15:28 +03:00
1d76cacae2 code brush some digest 2025-10-08 16:59:56 +03:00
db954ffdaa version 5.5.0
add PIIODevice::threadedReadTimeout
2025-09-29 18:48:20 +03:00
8d6ae976a3 remove comment 2025-09-26 21:38:41 +03:00
e767fae934 merge pscreen_win_u16 2025-09-26 21:35:36 +03:00
5db97ca959 version 5.4.0
remove CORS default header from PIHTTPServer
fix several docs
fix PIMathVector::dot return type
add units directory with PIUnits facility
2025-09-26 21:33:45 +03:00
daab41e41e add options for fftw3 precisions
configureFromFullPathDevice for all devices now trim() components
2025-09-23 21:16:54 +03:00
a61c8477c7 fix PIMap operator<<(PIMap) error for size=2 2025-09-22 22:34:06 +03:00
788ad8f2c0 PIVariant::toNum from mathvector safety fix 2025-09-22 20:58:58 +03:00
78afc179c4 PIVariant::toNum now from mathvector 2025-09-22 16:26:09 +03:00
69ec4c9837 .clang-format 2025-09-21 21:08:18 +03:00
2368de6e93 rename PRIVATE_DEFINITION_FINISH to PRIVATE_DEFINITION_END_NO_INITIALIZE 2025-09-21 21:05:56 +03:00
e5df76ab1d decompose PRIVATE_DEFINITION_END(c) to PRIVATE_DEFINITION_FINISH(c) and RIVATE_DEFINITION_INITIALIZE(c)
now you can define private in separate file and initialize it in main cpp
2025-09-19 17:39:39 +03:00
fdec0e66a8 Merge pull request 'codeparser_C' (#192) from codeparser_C into master
Reviewed-on: #192
2025-09-18 20:19:11 +03:00
5f3baa5580 PICODEINFO::accessOffsetFunction
add offset generation in pip_cmg for retrieve bytes offset of struct member
add pip_cmg -V doc
2025-09-18 17:12:35 +03:00
7083b2c32b finish codeparser improvements
pip_cmg now works with new nested entities approach
Getters now can access to bitfields
2025-09-18 05:54:31 +03:00
af02684dc5 adopt PICodeParser for C-style typedefs and some other 2025-09-17 19:42:00 +03:00
2806086558 add "const" to PIByteArray::dataAs 2025-09-15 21:21:58 +03:00
ce962bfb40 fix for new pip 2025-09-15 19:47:32 +03:00
dcdd7db33d version 5.2.1
fix potentially errors in PIConstChars compare methods
PIHIDevice::open() for open last device
PIVariant::toPoint() now can cast from PIMathVectord
2025-09-13 17:25:12 +03:00
3c72db2de8 add PIHIDevice 2025-09-11 21:06:30 +03:00
204 changed files with 17900 additions and 2557 deletions

View File

@@ -134,8 +134,8 @@ JavaScriptQuotes: Leave
JavaScriptWrapImports: true JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature LambdaBodyIndentation: Signature
MacroBlockBegin: "PRIVATE_DEFINITION_START|STATIC_INITIALIZER_BEGIN" MacroBlockBegin: "PRIVATE_DEFINITION_START|STATIC_INITIALIZER_BEGIN|DECLARE_UNIT_CLASS_BEGIN"
MacroBlockEnd: "PRIVATE_DEFINITION_END|STATIC_INITIALIZER_END" MacroBlockEnd: "PRIVATE_DEFINITION_END|PRIVATE_DEFINITION_END_NO_INITIALIZE|STATIC_INITIALIZER_END|DECLARE_UNIT_CLASS_END"
MaxEmptyLinesToKeep: 2 MaxEmptyLinesToKeep: 2
NamespaceIndentation: None NamespaceIndentation: None
ObjCBinPackProtocolList: Auto ObjCBinPackProtocolList: Auto

4
.gitignore vendored
View File

@@ -1,8 +1,10 @@
/.*
/src_main/piversion.h /src_main/piversion.h
/.svn
/doc/rtf /doc/rtf
_unsused _unsused
CMakeLists.txt.user* CMakeLists.txt.user*
/include /include
/release /release
/build* /build*
/AGENTS.md
/plans

121
3rd/BLAKE2/COPYING Normal file
View File

@@ -0,0 +1,121 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

219
3rd/SipHash/LICENSE_A2LLVM Normal file
View File

@@ -0,0 +1,219 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---- LLVM Exceptions to the Apache 2.0 License ----
As an exception, if, as a result of your compiling your source code, portions
of this Software are embedded into an Object form of such source code, you
may redistribute such embedded portions in such Object form without complying
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
In addition, if you combine or link compiled forms of this Software with
software that is licensed under the GPLv2 ("Combined Software") and if a
court of competent jurisdiction determines that the patent provision (Section
3), the indemnity provision (Section 9) or other Section of the License
conflicts with the conditions of the GPLv2, you may retroactively and
prospectively choose to deem waived or otherwise exclude such Section(s) of
the License, but only in their entirety and only with respect to the Combined
Software.

116
3rd/SipHash/LICENSE_CC0 Normal file
View File

@@ -0,0 +1,116 @@
CC0 1.0 Universal
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.
For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>

7
3rd/SipHash/LICENSE_MIT Normal file
View File

@@ -0,0 +1,7 @@
Copyright 2012-2024 JP Aumasson
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.

166
3rd/SipHash/halfsiphash.c Normal file
View File

@@ -0,0 +1,166 @@
/*
SipHash reference C implementation
Copyright (c) 2016 Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "halfsiphash.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
/* default: SipHash-2-4 */
#ifndef cROUNDS
#define cROUNDS 2
#endif
#ifndef dROUNDS
#define dROUNDS 4
#endif
#define ROTL(x, b) (uint32_t)(((x) << (b)) | ((x) >> (32 - (b))))
#define U32TO8_LE(p, v) \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24);
#define U8TO32_LE(p) \
(((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
#define SIPROUND \
do { \
v0 += v1; \
v1 = ROTL(v1, 5); \
v1 ^= v0; \
v0 = ROTL(v0, 16); \
v2 += v3; \
v3 = ROTL(v3, 8); \
v3 ^= v2; \
v0 += v3; \
v3 = ROTL(v3, 7); \
v3 ^= v0; \
v2 += v1; \
v1 = ROTL(v1, 13); \
v1 ^= v2; \
v2 = ROTL(v2, 16); \
} while (0)
#ifdef DEBUG_SIPHASH
#include <stdio.h>
#define TRACE \
do { \
printf("(%3zu) v0 %08" PRIx32 "\n", inlen, v0); \
printf("(%3zu) v1 %08" PRIx32 "\n", inlen, v1); \
printf("(%3zu) v2 %08" PRIx32 "\n", inlen, v2); \
printf("(%3zu) v3 %08" PRIx32 "\n", inlen, v3); \
} while (0)
#else
#define TRACE
#endif
/*
Computes a SipHash value
*in: pointer to input data (read-only)
inlen: input data length in bytes (any size_t value)
*k: pointer to the key data (read-only), must be 8 bytes
*out: pointer to output data (write-only), outlen bytes must be allocated
outlen: length of the output in bytes, must be 4 or 8
*/
int halfsiphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
const size_t outlen) {
const unsigned char *ni = (const unsigned char *)in;
const unsigned char *kk = (const unsigned char *)k;
assert((outlen == 4) || (outlen == 8));
uint32_t v0 = 0;
uint32_t v1 = 0;
uint32_t v2 = UINT32_C(0x6c796765);
uint32_t v3 = UINT32_C(0x74656462);
uint32_t k0 = U8TO32_LE(kk);
uint32_t k1 = U8TO32_LE(kk + 4);
uint32_t m;
int i;
const unsigned char *end = ni + inlen - (inlen % sizeof(uint32_t));
const int left = inlen & 3;
uint32_t b = ((uint32_t)inlen) << 24;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
if (outlen == 8)
v1 ^= 0xee;
for (; ni != end; ni += 4) {
m = U8TO32_LE(ni);
v3 ^= m;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= m;
}
switch (left) {
case 3:
b |= ((uint32_t)ni[2]) << 16;
/* FALLTHRU */
case 2:
b |= ((uint32_t)ni[1]) << 8;
/* FALLTHRU */
case 1:
b |= ((uint32_t)ni[0]);
break;
case 0:
break;
}
v3 ^= b;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= b;
if (outlen == 8)
v2 ^= 0xee;
else
v2 ^= 0xff;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v1 ^ v3;
U32TO8_LE(out, b);
if (outlen == 4)
return 0;
v1 ^= 0xdd;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v1 ^ v3;
U32TO8_LE(out + 4, b);
return 0;
}

34
3rd/SipHash/halfsiphash.h Normal file
View File

@@ -0,0 +1,34 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2021 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef HALFSIPHASH_H
#define HALFSIPHASH_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
int halfsiphash(const void * in, const size_t inlen, const void * k, uint8_t * out, const size_t outlen);
#if defined(__cplusplus)
}
#endif
#endif

185
3rd/SipHash/siphash.c Normal file
View File

@@ -0,0 +1,185 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2022 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#include "siphash.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
/* default: SipHash-2-4 */
#ifndef cROUNDS
#define cROUNDS 2
#endif
#ifndef dROUNDS
#define dROUNDS 4
#endif
#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
#define U32TO8_LE(p, v) \
(p)[0] = (uint8_t)((v)); \
(p)[1] = (uint8_t)((v) >> 8); \
(p)[2] = (uint8_t)((v) >> 16); \
(p)[3] = (uint8_t)((v) >> 24);
#define U64TO8_LE(p, v) \
U32TO8_LE((p), (uint32_t)((v))); \
U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
#define U8TO64_LE(p) \
(((uint64_t)((p)[0])) | ((uint64_t)((p)[1]) << 8) | \
((uint64_t)((p)[2]) << 16) | ((uint64_t)((p)[3]) << 24) | \
((uint64_t)((p)[4]) << 32) | ((uint64_t)((p)[5]) << 40) | \
((uint64_t)((p)[6]) << 48) | ((uint64_t)((p)[7]) << 56))
#define SIPROUND \
do { \
v0 += v1; \
v1 = ROTL(v1, 13); \
v1 ^= v0; \
v0 = ROTL(v0, 32); \
v2 += v3; \
v3 = ROTL(v3, 16); \
v3 ^= v2; \
v0 += v3; \
v3 = ROTL(v3, 21); \
v3 ^= v0; \
v2 += v1; \
v1 = ROTL(v1, 17); \
v1 ^= v2; \
v2 = ROTL(v2, 32); \
} while (0)
#ifdef DEBUG_SIPHASH
#include <stdio.h>
#define TRACE \
do { \
printf("(%3zu) v0 %016" PRIx64 "\n", inlen, v0); \
printf("(%3zu) v1 %016" PRIx64 "\n", inlen, v1); \
printf("(%3zu) v2 %016" PRIx64 "\n", inlen, v2); \
printf("(%3zu) v3 %016" PRIx64 "\n", inlen, v3); \
} while (0)
#else
#define TRACE
#endif
/*
Computes a SipHash value
*in: pointer to input data (read-only)
inlen: input data length in bytes (any size_t value)
*k: pointer to the key data (read-only), must be 16 bytes
*out: pointer to output data (write-only), outlen bytes must be allocated
outlen: length of the output in bytes, must be 8 or 16
*/
int siphash(const void *in, const size_t inlen, const void *k, uint8_t *out,
const size_t outlen) {
const unsigned char *ni = (const unsigned char *)in;
const unsigned char *kk = (const unsigned char *)k;
assert((outlen == 8) || (outlen == 16));
uint64_t v0 = UINT64_C(0x736f6d6570736575);
uint64_t v1 = UINT64_C(0x646f72616e646f6d);
uint64_t v2 = UINT64_C(0x6c7967656e657261);
uint64_t v3 = UINT64_C(0x7465646279746573);
uint64_t k0 = U8TO64_LE(kk);
uint64_t k1 = U8TO64_LE(kk + 8);
uint64_t m;
int i;
const unsigned char *end = ni + inlen - (inlen % sizeof(uint64_t));
const int left = inlen & 7;
uint64_t b = ((uint64_t)inlen) << 56;
v3 ^= k1;
v2 ^= k0;
v1 ^= k1;
v0 ^= k0;
if (outlen == 16)
v1 ^= 0xee;
for (; ni != end; ni += 8) {
m = U8TO64_LE(ni);
v3 ^= m;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= m;
}
switch (left) {
case 7:
b |= ((uint64_t)ni[6]) << 48;
/* FALLTHRU */
case 6:
b |= ((uint64_t)ni[5]) << 40;
/* FALLTHRU */
case 5:
b |= ((uint64_t)ni[4]) << 32;
/* FALLTHRU */
case 4:
b |= ((uint64_t)ni[3]) << 24;
/* FALLTHRU */
case 3:
b |= ((uint64_t)ni[2]) << 16;
/* FALLTHRU */
case 2:
b |= ((uint64_t)ni[1]) << 8;
/* FALLTHRU */
case 1:
b |= ((uint64_t)ni[0]);
break;
case 0:
break;
}
v3 ^= b;
TRACE;
for (i = 0; i < cROUNDS; ++i)
SIPROUND;
v0 ^= b;
if (outlen == 16)
v2 ^= 0xee;
else
v2 ^= 0xff;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out, b);
if (outlen == 8)
return 0;
v1 ^= 0xdd;
TRACE;
for (i = 0; i < dROUNDS; ++i)
SIPROUND;
b = v0 ^ v1 ^ v2 ^ v3;
U64TO8_LE(out + 8, b);
return 0;
}

34
3rd/SipHash/siphash.h Normal file
View File

@@ -0,0 +1,34 @@
/*
SipHash reference C implementation
Copyright (c) 2012-2021 Jean-Philippe Aumasson
<jeanphilippe.aumasson@gmail.com>
Copyright (c) 2012-2014 Daniel J. Bernstein <djb@cr.yp.to>
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
worldwide. This software is distributed without any warranty.
You should have received a copy of the CC0 Public Domain Dedication along
with
this software. If not, see
<http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef SIPHASH_H
#define SIPHASH_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
int siphash(const void * in, const size_t inlen, const void * k, uint8_t * out, const size_t outlen);
#if defined(__cplusplus)
}
#endif
#endif

2826
3rd/SipHash/vectors.h Normal file
View File

@@ -0,0 +1,2826 @@
#include <stdint.h>
const uint8_t vectors_sip64[64][8] = {
{
0x31,
0x0e,
0x0e,
0xdd,
0x47,
0xdb,
0x6f,
0x72,
},
{
0xfd,
0x67,
0xdc,
0x93,
0xc5,
0x39,
0xf8,
0x74,
},
{
0x5a,
0x4f,
0xa9,
0xd9,
0x09,
0x80,
0x6c,
0x0d,
},
{
0x2d,
0x7e,
0xfb,
0xd7,
0x96,
0x66,
0x67,
0x85,
},
{
0xb7,
0x87,
0x71,
0x27,
0xe0,
0x94,
0x27,
0xcf,
},
{
0x8d,
0xa6,
0x99,
0xcd,
0x64,
0x55,
0x76,
0x18,
},
{
0xce,
0xe3,
0xfe,
0x58,
0x6e,
0x46,
0xc9,
0xcb,
},
{
0x37,
0xd1,
0x01,
0x8b,
0xf5,
0x00,
0x02,
0xab,
},
{
0x62,
0x24,
0x93,
0x9a,
0x79,
0xf5,
0xf5,
0x93,
},
{
0xb0,
0xe4,
0xa9,
0x0b,
0xdf,
0x82,
0x00,
0x9e,
},
{
0xf3,
0xb9,
0xdd,
0x94,
0xc5,
0xbb,
0x5d,
0x7a,
},
{
0xa7,
0xad,
0x6b,
0x22,
0x46,
0x2f,
0xb3,
0xf4,
},
{
0xfb,
0xe5,
0x0e,
0x86,
0xbc,
0x8f,
0x1e,
0x75,
},
{
0x90,
0x3d,
0x84,
0xc0,
0x27,
0x56,
0xea,
0x14,
},
{
0xee,
0xf2,
0x7a,
0x8e,
0x90,
0xca,
0x23,
0xf7,
},
{
0xe5,
0x45,
0xbe,
0x49,
0x61,
0xca,
0x29,
0xa1,
},
{
0xdb,
0x9b,
0xc2,
0x57,
0x7f,
0xcc,
0x2a,
0x3f,
},
{
0x94,
0x47,
0xbe,
0x2c,
0xf5,
0xe9,
0x9a,
0x69,
},
{
0x9c,
0xd3,
0x8d,
0x96,
0xf0,
0xb3,
0xc1,
0x4b,
},
{
0xbd,
0x61,
0x79,
0xa7,
0x1d,
0xc9,
0x6d,
0xbb,
},
{
0x98,
0xee,
0xa2,
0x1a,
0xf2,
0x5c,
0xd6,
0xbe,
},
{
0xc7,
0x67,
0x3b,
0x2e,
0xb0,
0xcb,
0xf2,
0xd0,
},
{
0x88,
0x3e,
0xa3,
0xe3,
0x95,
0x67,
0x53,
0x93,
},
{
0xc8,
0xce,
0x5c,
0xcd,
0x8c,
0x03,
0x0c,
0xa8,
},
{
0x94,
0xaf,
0x49,
0xf6,
0xc6,
0x50,
0xad,
0xb8,
},
{
0xea,
0xb8,
0x85,
0x8a,
0xde,
0x92,
0xe1,
0xbc,
},
{
0xf3,
0x15,
0xbb,
0x5b,
0xb8,
0x35,
0xd8,
0x17,
},
{
0xad,
0xcf,
0x6b,
0x07,
0x63,
0x61,
0x2e,
0x2f,
},
{
0xa5,
0xc9,
0x1d,
0xa7,
0xac,
0xaa,
0x4d,
0xde,
},
{
0x71,
0x65,
0x95,
0x87,
0x66,
0x50,
0xa2,
0xa6,
},
{
0x28,
0xef,
0x49,
0x5c,
0x53,
0xa3,
0x87,
0xad,
},
{
0x42,
0xc3,
0x41,
0xd8,
0xfa,
0x92,
0xd8,
0x32,
},
{
0xce,
0x7c,
0xf2,
0x72,
0x2f,
0x51,
0x27,
0x71,
},
{
0xe3,
0x78,
0x59,
0xf9,
0x46,
0x23,
0xf3,
0xa7,
},
{
0x38,
0x12,
0x05,
0xbb,
0x1a,
0xb0,
0xe0,
0x12,
},
{
0xae,
0x97,
0xa1,
0x0f,
0xd4,
0x34,
0xe0,
0x15,
},
{
0xb4,
0xa3,
0x15,
0x08,
0xbe,
0xff,
0x4d,
0x31,
},
{
0x81,
0x39,
0x62,
0x29,
0xf0,
0x90,
0x79,
0x02,
},
{
0x4d,
0x0c,
0xf4,
0x9e,
0xe5,
0xd4,
0xdc,
0xca,
},
{
0x5c,
0x73,
0x33,
0x6a,
0x76,
0xd8,
0xbf,
0x9a,
},
{
0xd0,
0xa7,
0x04,
0x53,
0x6b,
0xa9,
0x3e,
0x0e,
},
{
0x92,
0x59,
0x58,
0xfc,
0xd6,
0x42,
0x0c,
0xad,
},
{
0xa9,
0x15,
0xc2,
0x9b,
0xc8,
0x06,
0x73,
0x18,
},
{
0x95,
0x2b,
0x79,
0xf3,
0xbc,
0x0a,
0xa6,
0xd4,
},
{
0xf2,
0x1d,
0xf2,
0xe4,
0x1d,
0x45,
0x35,
0xf9,
},
{
0x87,
0x57,
0x75,
0x19,
0x04,
0x8f,
0x53,
0xa9,
},
{
0x10,
0xa5,
0x6c,
0xf5,
0xdf,
0xcd,
0x9a,
0xdb,
},
{
0xeb,
0x75,
0x09,
0x5c,
0xcd,
0x98,
0x6c,
0xd0,
},
{
0x51,
0xa9,
0xcb,
0x9e,
0xcb,
0xa3,
0x12,
0xe6,
},
{
0x96,
0xaf,
0xad,
0xfc,
0x2c,
0xe6,
0x66,
0xc7,
},
{
0x72,
0xfe,
0x52,
0x97,
0x5a,
0x43,
0x64,
0xee,
},
{
0x5a,
0x16,
0x45,
0xb2,
0x76,
0xd5,
0x92,
0xa1,
},
{
0xb2,
0x74,
0xcb,
0x8e,
0xbf,
0x87,
0x87,
0x0a,
},
{
0x6f,
0x9b,
0xb4,
0x20,
0x3d,
0xe7,
0xb3,
0x81,
},
{
0xea,
0xec,
0xb2,
0xa3,
0x0b,
0x22,
0xa8,
0x7f,
},
{
0x99,
0x24,
0xa4,
0x3c,
0xc1,
0x31,
0x57,
0x24,
},
{
0xbd,
0x83,
0x8d,
0x3a,
0xaf,
0xbf,
0x8d,
0xb7,
},
{
0x0b,
0x1a,
0x2a,
0x32,
0x65,
0xd5,
0x1a,
0xea,
},
{
0x13,
0x50,
0x79,
0xa3,
0x23,
0x1c,
0xe6,
0x60,
},
{
0x93,
0x2b,
0x28,
0x46,
0xe4,
0xd7,
0x06,
0x66,
},
{
0xe1,
0x91,
0x5f,
0x5c,
0xb1,
0xec,
0xa4,
0x6c,
},
{
0xf3,
0x25,
0x96,
0x5c,
0xa1,
0x6d,
0x62,
0x9f,
},
{
0x57,
0x5f,
0xf2,
0x8e,
0x60,
0x38,
0x1b,
0xe5,
},
{
0x72,
0x45,
0x06,
0xeb,
0x4c,
0x32,
0x8a,
0x95,
},
};
const uint8_t vectors_sip128[64][16] = {
{
0xa3,
0x81,
0x7f,
0x04,
0xba,
0x25,
0xa8,
0xe6,
0x6d,
0xf6,
0x72,
0x14,
0xc7,
0x55,
0x02,
0x93,
},
{
0xda,
0x87,
0xc1,
0xd8,
0x6b,
0x99,
0xaf,
0x44,
0x34,
0x76,
0x59,
0x11,
0x9b,
0x22,
0xfc,
0x45,
},
{
0x81,
0x77,
0x22,
0x8d,
0xa4,
0xa4,
0x5d,
0xc7,
0xfc,
0xa3,
0x8b,
0xde,
0xf6,
0x0a,
0xff,
0xe4,
},
{
0x9c,
0x70,
0xb6,
0x0c,
0x52,
0x67,
0xa9,
0x4e,
0x5f,
0x33,
0xb6,
0xb0,
0x29,
0x85,
0xed,
0x51,
},
{
0xf8,
0x81,
0x64,
0xc1,
0x2d,
0x9c,
0x8f,
0xaf,
0x7d,
0x0f,
0x6e,
0x7c,
0x7b,
0xcd,
0x55,
0x79,
},
{
0x13,
0x68,
0x87,
0x59,
0x80,
0x77,
0x6f,
0x88,
0x54,
0x52,
0x7a,
0x07,
0x69,
0x0e,
0x96,
0x27,
},
{
0x14,
0xee,
0xca,
0x33,
0x8b,
0x20,
0x86,
0x13,
0x48,
0x5e,
0xa0,
0x30,
0x8f,
0xd7,
0xa1,
0x5e,
},
{
0xa1,
0xf1,
0xeb,
0xbe,
0xd8,
0xdb,
0xc1,
0x53,
0xc0,
0xb8,
0x4a,
0xa6,
0x1f,
0xf0,
0x82,
0x39,
},
{
0x3b,
0x62,
0xa9,
0xba,
0x62,
0x58,
0xf5,
0x61,
0x0f,
0x83,
0xe2,
0x64,
0xf3,
0x14,
0x97,
0xb4,
},
{
0x26,
0x44,
0x99,
0x06,
0x0a,
0xd9,
0xba,
0xab,
0xc4,
0x7f,
0x8b,
0x02,
0xbb,
0x6d,
0x71,
0xed,
},
{
0x00,
0x11,
0x0d,
0xc3,
0x78,
0x14,
0x69,
0x56,
0xc9,
0x54,
0x47,
0xd3,
0xf3,
0xd0,
0xfb,
0xba,
},
{
0x01,
0x51,
0xc5,
0x68,
0x38,
0x6b,
0x66,
0x77,
0xa2,
0xb4,
0xdc,
0x6f,
0x81,
0xe5,
0xdc,
0x18,
},
{
0xd6,
0x26,
0xb2,
0x66,
0x90,
0x5e,
0xf3,
0x58,
0x82,
0x63,
0x4d,
0xf6,
0x85,
0x32,
0xc1,
0x25,
},
{
0x98,
0x69,
0xe2,
0x47,
0xe9,
0xc0,
0x8b,
0x10,
0xd0,
0x29,
0x93,
0x4f,
0xc4,
0xb9,
0x52,
0xf7,
},
{
0x31,
0xfc,
0xef,
0xac,
0x66,
0xd7,
0xde,
0x9c,
0x7e,
0xc7,
0x48,
0x5f,
0xe4,
0x49,
0x49,
0x02,
},
{
0x54,
0x93,
0xe9,
0x99,
0x33,
0xb0,
0xa8,
0x11,
0x7e,
0x08,
0xec,
0x0f,
0x97,
0xcf,
0xc3,
0xd9,
},
{
0x6e,
0xe2,
0xa4,
0xca,
0x67,
0xb0,
0x54,
0xbb,
0xfd,
0x33,
0x15,
0xbf,
0x85,
0x23,
0x05,
0x77,
},
{
0x47,
0x3d,
0x06,
0xe8,
0x73,
0x8d,
0xb8,
0x98,
0x54,
0xc0,
0x66,
0xc4,
0x7a,
0xe4,
0x77,
0x40,
},
{
0xa4,
0x26,
0xe5,
0xe4,
0x23,
0xbf,
0x48,
0x85,
0x29,
0x4d,
0xa4,
0x81,
0xfe,
0xae,
0xf7,
0x23,
},
{
0x78,
0x01,
0x77,
0x31,
0xcf,
0x65,
0xfa,
0xb0,
0x74,
0xd5,
0x20,
0x89,
0x52,
0x51,
0x2e,
0xb1,
},
{
0x9e,
0x25,
0xfc,
0x83,
0x3f,
0x22,
0x90,
0x73,
0x3e,
0x93,
0x44,
0xa5,
0xe8,
0x38,
0x39,
0xeb,
},
{
0x56,
0x8e,
0x49,
0x5a,
0xbe,
0x52,
0x5a,
0x21,
0x8a,
0x22,
0x14,
0xcd,
0x3e,
0x07,
0x1d,
0x12,
},
{
0x4a,
0x29,
0xb5,
0x45,
0x52,
0xd1,
0x6b,
0x9a,
0x46,
0x9c,
0x10,
0x52,
0x8e,
0xff,
0x0a,
0xae,
},
{
0xc9,
0xd1,
0x84,
0xdd,
0xd5,
0xa9,
0xf5,
0xe0,
0xcf,
0x8c,
0xe2,
0x9a,
0x9a,
0xbf,
0x69,
0x1c,
},
{
0x2d,
0xb4,
0x79,
0xae,
0x78,
0xbd,
0x50,
0xd8,
0x88,
0x2a,
0x8a,
0x17,
0x8a,
0x61,
0x32,
0xad,
},
{
0x8e,
0xce,
0x5f,
0x04,
0x2d,
0x5e,
0x44,
0x7b,
0x50,
0x51,
0xb9,
0xea,
0xcb,
0x8d,
0x8f,
0x6f,
},
{
0x9c,
0x0b,
0x53,
0xb4,
0xb3,
0xc3,
0x07,
0xe8,
0x7e,
0xae,
0xe0,
0x86,
0x78,
0x14,
0x1f,
0x66,
},
{
0xab,
0xf2,
0x48,
0xaf,
0x69,
0xa6,
0xea,
0xe4,
0xbf,
0xd3,
0xeb,
0x2f,
0x12,
0x9e,
0xeb,
0x94,
},
{
0x06,
0x64,
0xda,
0x16,
0x68,
0x57,
0x4b,
0x88,
0xb9,
0x35,
0xf3,
0x02,
0x73,
0x58,
0xae,
0xf4,
},
{
0xaa,
0x4b,
0x9d,
0xc4,
0xbf,
0x33,
0x7d,
0xe9,
0x0c,
0xd4,
0xfd,
0x3c,
0x46,
0x7c,
0x6a,
0xb7,
},
{
0xea,
0x5c,
0x7f,
0x47,
0x1f,
0xaf,
0x6b,
0xde,
0x2b,
0x1a,
0xd7,
0xd4,
0x68,
0x6d,
0x22,
0x87,
},
{
0x29,
0x39,
0xb0,
0x18,
0x32,
0x23,
0xfa,
0xfc,
0x17,
0x23,
0xde,
0x4f,
0x52,
0xc4,
0x3d,
0x35,
},
{
0x7c,
0x39,
0x56,
0xca,
0x5e,
0xea,
0xfc,
0x3e,
0x36,
0x3e,
0x9d,
0x55,
0x65,
0x46,
0xeb,
0x68,
},
{
0x77,
0xc6,
0x07,
0x71,
0x46,
0xf0,
0x1c,
0x32,
0xb6,
0xb6,
0x9d,
0x5f,
0x4e,
0xa9,
0xff,
0xcf,
},
{
0x37,
0xa6,
0x98,
0x6c,
0xb8,
0x84,
0x7e,
0xdf,
0x09,
0x25,
0xf0,
0xf1,
0x30,
0x9b,
0x54,
0xde,
},
{
0xa7,
0x05,
0xf0,
0xe6,
0x9d,
0xa9,
0xa8,
0xf9,
0x07,
0x24,
0x1a,
0x2e,
0x92,
0x3c,
0x8c,
0xc8,
},
{
0x3d,
0xc4,
0x7d,
0x1f,
0x29,
0xc4,
0x48,
0x46,
0x1e,
0x9e,
0x76,
0xed,
0x90,
0x4f,
0x67,
0x11,
},
{
0x0d,
0x62,
0xbf,
0x01,
0xe6,
0xfc,
0x0e,
0x1a,
0x0d,
0x3c,
0x47,
0x51,
0xc5,
0xd3,
0x69,
0x2b,
},
{
0x8c,
0x03,
0x46,
0x8b,
0xca,
0x7c,
0x66,
0x9e,
0xe4,
0xfd,
0x5e,
0x08,
0x4b,
0xbe,
0xe7,
0xb5,
},
{
0x52,
0x8a,
0x5b,
0xb9,
0x3b,
0xaf,
0x2c,
0x9c,
0x44,
0x73,
0xcc,
0xe5,
0xd0,
0xd2,
0x2b,
0xd9,
},
{
0xdf,
0x6a,
0x30,
0x1e,
0x95,
0xc9,
0x5d,
0xad,
0x97,
0xae,
0x0c,
0xc8,
0xc6,
0x91,
0x3b,
0xd8,
},
{
0x80,
0x11,
0x89,
0x90,
0x2c,
0x85,
0x7f,
0x39,
0xe7,
0x35,
0x91,
0x28,
0x5e,
0x70,
0xb6,
0xdb,
},
{
0xe6,
0x17,
0x34,
0x6a,
0xc9,
0xc2,
0x31,
0xbb,
0x36,
0x50,
0xae,
0x34,
0xcc,
0xca,
0x0c,
0x5b,
},
{
0x27,
0xd9,
0x34,
0x37,
0xef,
0xb7,
0x21,
0xaa,
0x40,
0x18,
0x21,
0xdc,
0xec,
0x5a,
0xdf,
0x89,
},
{
0x89,
0x23,
0x7d,
0x9d,
0xed,
0x9c,
0x5e,
0x78,
0xd8,
0xb1,
0xc9,
0xb1,
0x66,
0xcc,
0x73,
0x42,
},
{
0x4a,
0x6d,
0x80,
0x91,
0xbf,
0x5e,
0x7d,
0x65,
0x11,
0x89,
0xfa,
0x94,
0xa2,
0x50,
0xb1,
0x4c,
},
{
0x0e,
0x33,
0xf9,
0x60,
0x55,
0xe7,
0xae,
0x89,
0x3f,
0xfc,
0x0e,
0x3d,
0xcf,
0x49,
0x29,
0x02,
},
{
0xe6,
0x1c,
0x43,
0x2b,
0x72,
0x0b,
0x19,
0xd1,
0x8e,
0xc8,
0xd8,
0x4b,
0xdc,
0x63,
0x15,
0x1b,
},
{
0xf7,
0xe5,
0xae,
0xf5,
0x49,
0xf7,
0x82,
0xcf,
0x37,
0x90,
0x55,
0xa6,
0x08,
0x26,
0x9b,
0x16,
},
{
0x43,
0x8d,
0x03,
0x0f,
0xd0,
0xb7,
0xa5,
0x4f,
0xa8,
0x37,
0xf2,
0xad,
0x20,
0x1a,
0x64,
0x03,
},
{
0xa5,
0x90,
0xd3,
0xee,
0x4f,
0xbf,
0x04,
0xe3,
0x24,
0x7e,
0x0d,
0x27,
0xf2,
0x86,
0x42,
0x3f,
},
{
0x5f,
0xe2,
0xc1,
0xa1,
0x72,
0xfe,
0x93,
0xc4,
0xb1,
0x5c,
0xd3,
0x7c,
0xae,
0xf9,
0xf5,
0x38,
},
{
0x2c,
0x97,
0x32,
0x5c,
0xbd,
0x06,
0xb3,
0x6e,
0xb2,
0x13,
0x3d,
0xd0,
0x8b,
0x3a,
0x01,
0x7c,
},
{
0x92,
0xc8,
0x14,
0x22,
0x7a,
0x6b,
0xca,
0x94,
0x9f,
0xf0,
0x65,
0x9f,
0x00,
0x2a,
0xd3,
0x9e,
},
{
0xdc,
0xe8,
0x50,
0x11,
0x0b,
0xd8,
0x32,
0x8c,
0xfb,
0xd5,
0x08,
0x41,
0xd6,
0x91,
0x1d,
0x87,
},
{
0x67,
0xf1,
0x49,
0x84,
0xc7,
0xda,
0x79,
0x12,
0x48,
0xe3,
0x2b,
0xb5,
0x92,
0x25,
0x83,
0xda,
},
{
0x19,
0x38,
0xf2,
0xcf,
0x72,
0xd5,
0x4e,
0xe9,
0x7e,
0x94,
0x16,
0x6f,
0xa9,
0x1d,
0x2a,
0x36,
},
{
0x74,
0x48,
0x1e,
0x96,
0x46,
0xed,
0x49,
0xfe,
0x0f,
0x62,
0x24,
0x30,
0x16,
0x04,
0x69,
0x8e,
},
{
0x57,
0xfc,
0xa5,
0xde,
0x98,
0xa9,
0xd6,
0xd8,
0x00,
0x64,
0x38,
0xd0,
0x58,
0x3d,
0x8a,
0x1d,
},
{
0x9f,
0xec,
0xde,
0x1c,
0xef,
0xdc,
0x1c,
0xbe,
0xd4,
0x76,
0x36,
0x74,
0xd9,
0x57,
0x53,
0x59,
},
{
0xe3,
0x04,
0x0c,
0x00,
0xeb,
0x28,
0xf1,
0x53,
0x66,
0xca,
0x73,
0xcb,
0xd8,
0x72,
0xe7,
0x40,
},
{
0x76,
0x97,
0x00,
0x9a,
0x6a,
0x83,
0x1d,
0xfe,
0xcc,
0xa9,
0x1c,
0x59,
0x93,
0x67,
0x0f,
0x7a,
},
{
0x58,
0x53,
0x54,
0x23,
0x21,
0xf5,
0x67,
0xa0,
0x05,
0xd5,
0x47,
0xa4,
0xf0,
0x47,
0x59,
0xbd,
},
{
0x51,
0x50,
0xd1,
0x77,
0x2f,
0x50,
0x83,
0x4a,
0x50,
0x3e,
0x06,
0x9a,
0x97,
0x3f,
0xbd,
0x7c,
},
};
const uint8_t vectors_hsip32[64][4] = {
{
0xa9,
0x35,
0x9f,
0x5b,
},
{
0x27,
0x47,
0x5a,
0xb8,
},
{
0xfa,
0x62,
0xa6,
0x03,
},
{
0x8a,
0xfe,
0xe7,
0x04,
},
{
0x2a,
0x6e,
0x46,
0x89,
},
{
0xc5,
0xfa,
0xb6,
0x69,
},
{
0x58,
0x63,
0xfc,
0x23,
},
{
0x8b,
0xcf,
0x63,
0xc5,
},
{
0xd0,
0xb8,
0x84,
0x8f,
},
{
0xf8,
0x06,
0xe7,
0x79,
},
{
0x94,
0xb0,
0x79,
0x34,
},
{
0x08,
0x08,
0x30,
0x50,
},
{
0x57,
0xf0,
0x87,
0x2f,
},
{
0x77,
0xe6,
0x63,
0xff,
},
{
0xd6,
0xff,
0xf8,
0x7c,
},
{
0x74,
0xfe,
0x2b,
0x97,
},
{
0xd9,
0xb5,
0xac,
0x84,
},
{
0xc4,
0x74,
0x64,
0x5b,
},
{
0x46,
0x5b,
0x8d,
0x9b,
},
{
0x7b,
0xef,
0xe3,
0x87,
},
{
0xe3,
0x4d,
0x10,
0x45,
},
{
0x61,
0x3f,
0x62,
0xb3,
},
{
0x70,
0xf3,
0x67,
0xfe,
},
{
0xe6,
0xad,
0xb8,
0xbd,
},
{
0x27,
0x40,
0x0c,
0x63,
},
{
0x26,
0x78,
0x78,
0x75,
},
{
0x4f,
0x56,
0x7b,
0x5f,
},
{
0x3a,
0xb0,
0xe6,
0x69,
},
{
0xb0,
0x64,
0x40,
0x00,
},
{
0xff,
0x67,
0x0f,
0xb4,
},
{
0x50,
0x9e,
0x33,
0x8b,
},
{
0x5d,
0x58,
0x9f,
0x1a,
},
{
0xfe,
0xe7,
0x21,
0x12,
},
{
0x33,
0x75,
0x32,
0x59,
},
{
0x6a,
0x43,
0x4f,
0x8c,
},
{
0xfe,
0x28,
0xb7,
0x29,
},
{
0xe7,
0x5c,
0xc6,
0xec,
},
{
0x69,
0x7e,
0x8d,
0x54,
},
{
0x63,
0x68,
0x8b,
0x0f,
},
{
0x65,
0x0b,
0x62,
0xb4,
},
{
0xb6,
0xbc,
0x18,
0x40,
},
{
0x5d,
0x07,
0x45,
0x05,
},
{
0x24,
0x42,
0xfd,
0x2e,
},
{
0x7b,
0xb7,
0x86,
0x3a,
},
{
0x77,
0x05,
0xd5,
0x48,
},
{
0xd7,
0x52,
0x08,
0xb1,
},
{
0xb6,
0xd4,
0x99,
0xc8,
},
{
0x08,
0x92,
0x20,
0x2e,
},
{
0x69,
0xe1,
0x2c,
0xe3,
},
{
0x8d,
0xb5,
0x80,
0xe5,
},
{
0x36,
0x97,
0x64,
0xc6,
},
{
0x01,
0x6e,
0x02,
0x04,
},
{
0x3b,
0x85,
0xf3,
0xd4,
},
{
0xfe,
0xdb,
0x66,
0xbe,
},
{
0x1e,
0x69,
0x2a,
0x3a,
},
{
0xc6,
0x89,
0x84,
0xc0,
},
{
0xa5,
0xc5,
0xb9,
0x40,
},
{
0x9b,
0xe9,
0xe8,
0x8c,
},
{
0x7d,
0xbc,
0x81,
0x40,
},
{
0x7c,
0x07,
0x8e,
0xc5,
},
{
0xd4,
0xe7,
0x6c,
0x73,
},
{
0x42,
0x8f,
0xcb,
0xb9,
},
{
0xbd,
0x83,
0x99,
0x7a,
},
{
0x59,
0xea,
0x4a,
0x74,
},
};
const uint8_t vectors_hsip64[64][8] = {
{
0x21,
0x8d,
0x1f,
0x59,
0xb9,
0xb8,
0x3c,
0xc8,
},
{
0xbe,
0x55,
0x24,
0x12,
0xf8,
0x38,
0x73,
0x15,
},
{
0x06,
0x4f,
0x39,
0xef,
0x7c,
0x50,
0xeb,
0x57,
},
{
0xce,
0x0f,
0x1a,
0x45,
0xf7,
0x06,
0x06,
0x79,
},
{
0xd5,
0xe7,
0x8a,
0x17,
0x5b,
0xe5,
0x2e,
0xa1,
},
{
0xcb,
0x9d,
0x7c,
0x3f,
0x2f,
0x3d,
0xb5,
0x80,
},
{
0xce,
0x3e,
0x91,
0x35,
0x8a,
0xa2,
0xbc,
0x25,
},
{
0xff,
0x20,
0x27,
0x28,
0xb0,
0x7b,
0xc6,
0x84,
},
{
0xed,
0xfe,
0xe8,
0x20,
0xbc,
0xe4,
0x85,
0x8c,
},
{
0x5b,
0x51,
0xcc,
0xcc,
0x13,
0x88,
0x83,
0x07,
},
{
0x95,
0xb0,
0x46,
0x9f,
0x06,
0xa6,
0xf2,
0xee,
},
{
0xae,
0x26,
0x33,
0x39,
0x94,
0xdd,
0xcd,
0x48,
},
{
0x7b,
0xc7,
0x1f,
0x9f,
0xae,
0xf5,
0xc7,
0x99,
},
{
0x5a,
0x23,
0x52,
0xd7,
0x5a,
0x0c,
0x37,
0x44,
},
{
0x3b,
0xb1,
0xa8,
0x70,
0xea,
0xe8,
0xe6,
0x58,
},
{
0x21,
0x7d,
0x0b,
0xcb,
0x4e,
0x81,
0xc9,
0x02,
},
{
0x73,
0x36,
0xaa,
0xd2,
0x5f,
0x7b,
0xf3,
0xb5,
},
{
0x37,
0xad,
0xc0,
0x64,
0x1c,
0x4c,
0x4f,
0x6a,
},
{
0xc9,
0xb2,
0xdb,
0x2b,
0x9a,
0x3e,
0x42,
0xf9,
},
{
0xf9,
0x10,
0xe4,
0x80,
0x20,
0xab,
0x36,
0x3c,
},
{
0x1b,
0xf5,
0x2b,
0x0a,
0x6f,
0xee,
0xa7,
0xdb,
},
{
0x00,
0x74,
0x1d,
0xc2,
0x69,
0xe8,
0xb3,
0xef,
},
{
0xe2,
0x01,
0x03,
0xfa,
0x1b,
0xa7,
0x76,
0xef,
},
{
0x4c,
0x22,
0x10,
0xe5,
0x4b,
0x68,
0x1d,
0x73,
},
{
0x70,
0x74,
0x10,
0x45,
0xae,
0x3f,
0xa6,
0xf1,
},
{
0x0c,
0x86,
0x40,
0x37,
0x39,
0x71,
0x40,
0x38,
},
{
0x0d,
0x89,
0x9e,
0xd8,
0x11,
0x29,
0x23,
0xf0,
},
{
0x22,
0x6b,
0xf5,
0xfa,
0xb8,
0x1e,
0xe1,
0xb8,
},
{
0x2d,
0x92,
0x5f,
0xfb,
0x1e,
0x00,
0x16,
0xb5,
},
{
0x36,
0x19,
0x58,
0xd5,
0x2c,
0xee,
0x10,
0xf1,
},
{
0x29,
0x1a,
0xaf,
0x86,
0x48,
0x98,
0x17,
0x9d,
},
{
0x86,
0x3c,
0x7f,
0x15,
0x5c,
0x34,
0x11,
0x7c,
},
{
0x28,
0x70,
0x9d,
0x46,
0xd8,
0x11,
0x62,
0x6c,
},
{
0x24,
0x84,
0x77,
0x68,
0x1d,
0x28,
0xf8,
0x9c,
},
{
0x83,
0x24,
0xe4,
0xd7,
0x52,
0x8f,
0x98,
0x30,
},
{
0xf9,
0xef,
0xd4,
0xe1,
0x3a,
0xea,
0x6b,
0xd8,
},
{
0x86,
0xd6,
0x7a,
0x40,
0xec,
0x42,
0x76,
0xdc,
},
{
0x3f,
0x62,
0x92,
0xec,
0xcc,
0xa9,
0x7e,
0x35,
},
{
0xcb,
0xd9,
0x2e,
0xe7,
0x24,
0xd4,
0x21,
0x09,
},
{
0x36,
0x8d,
0xf6,
0x80,
0x8d,
0x40,
0x3d,
0x79,
},
{
0x5b,
0x38,
0xc8,
0x1c,
0x67,
0xc8,
0xae,
0x4c,
},
{
0x95,
0xab,
0x71,
0x89,
0xd4,
0x39,
0xac,
0xb3,
},
{
0xa9,
0x1a,
0x52,
0xc0,
0x25,
0x32,
0x70,
0x24,
},
{
0x5b,
0x00,
0x87,
0xc6,
0x95,
0x28,
0xac,
0xea,
},
{
0x1e,
0x30,
0xf3,
0xad,
0x27,
0xdc,
0xb1,
0x5a,
},
{
0x69,
0x7f,
0x5c,
0x9a,
0x90,
0x32,
0x4e,
0xd4,
},
{
0x49,
0x5c,
0x0f,
0x99,
0x55,
0x57,
0xdc,
0x38,
},
{
0x94,
0x27,
0x20,
0x2a,
0x3c,
0x29,
0xf9,
0x4d,
},
{
0xa9,
0xea,
0xa8,
0xc0,
0x4b,
0xa9,
0x3e,
0x3e,
},
{
0xee,
0xa4,
0xc1,
0x73,
0x7d,
0x01,
0x12,
0x18,
},
{
0x91,
0x2d,
0x56,
0x8f,
0xd8,
0xf6,
0x5a,
0x49,
},
{
0x56,
0x91,
0x95,
0x96,
0xb0,
0xff,
0x5c,
0x97,
},
{
0x02,
0x44,
0x5a,
0x79,
0x98,
0xf5,
0x50,
0xe1,
},
{
0x86,
0xec,
0x46,
0x6c,
0xe7,
0x1d,
0x1f,
0xb2,
},
{
0x35,
0x95,
0x69,
0xe7,
0xd2,
0x89,
0xe3,
0xbc,
},
{
0x87,
0x1b,
0x05,
0xca,
0x62,
0xbb,
0x7c,
0x96,
},
{
0xa1,
0xa4,
0x92,
0xf9,
0x42,
0xf1,
0x5f,
0x1d,
},
{
0x12,
0xec,
0x26,
0x7f,
0xf6,
0x09,
0x5b,
0x6e,
},
{
0x5d,
0x1b,
0x5e,
0xa1,
0xb2,
0x31,
0xd8,
0x9d,
},
{
0xd8,
0xcf,
0xb4,
0x45,
0x3f,
0x92,
0xee,
0x54,
},
{
0xd6,
0x76,
0x28,
0x90,
0xbf,
0x26,
0xe4,
0x60,
},
{
0x31,
0x35,
0x63,
0xa4,
0xb7,
0xed,
0x5c,
0xf3,
},
{
0xf9,
0x0b,
0x3a,
0xb5,
0x72,
0xd4,
0x66,
0x93,
},
{
0x2e,
0xa6,
0x3c,
0x71,
0xbf,
0x32,
0x60,
0x87,
},
};

103
3rd/pcre2/LICENCE.md Normal file
View File

@@ -0,0 +1,103 @@
PCRE2 License
=============
| SPDX-License-Identifier: | BSD-3-Clause WITH PCRE2-exception |
|---------|-------|
PCRE2 is a library of functions to support regular expressions whose syntax
and semantics are as close as possible to those of the Perl 5 language.
Releases 10.00 and above of PCRE2 are distributed under the terms of the "BSD"
licence, as specified below, with one exemption for certain binary
redistributions. The documentation for PCRE2, supplied in the "doc" directory,
is distributed under the same terms as the software itself. The data in the
testdata directory is not copyrighted and is in the public domain.
The basic library functions are written in C and are freestanding. Also
included in the distribution is a just-in-time compiler that can be used to
optimize pattern matching. This is an optional feature that can be omitted when
the library is built.
COPYRIGHT
---------
### The basic library functions
Written by: Philip Hazel
Email local part: Philip.Hazel
Email domain: gmail.com
Retired from University of Cambridge Computing Service,
Cambridge, England.
Copyright (c) 1997-2007 University of Cambridge
Copyright (c) 2007-2024 Philip Hazel
All rights reserved.
### PCRE2 Just-In-Time compilation support
Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
Copyright (c) 2010-2024 Zoltan Herczeg
All rights reserved.
### Stack-less Just-In-Time compiler
Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
Copyright (c) 2009-2024 Zoltan Herczeg
All rights reserved.
### All other contributions
Many other contributors have participated in the authorship of PCRE2. As PCRE2
has never required a Contributor Licensing Agreement, or other copyright
assignment agreement, all contributions have copyright retained by each
original contributor or their employer.
THE "BSD" LICENCE
-----------------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notices,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notices, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the University of Cambridge nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
EXEMPTION FOR BINARY LIBRARY-LIKE PACKAGES
------------------------------------------
The second condition in the BSD licence (covering binary redistributions) does
not apply all the way down a chain of software. If binary package A includes
PCRE2, it must respect the condition, but if package B is software that
includes package A, the condition is not imposed on package B unless it uses
PCRE2 independently.
End

View File

@@ -5,7 +5,7 @@ if (POLICY CMP0177)
endif() endif()
project(PIP) project(PIP)
set(PIP_MAJOR 5) set(PIP_MAJOR 5)
set(PIP_MINOR 2) set(PIP_MINOR 6)
set(PIP_REVISION 0) set(PIP_REVISION 0)
set(PIP_SUFFIX ) set(PIP_SUFFIX )
set(PIP_COMPANY SHS) set(PIP_COMPANY SHS)
@@ -69,9 +69,14 @@ option(STD_IOSTREAM "Building with std iostream operators support" OFF)
option(INTROSPECTION "Build with introspection" OFF) option(INTROSPECTION "Build with introspection" OFF)
option(TESTS "Build tests and perform their before install step" OFF) option(TESTS "Build tests and perform their before install step" OFF)
option(COVERAGE "Build project with coverage info" OFF) option(COVERAGE "Build project with coverage info" OFF)
option(PIP_FFTW_F "Support fftw module for float" ON)
option(PIP_FFTW_L "Support fftw module for long double" ON)
option(PIP_FFTW_Q "Support fftw module for quad double" OFF)
set(PIP_UTILS 1) set(PIP_UTILS 1)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
shstk_is_parent_exists(_pe) shstk_is_parent_exists(_pe)
if (_pe) if (_pe)
@@ -113,8 +118,10 @@ macro(pip_module NAME LIBS LABEL INCLUDES SOURCES MSG)
list(REMOVE_ITEM HS ${PHS}) list(REMOVE_ITEM HS ${PHS})
endif() endif()
if (NOT "x${SOURCES}" STREQUAL "x") if (NOT "x${SOURCES}" STREQUAL "x")
file(GLOB_RECURSE ASRC "${SOURCES}/*.cpp" "${SOURCES}/*.c") foreach (_s ${SOURCES})
file(GLOB_RECURSE ASRC "${_s}/*.cpp" "${_s}/*.c")
list(APPEND CPPS ${ASRC}) list(APPEND CPPS ${ASRC})
endforeach()
endif() endif()
list(APPEND HDRS ${HS}) list(APPEND HDRS ${HS})
list(APPEND PHDRS ${PHS}) list(APPEND PHDRS ${PHS})
@@ -328,7 +335,7 @@ if(NOT PIP_FREERTOS)
if(WIN32) if(WIN32)
if(${C_COMPILER} STREQUAL "cl.exe") if(${C_COMPILER} STREQUAL "cl.exe")
else() else()
list(APPEND LIBS_MAIN ws2_32 iphlpapi psapi cfgmgr32 setupapi) list(APPEND LIBS_MAIN ws2_32 iphlpapi psapi cfgmgr32 setupapi hid)
endif() endif()
else() else()
list(APPEND LIBS_MAIN dl) list(APPEND LIBS_MAIN dl)
@@ -377,7 +384,7 @@ endif()
add_subdirectory("3rd/pcre2" EXCLUDE_FROM_ALL) add_subdirectory("3rd/pcre2" EXCLUDE_FROM_ALL)
list(APPEND LIBS_MAIN pcre2-16-static) list(APPEND LIBS_MAIN pcre2-16-static)
pip_module(main "${LIBS_MAIN}" "PIP main library" "" "${PIP_3PL_DIR}/BLAKE2" "") pip_module(main "${LIBS_MAIN}" "PIP main library" "" "${PIP_3PL_DIR}/BLAKE2;${PIP_3PL_DIR}/SipHash" "")
generate_export_header(pip) generate_export_header(pip)
list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/pip_export.h") list(APPEND HDRS "${CMAKE_CURRENT_BINARY_DIR}/pip_export.h")
@@ -436,8 +443,23 @@ if (NOT CROSSTOOLS)
if (PIP_BUILD_FFTW) if (PIP_BUILD_FFTW)
# Check if PIP support fftw3 for PIFFT using in math module # Check if PIP support fftw3 for PIFFT using in math module
set(FFTW_LIB_NAME fftw3) set(FFTW_LIB_NAME fftw3)
set(FFTW_LIB_SUFFIXES "" "f" "l" "q") set(FFTW_LIB_SUFFIXES "")
if (PIP_FFTW_F)
list(APPEND FFTW_LIB_SUFFIXES "f")
endif()
if (PIP_FFTW_L)
list(APPEND FFTW_LIB_SUFFIXES "l")
endif()
if (PIP_FFTW_Q)
list(APPEND FFTW_LIB_SUFFIXES "q")
endif()
if (NOT "${FFTW_LIB_SUFFIXES}" STREQUAL "")
set(FFTW_LIB_SUFFIXES ";${FFTW_LIB_SUFFIXES}")
else()
list(APPEND FFTW_LIB_SUFFIXES "" "_")
endif()
set(FFTW_LIB_SUFFIXES2 "" "-3") set(FFTW_LIB_SUFFIXES2 "" "-3")
set(FFTW_MSG "")
set(FFTW_LIBS) set(FFTW_LIBS)
set(FFTW_ABS_LIBS) set(FFTW_ABS_LIBS)
set(CMAKE_REQUIRED_INCLUDES fftw3.h) set(CMAKE_REQUIRED_INCLUDES fftw3.h)
@@ -452,6 +474,10 @@ if (NOT CROSSTOOLS)
set(${FFTW_CLN}_FOUND FALSE) set(${FFTW_CLN}_FOUND FALSE)
set(${FFTW_CLNT}_FOUND FALSE) set(${FFTW_CLNT}_FOUND FALSE)
if(${FFTW_CLN}_LIBRARIES) if(${FFTW_CLN}_LIBRARIES)
if (NOT "${FFTW_MSG}" STREQUAL "")
set(FFTW_MSG "${FFTW_MSG}, ")
endif()
set(FFTW_MSG "${FFTW_MSG}${FFTW_CLN}")
set(${FFTW_CLN}_FOUND TRUE) set(${FFTW_CLN}_FOUND TRUE)
list(APPEND FFTW_LIBS "${FFTW_CLN}") list(APPEND FFTW_LIBS "${FFTW_CLN}")
list(APPEND FFTW_ABS_LIBS "${${FFTW_CLN}_LIBRARIES}") list(APPEND FFTW_ABS_LIBS "${${FFTW_CLN}_LIBRARIES}")
@@ -475,7 +501,7 @@ if (NOT CROSSTOOLS)
endforeach() endforeach()
endforeach() endforeach()
if(FFTW_LIBS) if(FFTW_LIBS)
pip_module(fftw "${FFTW_LIBS}" "PIP FFTW support" "" "" "") pip_module(fftw "${FFTW_LIBS}" "PIP FFTW support" "" "" " (${FFTW_MSG})")
endif() endif()
endif() endif()

115
README.md
View File

@@ -40,3 +40,118 @@ You should add ${<out_var>} to your target.
[🇷🇺 Онлайн документация](https://shstk.ru/pip/html/ru/index.html) [🇷🇺 Онлайн документация](https://shstk.ru/pip/html/ru/index.html)
[🇷🇺 Qt-help](https://shstk.ru/pip/pip_ru.qch) [🇷🇺 Qt-help](https://shstk.ru/pip/pip_ru.qch)
## Основные опции сборки
### Стандартные опции (option())
| Опция | Описание | По умолчанию |
|-------|----------|--------------|
| `ICU` | ICU support для конвертации кодовых страниц | ON (кроме Win/Android/Apple) |
| `STD_IOSTREAM` | Поддержка std::iostream операторов | OFF |
| `INTROSPECTION` | Сборка с интроспекцией | OFF |
| `TESTS` | Сборка тестов | OFF |
| `COVERAGE` | Сборка с информацией о покрытии | OFF |
| `PIP_FFTW_F` | Поддержка FFTW для float | ON |
| `PIP_FFTW_L` | Поддержка FFTW для long double | ON |
| `PIP_FFTW_Q` | Поддержка FFTW для quad double | OFF |
### Опции модулей (PIP_BUILD_*)
| Опция | Модуль |
|-------|--------|
| `PIP_BUILD_CONSOLE` | console |
| `PIP_BUILD_CRYPT` | crypt (требует libsodium) |
| `PIP_BUILD_COMPRESS` | compress (требует zlib) |
| `PIP_BUILD_USB` | usb |
| `PIP_BUILD_FFTW` | fftw |
| `PIP_BUILD_OPENCL` | opencl |
| `PIP_BUILD_IO_UTILS` | io_utils |
| `PIP_BUILD_CLIENT_SERVER` | client_server |
| `PIP_BUILD_CLOUD` | cloud |
| `PIP_BUILD_LUA` | lua |
| `PIP_BUILD_HTTP_CLIENT` | http_client (требует libcurl) |
| `PIP_BUILD_HTTP_SERVER` | http_server (требует libmicrohttpd) |
### Дополнительные переменные
| Переменная | Описание |
|------------|----------|
| `PIP_BUILD_DEBUG` | Сборка debug версии |
| `PIP_FREERTOS` | Режим сборки для FreeRTOS |
| `CROSSTOOLS` | Собрать инструменты кросс-сборки под хостовую систему (pip_cmg, pip_rc, ...) |
| `LOCAL` | Локальная установка (bin/lib/include) |
| `PIP_CONTAINERS_MIN_ALLOC` | Переопределить минимальный размер аллокации контейнеров |
| `PIP_CONTAINERS_MAX_POT_ALLOC` | Переопределить максимальный размер дополнительной аллокации (поддерживает X_KiB, X_MiB) |
### Примеры использования
```bash
# Базовая сборка с тестами
cmake -B build -DTESTS=ON
# Сборка с покрытием и ICU
cmake -B build -DTESTS=ON -DCOVERAGE=ON -DICU=ON
# Отключение отдельных модулей
cmake -B build -DPIP_BUILD_CRYPT=OFF -DPIP_BUILD_OPENCL=OFF
# Переопределение параметров контейнеров
cmake -B build -DPIP_CONTAINERS_MIN_ALLOC=64
# Локальная установка
cmake -B build -DLOCAL=ON
```
## PIP Dependencies
### Встроенные (included in 3rd/)
| Библиотека | Назначение | Модуль PIP |
|------------|------------|------------|
| **PCRE2** | Регулярные выражения | main (internal) |
| **BLAKE2** | Хеширование | main (internal) |
| **SipHash** | Хеширование | main (internal) |
| **Lua** | Lua scripting | lua |
| **LuaBridge** | Lua bindings | lua |
### Внешние (системные)
| Библиотека | Опция | Модуль PIP |
|------------|-------|------------|
| **ICU** | `-DICU=ON` | main (string conversion) |
| **zlib** | `PIP_BUILD_COMPRESS` | compress |
| **libsodium** | `PIP_BUILD_CRYPT` | crypt, io_utils, cloud |
| **libusb** | `PIP_BUILD_USB` | usb |
| **FFTW3** (+ threads) | `PIP_BUILD_FFTW` | fftw |
| **OpenCL** | `PIP_BUILD_OPENCL` | opencl |
| **libmicrohttpd** | `PIP_BUILD_HTTP_SERVER` | http_server |
| **libcurl** | `PIP_BUILD_HTTP_CLIENT` | http_client |
### Опциональные (тесты/документация)
| Инструмент | Назначение |
|------------|------------|
| **Google Test** | Тестирование (fetched automatically) |
| **Doxygen** | Генерация документации |
### Схема зависимостей модулей
```
main (core)
├── PCRE2 (встроен)
├── BLAKE2 (встроен)
├── SipHash (встроен)
└── ICU (опционально)
console → main
compress → zlib
crypt → libsodium
usb → libusb
fftw → FFTW3
opencl → OpenCL
io_utils → [crypt, если доступен]
client_server → io_utils
cloud → io_utils, crypt
lua → Lua (встроен), LuaBridge (встроен)
http_server → libmicrohttpd
http_client → libcurl
```

Binary file not shown.

View File

@@ -20,7 +20,7 @@
<context> <context>
<name>PIFile</name> <name>PIFile</name>
<message> <message>
<location filename="../libs/main/io_devices/pifile.cpp" line="300"/> <location filename="../libs/main/io_devices/pifile.cpp" line="296"/>
<source>Downsize is not supported yet :-(</source> <source>Downsize is not supported yet :-(</source>
<translation>Уменьшение размера не поддерживается</translation> <translation>Уменьшение размера не поддерживается</translation>
</message> </message>
@@ -66,6 +66,239 @@
<translation type="vanished">Предупреждение: PICrypt неактивен, для активации установите библиотеку sodium и пересоберите PIP</translation> <translation type="vanished">Предупреждение: PICrypt неактивен, для активации установите библиотеку sodium и пересоберите PIP</translation>
</message> </message>
</context> </context>
<context>
<name>PIUnits</name>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="88"/>
<source>E</source>
<translation>Э</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="85"/>
<source>G</source>
<translation>Г</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="84"/>
<source>M</source>
<translation>М</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="87"/>
<source>P</source>
<translation>П</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="92"/>
<source>Q</source>
<translation>Кв</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="91"/>
<source>R</source>
<translation>Рн</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="86"/>
<source>T</source>
<translation>Т</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="90"/>
<source>Y</source>
<translation>И</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="89"/>
<source>Z</source>
<translation>З</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="101"/>
<source>a</source>
<translation>а</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="95"/>
<source>c</source>
<translation>с</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="94"/>
<source>d</source>
<translation>д</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="100"/>
<source>f</source>
<translation>ф</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="82"/>
<source>h</source>
<translation>г</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="83"/>
<source>k</source>
<translation>к</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="96"/>
<source>m</source>
<translation>м</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="98"/>
<source>n</source>
<translation>н</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="99"/>
<source>p</source>
<translation>п</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="104"/>
<source>r</source>
<translation>рн</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="97"/>
<source>u</source>
<translation>мк</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="103"/>
<source>y</source>
<translation>и</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="102"/>
<source>z</source>
<translation>з</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="81"/>
<source>da</source>
<translation>да</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="88"/>
<source>exa</source>
<translation>экса</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="101"/>
<source>atto</source>
<translation>атто</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="81"/>
<source>deca</source>
<translation>дека</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="94"/>
<source>deci</source>
<translation>деци</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="85"/>
<source>giga</source>
<translation>гига</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="83"/>
<source>kilo</source>
<translation>кило</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="84"/>
<source>mega</source>
<translation>мега</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="98"/>
<source>nano</source>
<translation>нано</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="87"/>
<source>peta</source>
<translation>пета</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="99"/>
<source>pico</source>
<translation>пико</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="86"/>
<source>tera</source>
<translation>тера</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="95"/>
<source>centi</source>
<translation>санти</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="100"/>
<source>femto</source>
<translation>фемто</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="82"/>
<source>hecto</source>
<translation>гекто</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="97"/>
<source>micro</source>
<translation>микро</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="96"/>
<source>milli</source>
<translation>милли</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="91"/>
<source>ronna</source>
<translation>ронна</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="104"/>
<source>ronto</source>
<translation>ронто</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="103"/>
<source>yocto</source>
<translation>иокто</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="90"/>
<source>yotta</source>
<translation>иотта</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="102"/>
<source>zepto</source>
<translation>зепто</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="89"/>
<source>zetta</source>
<translation>зетта</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_prefix.cpp" line="92"/>
<source>quetta</source>
<translation>кветта</translation>
</message>
</context>
<context> <context>
<name>PIBinLog</name> <name>PIBinLog</name>
<message> <message>
@@ -253,47 +486,47 @@
<context> <context>
<name>PIString</name> <name>PIString</name>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1787"/> <location filename="../libs/main/text/pistring.cpp" line="1807"/>
<source>B</source> <source>B</source>
<translation>Б</translation> <translation>Б</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1807"/> <location filename="../libs/main/text/pistring.cpp" line="1827"/>
<source>EiB</source> <source>EiB</source>
<translation>ЭиБ</translation> <translation>ЭиБ</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1804"/> <location filename="../libs/main/text/pistring.cpp" line="1824"/>
<source>GiB</source> <source>GiB</source>
<translation>ГиБ</translation> <translation>ГиБ</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1802"/> <location filename="../libs/main/text/pistring.cpp" line="1822"/>
<source>KiB</source> <source>KiB</source>
<translation>КиБ</translation> <translation>КиБ</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1803"/> <location filename="../libs/main/text/pistring.cpp" line="1823"/>
<source>MiB</source> <source>MiB</source>
<translation>МиБ</translation> <translation>МиБ</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1806"/> <location filename="../libs/main/text/pistring.cpp" line="1826"/>
<source>PiB</source> <source>PiB</source>
<translation>ПиБ</translation> <translation>ПиБ</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1805"/> <location filename="../libs/main/text/pistring.cpp" line="1825"/>
<source>TiB</source> <source>TiB</source>
<translation>ТиБ</translation> <translation>ТиБ</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1809"/> <location filename="../libs/main/text/pistring.cpp" line="1829"/>
<source>YiB</source> <source>YiB</source>
<translation>ЙиБ</translation> <translation>ЙиБ</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/text/pistring.cpp" line="1808"/> <location filename="../libs/main/text/pistring.cpp" line="1828"/>
<source>ZiB</source> <source>ZiB</source>
<translation>ЗиБ</translation> <translation>ЗиБ</translation>
</message> </message>
@@ -319,7 +552,7 @@
<context> <context>
<name>PIProcess</name> <name>PIProcess</name>
<message> <message>
<location filename="../libs/main/system/piprocess.cpp" line="200"/> <location filename="../libs/main/system/piprocess.cpp" line="316"/>
<source>&quot;CreateProcess&quot; error: %1</source> <source>&quot;CreateProcess&quot; error: %1</source>
<translation>Ошибка &quot;CreateProcess&quot;: %1</translation> <translation>Ошибка &quot;CreateProcess&quot;: %1</translation>
</message> </message>
@@ -327,12 +560,12 @@
<context> <context>
<name>PIVariant</name> <name>PIVariant</name>
<message> <message>
<location filename="../libs/main/types/pivariant.cpp" line="415"/> <location filename="../libs/main/types/pivariant.cpp" line="418"/>
<source>Can`t initialize PIVariant from unregistered type &quot;%1&quot;!</source> <source>Can`t initialize PIVariant from unregistered type &quot;%1&quot;!</source>
<translation>Невозможно инициализировать PIVariant из незарегистрированного типа &quot;%1&quot;!</translation> <translation>Невозможно инициализировать PIVariant из незарегистрированного типа &quot;%1&quot;!</translation>
</message> </message>
<message> <message>
<location filename="../libs/main/types/pivariant.cpp" line="393"/> <location filename="../libs/main/types/pivariant.cpp" line="396"/>
<source>Can`t initialize PIVariant from unregistered typeID &quot;%1&quot;!</source> <source>Can`t initialize PIVariant from unregistered typeID &quot;%1&quot;!</source>
<translation>Невозможно инициализировать PIVariant из незарегистрированного ID типа &quot;%1&quot;!</translation> <translation>Невозможно инициализировать PIVariant из незарегистрированного ID типа &quot;%1&quot;!</translation>
</message> </message>
@@ -358,7 +591,7 @@
<context> <context>
<name>PIEthernet</name> <name>PIEthernet</name>
<message> <message>
<location filename="../libs/main/io_devices/piethernet.cpp" line="1272"/> <location filename="../libs/main/io_devices/piethernet.cpp" line="1275"/>
<source>Can`t get interfaces: %1</source> <source>Can`t get interfaces: %1</source>
<translation>Невозможно получить интерфейсы: %1</translation> <translation>Невозможно получить интерфейсы: %1</translation>
</message> </message>
@@ -389,6 +622,67 @@
<translation>Ошибка: Режим ReadWrite не поддерживается, используйте WriteOnly или ReadOnly</translation> <translation>Ошибка: Режим ReadWrite не поддерживается, используйте WriteOnly или ReadOnly</translation>
</message> </message>
</context> </context>
<context>
<name>PIUnitsMass</name>
<message>
<location filename="../libs/main/units/piunits_class_mass.cpp" line="35"/>
<source>g</source>
<translation>г</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_mass.cpp" line="37"/>
<source>℥</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_mass.cpp" line="36"/>
<source>lb</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_mass.cpp" line="25"/>
<source>gram</source>
<translation>грамм</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_mass.cpp" line="27"/>
<source>ounce</source>
<translation>унция</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_mass.cpp" line="26"/>
<source>pound</source>
<translation>фунт</translation>
</message>
</context>
<context>
<name>PIUnitsTime</name>
<message>
<location filename="../libs/main/units/piunits_class_time.cpp" line="34"/>
<source>s</source>
<translation>с</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_time.cpp" line="35"/>
<source>Hz</source>
<translation>Гц</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_time.cpp" line="26"/>
<source>hertz</source>
<translation>герц</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_time.cpp" line="25"/>
<source>second</source>
<translation>секунд</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_time.cpp" line="25"/>
<source>secons</source>
<translation type="vanished">секунд</translation>
</message>
</context>
<context> <context>
<name>PIConnection</name> <name>PIConnection</name>
<message> <message>
@@ -455,6 +749,29 @@
<translation>toSystemTime() Предупреждение: неверная частота: %1</translation> <translation>toSystemTime() Предупреждение: неверная частота: %1</translation>
</message> </message>
</context> </context>
<context>
<name>PIUnitsAngle</name>
<message>
<location filename="../libs/main/units/piunits_class_angle.cpp" line="36"/>
<source>°</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_angle.cpp" line="37"/>
<source>rad</source>
<translation>рад</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_angle.cpp" line="27"/>
<source>degree</source>
<translation>градусы</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_angle.cpp" line="28"/>
<source>radian</source>
<translation>радиан</translation>
</message>
</context>
<context> <context>
<name>PIEthUtilBase</name> <name>PIEthUtilBase</name>
<message> <message>
@@ -528,4 +845,171 @@
<translation>Невозможно открыть процесс с ID = %1, %2!</translation> <translation>Невозможно открыть процесс с ID = %1, %2!</translation>
</message> </message>
</context> </context>
<context>
<name>PIUnitsDistance</name>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="40"/>
<source>&quot;</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="44"/>
<source>Å</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="39"/>
<source>m</source>
<translation>м</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="45"/>
<source>au</source>
<translation>а. е.</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="42"/>
<source>ft</source>
<translation>фут</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="43"/>
<source>yd</source>
<translation>ярд</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="27"/>
<source>mil</source>
<translation>мил</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="28"/>
<source>foot</source>
<translation>фут</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="26"/>
<source>inch</source>
<translation>дюйм</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="41"/>
<source>thou</source>
<translation>мил</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="29"/>
<source>yard</source>
<translation>ярд</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="25"/>
<source>meter</source>
<translation>метр</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="30"/>
<source>angstrom</source>
<translation>ангстрем</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_distance.cpp" line="31"/>
<source>astronomical unit</source>
<translation>астрономическая единица</translation>
</message>
</context>
<context>
<name>PIUnitsPressure</name>
<message>
<location filename="../libs/main/units/piunits_class_pressure.cpp" line="36"/>
<source>Pa</source>
<translation>Па</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_pressure.cpp" line="37"/>
<source>atm</source>
<translation>атм</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_pressure.cpp" line="38"/>
<source>bar</source>
<translation>бар</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_pressure.cpp" line="39"/>
<source>mmHg</source>
<translation>мм рт. ст.</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_pressure.cpp" line="28"/>
<source>mm Hg</source>
<translation>мм рт. ст.</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_pressure.cpp" line="25"/>
<source>pascal</source>
<translation>паскаль</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_pressure.cpp" line="26"/>
<source>atmosphere</source>
<translation>атмосфер</translation>
</message>
</context>
<context>
<name>PIUnitsInformation</name>
<message>
<location filename="../libs/main/units/piunits_class_information.cpp" line="35"/>
<source>B</source>
<translation>Б</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_information.cpp" line="34"/>
<source>b</source>
<translation>б</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_information.cpp" line="25"/>
<source>bit</source>
<translation>бит</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_information.cpp" line="26"/>
<source>byte</source>
<translation>байт</translation>
</message>
</context>
<context>
<name>PIUnitsTemperature</name>
<message>
<location filename="../libs/main/units/piunits_class_temperature.cpp" line="35"/>
<source>K</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_temperature.cpp" line="36"/>
<source>°C</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_temperature.cpp" line="37"/>
<source>°F</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_temperature.cpp" line="25"/>
<source>Kelvin</source>
<translation>Кельвин</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_temperature.cpp" line="26"/>
<source>Celsius</source>
<translation>Цельсий</translation>
</message>
<message>
<location filename="../libs/main/units/piunits_class_temperature.cpp" line="27"/>
<source>Fahrenheit</source>
<translation>Фаренгейт</translation>
</message>
</context>
</TS> </TS>

View File

@@ -189,8 +189,8 @@ void PIScreen::SystemConsole::print() {
for (int j = 0; j < dh; ++j) { for (int j = 0; j < dh; ++j) {
int k = j * dw + i; int k = j * dw + i;
Cell & c(cells[j + dy0][i + dx0]); Cell & c(cells[j + dy0][i + dx0]);
PRIVATE->chars[k].Char.UnicodeChar = 0; PRIVATE->chars[k].Char.UnicodeChar = c.symbol.unicode16Code();
PRIVATE->chars[k].Char.AsciiChar = c.symbol.toConsole1Byte(); // PRIVATE->chars[k].Char.AsciiChar = c.symbol.toConsole1Byte();
PRIVATE->chars[k].Attributes = attributes(c); PRIVATE->chars[k].Attributes = attributes(c);
} }
// piCout << "draw" << dw << dh; // piCout << "draw" << dw << dh;
@@ -200,7 +200,7 @@ void PIScreen::SystemConsole::print() {
PRIVATE->srect.Top += dy0; PRIVATE->srect.Top += dy0;
PRIVATE->srect.Right -= width - dx1 - 1; PRIVATE->srect.Right -= width - dx1 - 1;
PRIVATE->srect.Bottom -= height - dy1 - 1; PRIVATE->srect.Bottom -= height - dy1 - 1;
WriteConsoleOutput(PRIVATE->hOut, PRIVATE->chars.data(), PRIVATE->bs, PRIVATE->bc, &PRIVATE->srect); WriteConsoleOutputW(PRIVATE->hOut, PRIVATE->chars.data(), PRIVATE->bs, PRIVATE->bc, &PRIVATE->srect);
#else #else
PIString s; PIString s;
int si = 0, sj = 0; int si = 0, sj = 0;

View File

@@ -59,7 +59,7 @@ bool PIHTTPClient::init() {
if (is_cancel) return false; if (is_cancel) return false;
CurlThreadPool::instance(); CurlThreadPool::instance();
if (!PRIVATE->init()) return false; if (!PRIVATE->init()) return false;
auto ait = request.arguments().makeIterator(); auto ait = request.queryArguments().makeIterator();
while (ait.next()) { while (ait.next()) {
if (!url.contains('?')) if (!url.contains('?'))
url.append('?'); url.append('?');

View File

@@ -363,5 +363,5 @@ void MicrohttpdServer::addFixedHeaders(MessageMutable & msg) {
msg.addHeader(Header::ContentType, "application/json; charset=utf-8"); msg.addHeader(Header::ContentType, "application/json; charset=utf-8");
} }
} }
msg.addHeader(Header::AccessControlAllowOrigin, "*"); // msg.addHeader(Header::AccessControlAllowOrigin, "*");
} }

View File

@@ -64,13 +64,25 @@ public:
//! \~english Returns unparsed command-line argument by index "index". Index 0 is program execute command. //! \~english Returns unparsed command-line argument by index "index". Index 0 is program execute command.
//! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы. //! \~russian Возвращает исходный аргумент командной строки по индексу "index". Индекс 0 это команда вызова программы.
PIString rawArgument(int index); PIString rawArgument(int index);
//! \~english Returns mandatory command-line argument by index "index".
//! \~russian Возвращает обязательный аргумент командной строки по индексу "index".
PIString mandatoryArgument(int index); PIString mandatoryArgument(int index);
//! \~english Returns optional command-line argument by index "index".
//! \~russian Возвращает опциональный аргумент командной строки по индексу "index".
PIString optionalArgument(int index); PIString optionalArgument(int index);
//! \~english Returns unparsed command-line arguments. //! \~english Returns unparsed command-line arguments.
//! \~russian Возвращает исходные аргументы командной строки. //! \~russian Возвращает исходные аргументы командной строки.
const PIStringList & rawArguments(); const PIStringList & rawArguments();
//! \~english Returns mandatory command-line arguments.
//! \~russian Возвращает обязательные аргументы командной строки.
const PIStringList & mandatoryArguments(); const PIStringList & mandatoryArguments();
//! \~english Returns optional command-line arguments.
//! \~russian Возвращает опциональные аргументы командной строки.
const PIStringList & optionalArguments(); const PIStringList & optionalArguments();
//! \~english Returns program execute command without arguments. //! \~english Returns program execute command without arguments.
@@ -93,18 +105,52 @@ public:
//! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет. //! \~russian Возвращает полный ключ аргумента "name" или пустую строку, если аргумента нет.
PIString argumentFullKey(const PIString & name); PIString argumentFullKey(const PIString & name);
//! \~english Returns short key prefix.
//! \~russian Возвращает префикс короткого ключа.
const PIString & shortKeyPrefix() const { return _prefix_short; } const PIString & shortKeyPrefix() const { return _prefix_short; }
//! \~english Returns full key prefix.
//! \~russian Возвращает префикс полного ключа.
const PIString & fullKeyPrefix() const { return _prefix_full; } const PIString & fullKeyPrefix() const { return _prefix_full; }
//! \~english Returns mandatory arguments count.
//! \~russian Возвращает количество обязательных аргументов.
int mandatoryArgumentsCount() const { return _count_mand; } int mandatoryArgumentsCount() const { return _count_mand; }
//! \~english Returns optional arguments count.
//! \~russian Возвращает количество опциональных аргументов.
int optionalArgumentsCount() const { return _count_opt; } int optionalArgumentsCount() const { return _count_opt; }
//! \~english Sets short key prefix.
//! \~russian Устанавливает префикс короткого ключа.
void setShortKeyPrefix(const PIString & prefix); void setShortKeyPrefix(const PIString & prefix);
//! \~english Sets full key prefix.
//! \~russian Устанавливает префикс полного ключа.
void setFullKeyPrefix(const PIString & prefix); void setFullKeyPrefix(const PIString & prefix);
//! \~english Sets mandatory arguments count.
//! \~russian Устанавливает количество обязательных аргументов.
void setMandatoryArgumentsCount(const int count); void setMandatoryArgumentsCount(const int count);
//! \~english Sets optional arguments count.
//! \~russian Устанавливает количество опциональных аргументов.
void setOptionalArgumentsCount(const int count); void setOptionalArgumentsCount(const int count);
//! \~english Returns debug mode state.
//! \~russian Возвращает состояние режима отладки.
bool debug() const { return debug_; } bool debug() const { return debug_; }
//! \~english Sets debug mode state.
//! \~russian Устанавливает состояние режима отладки.
void setDebug(bool debug) { debug_ = debug; } void setDebug(bool debug) { debug_ = debug; }
//! \~english Returns class name.
//! \~russian Возвращает имя класса.
PIConstChars className() const { return "PICLI"; } PIConstChars className() const { return "PICLI"; }
//! \~english Returns object name.
//! \~russian Возвращает имя объекта.
PIString name() const { return PIStringAscii("CLI"); } PIString name() const { return PIStringAscii("CLI"); }
private: private:

View File

@@ -38,7 +38,12 @@ class PIP_EXPORT PILog: public PIThread {
PIOBJECT_SUBCLASS(PILog, PIThread) PIOBJECT_SUBCLASS(PILog, PIThread)
public: public:
//! \~english Constructs empty %PILog.
//! \~russian Создает пустой %PILog.
PILog(); PILog();
//! \~english Destructor. Calls stop().
//! \~russian Деструктор. Вызывает stop().
~PILog(); ~PILog();
//! \~english Message category //! \~english Message category

View File

@@ -42,6 +42,8 @@ public:
//! \~russian Создает %PISingleApplication с именем "app_name" //! \~russian Создает %PISingleApplication с именем "app_name"
PISingleApplication(const PIString & app_name = PIString()); PISingleApplication(const PIString & app_name = PIString());
//! \~english Destructor.
//! \~russian Деструктор.
~PISingleApplication(); ~PISingleApplication();

View File

@@ -227,23 +227,25 @@ public:
//! \~russian Возвращает статистику потоков наблюдаемого процесса //! \~russian Возвращает статистику потоков наблюдаемого процесса
PIVector<ThreadStats> threadsStatistic() const; PIVector<ThreadStats> threadsStatistic() const;
//! \~english Sets process statistics.
//! \~russian Устанавливает статистику процесса.
void setStatistic(const ProcessStats & s); void setStatistic(const ProcessStats & s);
//! \~english //! \~english Returns total RAM in bytes.
//! \~russian //! \~russian Возвращает общий объем ОЗУ в байтах.
static ullong totalRAM(); static ullong totalRAM();
//! \~english //! \~english Returns free RAM in bytes.
//! \~russian //! \~russian Возвращает свободный объем ОЗУ в байтах.
static ullong freeRAM(); static ullong freeRAM();
//! \~english //! \~english Returns used RAM in bytes.
//! \~russian //! \~russian Возвращает используемый объем ОЗУ в байтах.
static ullong usedRAM(); static ullong usedRAM();
//! \~english //! \~english Event raised when new measurements are available.
//! \~russian //! \~russian Событие вызывается когда доступны новые измерения.
EVENT(measured); EVENT(measured);
private: private:

View File

@@ -38,15 +38,40 @@
//! \~russian Поддержка перевода //! \~russian Поддержка перевода
class PIP_EXPORT PITranslator { class PIP_EXPORT PITranslator {
public: public:
//! \~english Translates string "in" with optional context.
//! \~russian Переводит строку "in" с опциональным контекстом.
static PIString tr(const PIString & in, const PIString & context = {}); static PIString tr(const PIString & in, const PIString & context = {});
//! \~english Translates string "in" with optional context.
//! \~russian Переводит строку "in" с опциональным контекстом.
static PIString tr(const char * in, const PIString & context = {}) { return tr(PIString::fromUTF8(in), context); } static PIString tr(const char * in, const PIString & context = {}) { return tr(PIString::fromUTF8(in), context); }
//! \~english Returns original string without translation.
//! \~russian Возвращает оригинальную строку без перевода.
static PIString trNoOp(const PIString & in, const PIString & context = {}) { return in; } static PIString trNoOp(const PIString & in, const PIString & context = {}) { return in; }
//! \~english Returns original string without translation.
//! \~russian Возвращает оригинальную строку без перевода.
static PIString trNoOp(const char * in, const PIString & context = {}) { return trNoOp(PIString::fromUTF8(in), context); } static PIString trNoOp(const char * in, const PIString & context = {}) { return trNoOp(PIString::fromUTF8(in), context); }
//! \~english Clears all loaded translations.
//! \~russian Очищает все загруженные переводы.
static void clear(); static void clear();
//! \~english Loads translation for language "short_lang" from directory "dir".
//! \~russian Загружает перевод для языка "short_lang" из директории "dir".
static void loadLang(const PIString & short_lang, PIString dir = {}); static void loadLang(const PIString & short_lang, PIString dir = {});
//! \~english Loads translation from config "content".
//! \~russian Загружает перевод из конфигурации "content".
static void loadConfig(const PIString & content); static void loadConfig(const PIString & content);
//! \~english Loads translation from binary content.
//! \~russian Загружает перевод из бинарного содержимого.
static bool load(const PIByteArray & content); static bool load(const PIByteArray & content);
//! \~english Loads translation from file.
//! \~russian Загружает перевод из файла.
static bool loadFile(const PIString & path); static bool loadFile(const PIString & path);
private: private:
@@ -59,10 +84,20 @@ private:
}; };
//! \~english Context-aware string wrapper for translation.
//! \~russian Контекстно-зависимая обертка строки для перевода.
class PIStringContextTr { class PIStringContextTr {
public: public:
//! \~english Constructs wrapper from string.
//! \~russian Создает обертку из строки.
PIStringContextTr(PIString && s): _s(s) {} PIStringContextTr(PIString && s): _s(s) {}
//! \~english Returns translated string.
//! \~russian Возвращает переведенную строку.
operator PIString() const { return PITranslator::tr(_s); } operator PIString() const { return PITranslator::tr(_s); }
//! \~english Returns translated string with context.
//! \~russian Возвращает переведенную строку с контекстом.
PIString operator()(const PIString & ctx = {}) const { return PITranslator::tr(_s, ctx); } PIString operator()(const PIString & ctx = {}) const { return PITranslator::tr(_s, ctx); }
private: private:
@@ -70,10 +105,20 @@ private:
}; };
//! \~english Context-aware string wrapper without translation (no-op).
//! \~russian Контекстно-зависимая обертка строки без перевода (заглушка).
class PIStringContextTrNoOp { class PIStringContextTrNoOp {
public: public:
//! \~english Constructs wrapper from string.
//! \~russian Создает обертку из строки.
PIStringContextTrNoOp(PIString && s): _s(s) {} PIStringContextTrNoOp(PIString && s): _s(s) {}
//! \~english Returns original string.
//! \~russian Возвращает оригинальную строку.
operator PIString() const { return _s; } operator PIString() const { return _s; }
//! \~english Returns original string with context.
//! \~russian Возвращает оригинальную строку с контекстом.
PIString operator()(const PIString & ctx = {}) const { return _s; } PIString operator()(const PIString & ctx = {}) const { return _s; }
private: private:

View File

@@ -1,9 +1,11 @@
/*! \file piclientserver_client.h //! \file piclientserver_client.h
* \ingroup ClientServer //! \ingroup ClientServer
* \~\brief //! \brief
* \~english //! \~english Client and ServerClient classes
* \~russian //! \~russian Классы Client и ServerClient
*/ //! \details
//! \~english Provides client implementation for connecting to servers and server-side client representation.
//! \~russian Обеспечивает реализацию клиента для подключения к серверам и представление клиента на стороне сервера.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -33,13 +35,18 @@ namespace PIClientServer {
// ServerClient // ServerClient
//! ~english Server-side client implementation //! \details
//! ~russian Серверная реализация клиента //! \~english Server-side client representation. Created and managed by Server. Used to communicate with remote clients connected to the
//! server.
//! \~russian Представление клиента на стороне сервера. Создаётся и управляется сервером. Используется для коммуникации с удалёнными
//! клиентами, подключёнными к серверу.
class PIP_CLIENT_SERVER_EXPORT ServerClient: public ClientBase { class PIP_CLIENT_SERVER_EXPORT ServerClient: public ClientBase {
friend class Server; friend class Server;
NO_COPY_CLASS(ServerClient); NO_COPY_CLASS(ServerClient);
public: public:
//! \~english Creates empty ServerClient instance
//! \~russian Создает пустой экземпляр ServerClient
ServerClient() {} ServerClient() {}
protected: protected:
@@ -54,13 +61,20 @@ private:
// Client // Client
//! ~english Client implementation for connecting to servers //! \details
//! ~russian Клиентская реализация для подключения к серверам //! \~english Client implementation for connecting to servers. Provides TCP connection to remote server with diagnostics and packet
//! streaming support.
//! \~russian Реализация клиента для подключения к серверам. Обеспечивает TCP-соединение с удалённым сервером с поддержкой диагностики и
//! потоковой передачи пакетов.
class PIP_CLIENT_SERVER_EXPORT Client: public ClientBase { class PIP_CLIENT_SERVER_EXPORT Client: public ClientBase {
NO_COPY_CLASS(Client); NO_COPY_CLASS(Client);
public: public:
//! \~english Creates Client instance
//! \~russian Создает экземпляр Client
Client(); Client();
//! \~english Destroys Client instance
//! \~russian Уничтожает экземпляр Client
~Client(); ~Client();
//! ~english Connects to specified server address //! ~english Connects to specified server address

View File

@@ -1,9 +1,11 @@
/*! \file piclientserver_client_base.h //! \file piclientserver_client_base.h
* \ingroup ClientServer //! \ingroup ClientServer
* \~\brief //! \brief
* \~english //! \~english Base class for client-server communication
* \~russian //! \~russian Базовый класс для клиент-серверного взаимодействия
*/ //! \details
//! \~english Provides base functionality for client-server communication with diagnostics support.
//! \~russian Обеспечивает базовую функциональность для клиент-серверного взаимодействия с поддержкой диагностики.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -37,77 +39,117 @@ class Server;
class ClientInterface {}; class ClientInterface {};
//! ~english Base class for client-server communication with diagnostics support //! \brief
//! ~russian Базовый класс для клиент-серверного взаимодействия с поддержкой диагностики //! \~english Base class for client and server-side client
//! \~russian Базовый класс для клиента и клиента на стороне сервера
//! \details
//! \~english Base class for client and server-side client communication. Provides TCP connection management, diagnostics, and packet
//! streaming capabilities.
//! \~russian Базовый класс для клиентской и серверной коммуникации. Обеспечивает управление TCP-соединением, диагностику и потоковую
//! передачу пакетов.
// template<bool EnableDiagnostics = false> // template<bool EnableDiagnostics = false>
class PIP_CLIENT_SERVER_EXPORT ClientBase { class PIP_CLIENT_SERVER_EXPORT ClientBase {
friend class Server; friend class Server;
NO_COPY_CLASS(ClientBase); NO_COPY_CLASS(ClientBase);
public: public:
//! \brief
//! \~english Constructs ClientBase
//! \~russian Создает ClientBase
ClientBase(); ClientBase();
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~ClientBase(); virtual ~ClientBase();
//! ~english Gets underlying TCP connection //! \brief
//! ~russian Возвращает TCP-соединение //! \~english Gets underlying TCP connection
//! \~russian Возвращает TCP-соединение
const PIEthernet * getTCP() const { return tcp; } const PIEthernet * getTCP() const { return tcp; }
//! ~english Closes the connection //! \brief
//! ~russian Закрывает соединение //! \~english Closes the connection
//! \~russian Закрывает соединение
void close(); void close();
//! ~english Gracefully stops and waits for completion //! \brief
//! ~russian Плавно останавливает и ожидает завершения //! \~english Gracefully stops and waits for completion
//! \~russian Плавно останавливает и ожидает завершения
void stopAndWait(); void stopAndWait();
//! ~english Writes byte array to the connection //! \brief
//! ~russian Записывает массив байтов в соединение //! \~english Writes byte array to the connection
//! \~russian Записывает массив байтов в соединение
int write(const void * d, const size_t s); int write(const void * d, const size_t s);
//! ~english Writes byte array to the connection //! \brief
//! ~russian Записывает массив байтов в соединение //! \~english Writes byte array to the connection
//! \~russian Записывает массив байтов в соединение
int write(const PIByteArray & ba) { return write(ba.data(), ba.size()); } int write(const PIByteArray & ba) { return write(ba.data(), ba.size()); }
//! ~english Enables diagnostics collection //! \brief
//! ~russian Включает сбор диагностики //! \~english Enables diagnostics collection
//! \~russian Включает сбор диагностики
void enableDiagnostics(); void enableDiagnostics();
//! ~english Gets current diagnostics state //! \brief
//! ~russian Возвращает текущее состояние диагностики //! \~english Gets current diagnostics state
//! \~russian Возвращает текущее состояние диагностики
PIDiagnostics::State diagnostics() const; PIDiagnostics::State diagnostics() const;
//! ~english Gets current received packet bytes already received (all bytes count passed in \a receivePacketStart()) //! \brief
//! ~russian Возвращает сколько байт принимаемого пакета получено (общее количество передается в \a receivePacketStart()) //! \~english Gets current received packet bytes already received (all bytes count passed in \a receivePacketStart())
//! \~russian Возвращает сколько байт принимаемого пакета получено (общее количество передается в \a receivePacketStart())
int receivePacketProgress() const; int receivePacketProgress() const;
//! \brief
//! \~english Returns stream configuration
//! \~russian Возвращает конфигурацию стрима
const PIStreamPackerConfig & configuration() const { return stream.configuration(); } const PIStreamPackerConfig & configuration() const { return stream.configuration(); }
//! \brief
//! \~english Returns stream configuration
//! \~russian Возвращает конфигурацию стрима
PIStreamPackerConfig & configuration() { return stream.configuration(); } PIStreamPackerConfig & configuration() { return stream.configuration(); }
//! \brief
//! \~english Sets stream configuration
//! \~russian Устанавливает конфигурацию стрима
void setConfiguration(const PIStreamPackerConfig & config) { stream.setConfiguration(config); } void setConfiguration(const PIStreamPackerConfig & config) { stream.setConfiguration(config); }
protected: protected:
//! ~english Called when data is received //! \brief
//! ~russian Вызывается при получении данных //! \~english Called when data is received
//! \~russian Вызывается при получении данных
virtual void readed(PIByteArray data) {} virtual void readed(PIByteArray data) {}
//! ~english Called when connection is established //! \brief
//! ~russian Вызывается при установке соединения //! \~english Called when connection is established
//! \~russian Вызывается при установке соединения
virtual void connected() {} virtual void connected() {}
//! ~english Called when connection is closed //! \brief
//! ~russian Вызывается при закрытии соединения //! \~english Called when connection is closed
//! \~russian Вызывается при закрытии соединения
virtual void disconnected() {} virtual void disconnected() {}
//! ~english Called when packet receiving starts //! \brief
//! ~russian Вызывается при начале получения пакета //! \~english Called when packet receiving starts
//! \~russian Вызывается при начале получения пакета
virtual void receivePacketStart(int size) {} virtual void receivePacketStart(int size) {}
//! ~english Called when packet receiving ends //! \brief
//! ~russian Вызывается при завершении получения пакета //! \~english Called when packet receiving ends
//! \~russian Вызывается при завершении получения пакета
virtual void receivePacketEnd() {} virtual void receivePacketEnd() {}
//! \brief
//! \~english Initializes the client
//! \~russian Инициализирует клиента
void init(); void init();
bool own_tcp = false; bool own_tcp = false;

View File

@@ -1,9 +1,11 @@
/*! \file piclientserver_server.h //! \file piclientserver_server.h
* \ingroup ClientServer //! \ingroup ClientServer
* \~\brief //! \brief
* \~english //! \~english TCP Server
* \~russian //! \~russian TCP Сервер
*/ //! \details
//! \~english TCP server implementation for client-server communication.
//! \~russian Реализация TCP сервера для клиент-серверного взаимодействия.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -38,14 +40,21 @@ namespace PIClientServer {
class ServerClient; class ServerClient;
//! ~english TCP server for client-server communication //! \details
//! ~russian TCP сервер для клиент-серверного взаимодействия //! \~english TCP server implementation for client-server communication. Accepts incoming connections and manages multiple clients with
//! configurable factory for client instance creation.
//! \~russian Реализация TCP сервера для клиент-серверного взаимодействия. Принимает входящие соединения и управляет несколькими клиентами с
//! настраиваемой фабрикой для создания экземпляров клиентов.
class PIP_CLIENT_SERVER_EXPORT Server: public PIStreamPackerConfig { class PIP_CLIENT_SERVER_EXPORT Server: public PIStreamPackerConfig {
friend class ServerClient; friend class ServerClient;
NO_COPY_CLASS(Server); NO_COPY_CLASS(Server);
public: public:
//! \~english Creates Server instance
//! \~russian Создает экземпляр Server
Server(); Server();
//! \~english Destroys Server instance
//! \~russian Уничтожает экземпляр Server
virtual ~Server(); virtual ~Server();
//! ~english Starts listening on specified address //! ~english Starts listening on specified address

View File

@@ -1,9 +1,11 @@
/*! \file picloudbase.h //! \file picloudbase.h
* \ingroup Cloud //! \ingroup Cloud
* \~\brief //! \brief
* \~english Base class for PICloudClient and PICloudServer //! \~english Base class for PICloudClient and PICloudServer
* \~russian Базовый класс для PICloudClient и PICloudServer //! \~russian Базовый класс для PICloudClient и PICloudServer
*/ //! \details
//! \~english Provides common functionality for cloud client and server implementations.
//! \~russian Обеспечивает общую функциональность для реализаций облачного клиента и сервера.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Base - Base class for PICloudClient and PICloud Server PICloud Base - Base class for PICloudClient and PICloud Server
@@ -31,10 +33,20 @@
#include "pistreampacker.h" #include "pistreampacker.h"
//! \brief
//! \~english Base class for cloud client and server
//! \~russian Базовый класс для облачного клиента и сервера
class PIP_CLOUD_EXPORT PICloudBase { class PIP_CLOUD_EXPORT PICloudBase {
public: public:
//! \brief
//! \~english Constructs PICloudBase
//! \~russian Создает PICloudBase
PICloudBase(); PICloudBase();
//! \brief
//! \~english Returns server name
//! \~russian Возвращает имя сервера
PIString serverName() const; PIString serverName() const;
protected: protected:

View File

@@ -1,9 +1,11 @@
/*! \file picloudclient.h //! \file picloudclient.h
* \ingroup Cloud //! \ingroup Cloud
* \~\brief //! \brief
* \~english PICloud Client //! \~english PICloud Client
* \~russian Клиент PICloud //! \~russian Клиент PICloud
*/ //! \details
//! \~english Client implementation for connecting to PICloud servers over TCP.
//! \~russian Реализация клиента для подключения к серверам PICloud по TCP.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Client PICloud Client
@@ -30,7 +32,9 @@
#include "piconditionvar.h" #include "piconditionvar.h"
//! \brief PICloudClient //! \brief PICloud client implementation
//! \~english PICloud client for connecting to servers
//! \~russian Клиент PICloud для подключения к серверам
class PIP_CLOUD_EXPORT PICloudClient class PIP_CLOUD_EXPORT PICloudClient
: public PIIODevice : public PIIODevice
@@ -38,23 +42,75 @@ class PIP_CLOUD_EXPORT PICloudClient
PIIODEVICE(PICloudClient, ""); PIIODEVICE(PICloudClient, "");
public: public:
//! \brief
//! \~english Constructs PICloudClient
//! \~russian Создает PICloudClient
explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICloudClient(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~PICloudClient(); virtual ~PICloudClient();
//! \brief
//! \~english Sets server name
//! \~russian Устанавливает имя сервера
void setServerName(const PIString & server_name); void setServerName(const PIString & server_name);
//! \brief
//! \~english Sets keep connection mode
//! \~russian Устанавливает режим поддержания соединения
void setKeepConnection(bool on); void setKeepConnection(bool on);
//! \brief
//! \~english Checks if connected to server
//! \~russian Проверяет подключение к серверу
bool isConnected() const { return is_connected; } bool isConnected() const { return is_connected; }
//! \brief
//! \~english Returns number of bytes available
//! \~russian Возвращает количество доступных байт
ssize_t bytesAvailable() const override { return buff.size(); } ssize_t bytesAvailable() const override { return buff.size(); }
//! \brief
//! \~english Interrupts connection
//! \~russian Прерывает соединение
void interrupt() override; void interrupt() override;
//! \brief
//! \~english Raised when connected to server
//! \~russian Вызывается при подключении к серверу
EVENT(connected); EVENT(connected);
//! \brief
//! \~english Raised when disconnected from server
//! \~russian Вызывается при отключении от сервера
EVENT(disconnected); EVENT(disconnected);
protected: protected:
//! \brief
//! \~english Opens device
//! \~russian Открывает устройство
bool openDevice() override; bool openDevice() override;
//! \brief
//! \~english Closes device
//! \~russian Закрывает устройство
bool closeDevice() override; bool closeDevice() override;
//! \brief
//! \~english Reads data from device
//! \~russian Читает данные из устройства
ssize_t readDevice(void * read_to, ssize_t max_size) override; ssize_t readDevice(void * read_to, ssize_t max_size) override;
//! \brief
//! \~english Writes data to device
//! \~russian Записывает данные в устройство
ssize_t writeDevice(const void * data, ssize_t size) override; ssize_t writeDevice(const void * data, ssize_t size) override;
//! \brief
//! \~english Returns device info flags
//! \~russian Возвращает флаги информации об устройстве
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; } DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
private: private:

View File

@@ -1,9 +1,11 @@
/*! \file picloudserver.h //! \file picloudserver.h
* \ingroup Cloud //! \ingroup Cloud
* \~\brief //! \brief
* \~english PICloud Server //! \~english PICloud Server
* \~russian Сервер PICloud //! \~russian Сервер PICloud
*/ //! \details
//! \~english Server implementation for accepting PICloud client connections over TCP.
//! \~russian Реализация сервера для приема подключений клиентов PICloud по TCP.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud Server PICloud Server
@@ -30,31 +32,79 @@
#include "piconditionvar.h" #include "piconditionvar.h"
//! \brief PICloud server implementation
//! \~english PICloud server for accepting client connections
//! \~russian Сервер PICloud для приема подключений клиентов
class PIP_CLOUD_EXPORT PICloudServer class PIP_CLOUD_EXPORT PICloudServer
: public PIIODevice : public PIIODevice
, public PICloudBase { , public PICloudBase {
PIIODEVICE(PICloudServer, ""); PIIODEVICE(PICloudServer, "");
public: public:
//! PICloudServer //! \brief
//! \~english Constructs PICloudServer
//! \~russian Создает PICloudServer
explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICloudServer(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~PICloudServer(); virtual ~PICloudServer();
//! \brief Connected client representation
//! \~english Represents a client connected to the server
//! \~russian Представляет клиента, подключенного к серверу
class Client: public PIIODevice { class Client: public PIIODevice {
PIIODEVICE(PICloudServer::Client, ""); PIIODEVICE(PICloudServer::Client, "");
friend class PICloudServer; friend class PICloudServer;
public: public:
//! \brief
//! \~english Constructs Client
//! \~russian Создает Client
//! \param srv Parent server / Родительский сервер
//! \param id Client ID / ID клиента
Client(PICloudServer * srv = nullptr, uint id = 0); Client(PICloudServer * srv = nullptr, uint id = 0);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~Client(); virtual ~Client();
protected: protected:
//! \brief
//! \~english Opens device
//! \~russian Открывает устройство
bool openDevice() override; bool openDevice() override;
//! \brief
//! \~english Closes device
//! \~russian Закрывает устройство
bool closeDevice() override; bool closeDevice() override;
//! \brief
//! \~english Reads data from device
//! \~russian Читает данные из устройства
ssize_t readDevice(void * read_to, ssize_t max_size) override; ssize_t readDevice(void * read_to, ssize_t max_size) override;
//! \brief
//! \~english Writes data to device
//! \~russian Записывает данные в устройство
ssize_t writeDevice(const void * data, ssize_t size) override; ssize_t writeDevice(const void * data, ssize_t size) override;
//! \brief
//! \~english Returns device info flags
//! \~russian Возвращает флаги информации об устройстве
DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; } DeviceInfoFlags deviceInfoFlags() const override { return PIIODevice::Reliable; }
//! \brief
//! \~english Returns number of bytes available
//! \~russian Возвращает количество доступных байт
ssize_t bytesAvailable() const override { return buff.size(); } ssize_t bytesAvailable() const override { return buff.size(); }
//! \brief
//! \~english Interrupts connection
//! \~russian Прерывает соединение
void interrupt() override; void interrupt() override;
private: private:
@@ -67,17 +117,45 @@ public:
std::atomic_bool is_connected; std::atomic_bool is_connected;
}; };
//! \brief
//! \~english Sets server name
//! \~russian Устанавливает имя сервера
void setServerName(const PIString & server_name); void setServerName(const PIString & server_name);
//! \brief
//! \~english Returns list of connected clients
//! \~russian Возвращает список подключенных клиентов
PIVector<PICloudServer::Client *> clients() const; PIVector<PICloudServer::Client *> clients() const;
//! \brief
//! \~english Raised when new client connects
//! \~russian Вызывается при подключении нового клиента
EVENT1(newConnection, PICloudServer::Client *, client); EVENT1(newConnection, PICloudServer::Client *, client);
protected: protected:
//! \brief
//! \~english Opens device
//! \~russian Открывает устройство
bool openDevice() override; bool openDevice() override;
//! \brief
//! \~english Closes device
//! \~russian Закрывает устройство
bool closeDevice() override; bool closeDevice() override;
//! \brief
//! \~english Reads data from device
//! \~russian Читает данные из устройства
ssize_t readDevice(void * read_to, ssize_t max_size) override; ssize_t readDevice(void * read_to, ssize_t max_size) override;
//! \brief
//! \~english Writes data to device
//! \~russian Записывает данные в устройство
ssize_t writeDevice(const void * data, ssize_t max_size) override; ssize_t writeDevice(const void * data, ssize_t max_size) override;
//! \brief
//! \~english Interrupts connection
//! \~russian Прерывает соединение
void interrupt() override; void interrupt() override;
private: private:

View File

@@ -1,9 +1,11 @@
/*! \file picloudtcp.h //! \file picloudtcp.h
* \ingroup Cloud //! \ingroup Cloud
* \~\brief //! \brief
* \~english PICloud TCP transport //! \~english PICloud TCP transport
* \~russian TCP слой PICloud //! \~russian TCP слой PICloud
*/ //! \details
//! \~english Low-level TCP protocol implementation for PICloud communication.
//! \~russian Реализация низкоуровневого TCP-протокола для коммуникации PICloud.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
PICloud TCP transport PICloud TCP transport
@@ -36,45 +38,118 @@ class PIStreamPacker;
namespace PICloud { namespace PICloud {
//! \brief TCP transport protocol
//! \~english TCP transport protocol for cloud communication
//! \~russian TCP транспортный протокол для облачной коммуникации
class PIP_CLOUD_EXPORT TCP { class PIP_CLOUD_EXPORT TCP {
public: public:
//! \brief Protocol version
enum Version { enum Version {
Version_1 = 1, Version_1 = 1, //!< Version 1 / Версия 1
Version_2 = 2, Version_2 = 2, //!< Version 2 / Версия 2
}; };
//! \brief Connection role
enum Role { enum Role {
InvalidRole = 0, InvalidRole = 0, //!< Invalid role / Неверная роль
Server = 1, Server = 1, //!< Server role / Роль сервера
Client = 2, Client = 2, //!< Client role / Роль клиента
}; };
//! \brief Message type
enum Type { enum Type {
InvalidType = 0, InvalidType = 0, //!< Invalid type / Неверный тип
Connect = 1, Connect = 1, //!< Connect message / Сообщение о подключении
Disconnect = 2, Disconnect = 2, //!< Disconnect message / Сообщение об отключении
Data = 3, Data = 3, //!< Data message / Сообщение с данными
Ping = 4, Ping = 4, //!< Ping message / Сообщение ping
}; };
//! \brief
//! \~english Constructs TCP transport
//! \~russian Создает TCP транспорт
//! \param s Stream packer instance / Экземпляр стримового упаковщика
TCP(PIStreamPacker * s); TCP(PIStreamPacker * s);
//! \brief
//! \~english Sets connection role
//! \~russian Устанавливает роль соединения
void setRole(Role r); void setRole(Role r);
//! \brief
//! \~english Returns connection role
//! \~russian Возвращает роль соединения
Role role() const { return (Role)header.role; } Role role() const { return (Role)header.role; }
//! \brief
//! \~english Sets server name
//! \~russian Устанавливает имя сервера
void setServerName(const PIString & server_name_); void setServerName(const PIString & server_name_);
//! \brief
//! \~english Returns server name
//! \~russian Возвращает имя сервера
PIString serverName() const; PIString serverName() const;
//! \brief
//! \~english Sends start message
//! \~russian Отправляет сообщение о старте
void sendStart(); void sendStart();
//! \brief
//! \~english Sends connected message
//! \~russian Отправляет сообщение о подключении
void sendConnected(uint client_id); void sendConnected(uint client_id);
//! \brief
//! \~english Sends disconnected message
//! \~russian Отправляет сообщение об отключении
void sendDisconnected(uint client_id); void sendDisconnected(uint client_id);
//! \brief
//! \~english Sends data to all clients
//! \~russian Отправляет данные всем клиентам
int sendData(const PIByteArray & data); int sendData(const PIByteArray & data);
//! \brief
//! \~english Sends data to specific client
//! \~russian Отправляет данные конкретному клиенту
int sendData(const PIByteArray & data, uint client_id); int sendData(const PIByteArray & data, uint client_id);
//! \brief
//! \~english Sends ping message
//! \~russian Отправляет сообщение ping
void sendPing(); void sendPing();
//! \brief
//! \~english Parses header from buffer
//! \~russian Парсит заголовок из буфера
PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba); PIPair<PICloud::TCP::Type, PICloud::TCP::Role> parseHeader(PIByteArray & ba);
//! \brief
//! \~english Checks if data can be parsed
//! \~russian Проверяет возможность парсинга данных
bool canParseData(PIByteArray & ba); bool canParseData(PIByteArray & ba);
//! \brief
//! \~english Parses data for server
//! \~russian Парсит данные для сервера
PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba); PIPair<uint, PIByteArray> parseDataServer(PIByteArray & ba);
//! \brief
//! \~english Parses connect data
//! \~russian Парсит данные подключения
PIByteArray parseConnect_d(PIByteArray & ba); PIByteArray parseConnect_d(PIByteArray & ba);
//! \brief
//! \~english Parses connect message
//! \~russian Парсит сообщение подключения
uint parseConnect(PIByteArray & ba); uint parseConnect(PIByteArray & ba);
//! \brief
//! \~english Parses disconnect message
//! \~russian Парсит сообщение отключения
uint parseDisconnect(PIByteArray & ba); uint parseDisconnect(PIByteArray & ba);
private: private:

View File

@@ -59,6 +59,7 @@ PICodeInfo::__Storage__::__Storage__() {
enumsInfo = new PIMap<PIConstChars, EnumInfo *>; enumsInfo = new PIMap<PIConstChars, EnumInfo *>;
accessValueFunctions = new PIMap<PIConstChars, AccessValueFunction>; accessValueFunctions = new PIMap<PIConstChars, AccessValueFunction>;
accessTypeFunctions = new PIMap<PIConstChars, AccessTypeFunction>; accessTypeFunctions = new PIMap<PIConstChars, AccessTypeFunction>;
accessOffsetFunctions = new PIMap<PIConstChars, AccessOffsetFunction>;
(*enumsInfo)[""] = new EnumInfo(); (*enumsInfo)[""] = new EnumInfo();
} }
@@ -70,6 +71,7 @@ PICodeInfo::__Storage__::~__Storage__() {
piDeleteSafety(enumsInfo); piDeleteSafety(enumsInfo);
piDeleteSafety(accessValueFunctions); piDeleteSafety(accessValueFunctions);
piDeleteSafety(accessTypeFunctions); piDeleteSafety(accessTypeFunctions);
piDeleteSafety(accessOffsetFunctions);
} }

View File

@@ -58,11 +58,14 @@ typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
typedef PIMap<PIString, PIString> MetaMap; typedef PIMap<PIString, PIString> MetaMap;
typedef PIByteArray (*AccessValueFunction)(const void *, const char *); typedef PIByteArray (*AccessValueFunction)(const void *, const char *);
typedef const char * (*AccessTypeFunction)(const char *); typedef const char * (*AccessTypeFunction)(const char *);
typedef int (*AccessOffsetFunction)(const char *);
//! \~english Type information //! \~english Type information
//! \~russian Информация о типе //! \~russian Информация о типе
struct PIP_EXPORT TypeInfo { struct PIP_EXPORT TypeInfo {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) { TypeInfo(const PIConstChars & n = PIConstChars(), const PIConstChars & t = PIConstChars(), PICodeInfo::TypeFlags f = 0, int b = -1) {
name = n; name = n;
type = t; type = t;
@@ -120,15 +123,17 @@ struct PIP_EXPORT FunctionInfo {
//! \~english Class or struct information //! \~english Class or struct information
//! \~russian Информация о классе или структуре //! \~russian Информация о классе или структуре
struct PIP_EXPORT ClassInfo { struct PIP_EXPORT ClassInfo {
ClassInfo() { has_name = true; } //! \~english Default constructor
//! \~russian Конструктор по умолчанию
ClassInfo() { is_anonymous = false; }
//! \~english Custom PIMETA content //! \~english Custom PIMETA content
//! \~russian Произвольное содержимое PIMETA //! \~russian Произвольное содержимое PIMETA
MetaMap meta; MetaMap meta;
//! \~english Has name or not //! \~english Anonymous or not
//! \~russian Имеет или нет имя //! \~russian Анонимный или нет
bool has_name; bool is_anonymous;
//! \~english Type //! \~english Type
//! \~russian Тип //! \~russian Тип
@@ -159,10 +164,14 @@ struct PIP_EXPORT ClassInfo {
//! \~english Enumerator information //! \~english Enumerator information
//! \~russian Информация об элементе перечисления //! \~russian Информация об элементе перечисления
struct PIP_EXPORT EnumeratorInfo { struct PIP_EXPORT EnumeratorInfo {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) { EnumeratorInfo(const PIConstChars & n = PIConstChars(), int v = 0) {
name = n; name = n;
value = v; value = v;
} }
//! \~english Converts to PIVariantTypes::Enumerator
//! \~russian Конвертирует в PIVariantTypes::Enumerator
PIVariantTypes::Enumerator toPIVariantEnumerator() { return PIVariantTypes::Enumerator(value, name.toString()); } PIVariantTypes::Enumerator toPIVariantEnumerator() { return PIVariantTypes::Enumerator(value, name.toString()); }
//! \~english Custom PIMETA content //! \~english Custom PIMETA content
@@ -208,6 +217,8 @@ struct PIP_EXPORT EnumInfo {
}; };
//! \~english Output stream operator for TypeInfo
//! \~russian Оператор вывода для TypeInfo
inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) { inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) {
if (v.flags[Inline]) s << "inline "; if (v.flags[Inline]) s << "inline ";
if (v.flags[Virtual]) s << "virtual "; if (v.flags[Virtual]) s << "virtual ";
@@ -220,11 +231,15 @@ inline PICout operator<<(PICout s, const PICodeInfo::TypeInfo & v) {
return s; return s;
} }
//! \~english Output stream operator for EnumeratorInfo
//! \~russian Оператор вывода для EnumeratorInfo
inline PICout operator<<(PICout s, const PICodeInfo::EnumeratorInfo & v) { inline PICout operator<<(PICout s, const PICodeInfo::EnumeratorInfo & v) {
s << v.name << " = " << v.value << " Meta" << v.meta; s << v.name << " = " << v.value << " Meta" << v.meta;
return s; return s;
} }
//! \~english Output stream operator for ClassInfo
//! \~russian Оператор вывода для ClassInfo
inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) { inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) {
s.saveAndSetControls(0); s.saveAndSetControls(0);
s << "class " << v.name; s << "class " << v.name;
@@ -261,6 +276,8 @@ inline PICout operator<<(PICout s, const PICodeInfo::ClassInfo & v) {
return s; return s;
} }
//! \~english Output stream operator for EnumInfo
//! \~russian Оператор вывода для EnumInfo
inline PICout operator<<(PICout s, const PICodeInfo::EnumInfo & v) { inline PICout operator<<(PICout s, const PICodeInfo::EnumInfo & v) {
s.saveAndSetControls(0); s.saveAndSetControls(0);
s << "enum " << v.name << " Meta" << v.meta << " {\n"; s << "enum " << v.name << " Meta" << v.meta << " {\n";
@@ -278,44 +295,69 @@ inline PICout operator<<(PICout s, const PICodeInfo::EnumInfo & v) {
} }
//! \~english Storage singleton for PICodeInfo
//! \~russian Синглтон хранилища для PICodeInfo
class PIP_EXPORT __Storage__ { class PIP_EXPORT __Storage__ {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
__Storage__(); __Storage__();
//! \~english Destructor
//! \~russian Деструктор
~__Storage__(); ~__Storage__();
public: public:
//! \~english Returns singleton instance
//! \~russian Возвращает экземпляр синглтона
static __Storage__ * instance(); static __Storage__ * instance();
PIMap<PIConstChars, PICodeInfo::ClassInfo *> * classesInfo; PIMap<PIConstChars, PICodeInfo::ClassInfo *> * classesInfo;
PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo; PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo;
PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions; PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions; PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> * accessOffsetFunctions;
private: private:
NO_COPY_CLASS(__Storage__) NO_COPY_CLASS(__Storage__)
}; };
//! \~english Access to singleton storage of PICodeInfo
//! \~russian Доступ к синглтону хранилища PICodeInfo
class PIP_EXPORT __StorageAccess__ { class PIP_EXPORT __StorageAccess__ {
public: public:
//! \~english Getter for single storage of PICodeInfo::ClassInfo, access by name //! \~english Getter for single storage of PICodeInfo::ClassInfo, access by name
//! \~russian Доступ к единому хранилищу PICodeInfo::ClassInfo, доступ по имени //! \~russian Доступ к единому хранилищу PICodeInfo::ClassInfo, доступ по имени
static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes() { return *(__Storage__::instance()->classesInfo); } static const PIMap<PIConstChars, PICodeInfo::ClassInfo *> & classes() {
return *(__Storage__::instance()->classesInfo);
} // namespace PICodeInfo
//! \~english Getter for single storage of PICodeInfo::EnumInfo, access by name //! \~english Getter for single storage of PICodeInfo::EnumInfo, access by name
//! \~russian Доступ к единому хранилищу хранилище PICodeInfo::EnumInfo, доступ по имени //! \~russian Доступ к единому хранилищу хранилище PICodeInfo::EnumInfo, доступ по имени
static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() { return *(__Storage__::instance()->enumsInfo); } static const PIMap<PIConstChars, PICodeInfo::EnumInfo *> & enums() { return *(__Storage__::instance()->enumsInfo); }
//! \~english Access to value functions map
//! \~russian Доступ к карте функций значений
static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() { static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueFunctions() {
return *(__Storage__::instance()->accessValueFunctions); return *(__Storage__::instance()->accessValueFunctions);
} }
//! \~english Access to type functions map
//! \~russian Доступ к карте функций типов
static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() { static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() {
return *(__Storage__::instance()->accessTypeFunctions); return *(__Storage__::instance()->accessTypeFunctions);
} }
//! \~english Access to offset functions map
//! \~russian Доступ к карте функций смещений
static const PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> & accessOffsetFunctions() {
return *(__Storage__::instance()->accessOffsetFunctions);
}
}; };
#define PICODEINFO PICodeInfo::__StorageAccess__ #define PICODEINFO PICodeInfo::__StorageAccess__
//! \~english Deprecated interface for accessing classes info
//! \~russian Устаревший интерфейс для доступа к информации о классах
class PIP_EXPORT ClassInfoInterface { class PIP_EXPORT ClassInfoInterface {
public: public:
const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()") { const PIMap<PIConstChars, PICodeInfo::ClassInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::classes()") {
@@ -325,6 +367,8 @@ public:
static ClassInfoInterface classesInfo; static ClassInfoInterface classesInfo;
//! \~english Deprecated interface for accessing enums info
//! \~russian Устаревший интерфейс для доступа к информации о перечислениях
class PIP_EXPORT EnumsInfoInterface { class PIP_EXPORT EnumsInfoInterface {
public: public:
const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()") { const PIMap<PIConstChars, PICodeInfo::EnumInfo *> * operator->() const DEPRECATEDM("use PICODEINFO::enums()") {
@@ -334,6 +378,8 @@ public:
static EnumsInfoInterface enumsInfo; static EnumsInfoInterface enumsInfo;
//! \~english Deprecated interface for accessing value functions
//! \~russian Устаревший интерфейс для доступа к функциям значений
class PIP_EXPORT AccessValueFunctionInterface { class PIP_EXPORT AccessValueFunctionInterface {
public: public:
const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessValueFunctions()") { const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessValueFunctions()") {
@@ -343,6 +389,8 @@ public:
static AccessValueFunctionInterface accessValueFunctions; static AccessValueFunctionInterface accessValueFunctions;
//! \~english Deprecated interface for accessing type functions
//! \~russian Устаревший интерфейс для доступа к функциям типов
class PIP_EXPORT AccessTypeFunctionInterface { class PIP_EXPORT AccessTypeFunctionInterface {
public: public:
const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()") { const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * operator->() const DEPRECATEDM("use PICODEINFO::accessTypeFunctions()") {
@@ -360,6 +408,8 @@ STATIC_INITIALIZER_BEGIN
STATIC_INITIALIZER_END STATIC_INITIALIZER_END
//! \~english Gets member value as PIByteArray
//! \~russian Получает значение члена как PIByteArray
inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) { inline PIByteArray getMemberValue(const void * p, const char * class_name, const char * member_name) {
if (!p || !class_name || !member_name) return PIByteArray(); if (!p || !class_name || !member_name) return PIByteArray();
AccessValueFunction af = PICODEINFO::accessValueFunctions().value(class_name, (AccessValueFunction)0); AccessValueFunction af = PICODEINFO::accessValueFunctions().value(class_name, (AccessValueFunction)0);
@@ -367,6 +417,8 @@ inline PIByteArray getMemberValue(const void * p, const char * class_name, const
return af(p, member_name); return af(p, member_name);
} }
//! \~english Gets member type as string
//! \~russian Получает тип члена как строку
inline const char * getMemberType(const char * class_name, const char * member_name) { inline const char * getMemberType(const char * class_name, const char * member_name) {
if (!class_name || !member_name) return ""; if (!class_name || !member_name) return "";
AccessTypeFunction af = PICODEINFO::accessTypeFunctions().value(class_name, (AccessTypeFunction)0); AccessTypeFunction af = PICODEINFO::accessTypeFunctions().value(class_name, (AccessTypeFunction)0);
@@ -374,14 +426,20 @@ inline const char * getMemberType(const char * class_name, const char * member_n
return af(member_name); return af(member_name);
} }
//! \~english Gets member value as PIVariant
//! \~russian Получает значение члена как PIVariant
PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name); PIP_EXPORT PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name);
//! \~english Serializes value to PIByteArray (for assignable types)
//! \~russian Сериализует значение в PIByteArray (для назначаемых типов)
template<typename T, typename std::enable_if<std::is_assignable<T &, const T &>::value, int>::type = 0> template<typename T, typename std::enable_if<std::is_assignable<T &, const T &>::value, int>::type = 0>
void serialize(PIByteArray & ret, const T & v) { void serialize(PIByteArray & ret, const T & v) {
ret << v; ret << v;
} }
//! \~english Empty serialization (for non-assignable types)
//! \~russian Пустая сериализация (для неназначаемых типов)
template<typename T, typename std::enable_if<!std::is_assignable<T &, const T &>::value, int>::type = 0> template<typename T, typename std::enable_if<!std::is_assignable<T &, const T &>::value, int>::type = 0>
void serialize(PIByteArray & ret, const T & v) {} void serialize(PIByteArray & ret, const T & v) {}

View File

@@ -19,6 +19,8 @@
#include "picodeparser.h" #include "picodeparser.h"
#include "piliterals_string.h"
PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const { PIString PICodeParser::Macro::expand(PIString args_, bool * ok) const {
PIStringList arg_vals; PIStringList arg_vals;
@@ -454,7 +456,7 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
cur_namespace += pfc.takeCWord() + s_ns; cur_namespace += pfc.takeCWord() + s_ns;
ccmn = pfc.takeRange('{', '}'); ccmn = pfc.takeRange('{', '}');
// piCout << "namespace" << cur_namespace; // piCout << "namespace" << cur_namespace;
parseClass(0, ccmn, true); parseClass(nullptr, ccmn, true);
cur_namespace = prev_namespace; cur_namespace = prev_namespace;
continue; continue;
} }
@@ -483,8 +485,8 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
continue; continue;
} }
ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc; ccmn = pfc.left(dind) + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
pfc.remove(0, ccmn.size()); pfc.remove(0, ccmn.size() - 2);
parseClass(0, ccmn, false); parseClass(nullptr, ccmn, false);
continue; continue;
} }
if (pfc.left(4) == s_enum) { if (pfc.left(4) == s_enum) {
@@ -499,17 +501,59 @@ bool PICodeParser::parseFileContent(PIString & fc, bool main) {
meta << smeta; meta << smeta;
} }
// piCout << "pfc E" << cur_namespace << "," << tmp; // piCout << "pfc E" << cur_namespace << "," << tmp;
parseEnum(0, cur_namespace + tmp, pfc.takeRange('{', '}'), meta); parseEnum(nullptr, cur_namespace + tmp, pfc.takeRange('{', '}'), meta);
pfc.takeSymbol(); pfc.takeSymbol();
continue; continue;
} }
if (pfc.left(7) == s_typedef) { if (pfc.left(7) == s_typedef) {
pfc.cutLeft(7); pfc.cutLeft(7);
typedefs << parseTypedef(pfc.takeLeft(pfc.find(';'))); PIString typedef_type = pfc.takeCWord();
if (typedef_type == s_class || typedef_type == s_struct || typedef_type == s_union) {
int dind = pfc.find('{', 0), find = pfc.find(';', 0);
if (dind < 0 && find < 0) {
pfc.cutLeft(6);
continue;
}
if (dind < 0 || find < dind) {
pfc.cutLeft(find + 1);
continue;
}
PIString cname = pfc.left(dind);
ccmn = cname + s_bo + pfc.mid(dind).takeRange('{', '}') + s_bc;
pfc.remove(0, ccmn.size() - 3);
if (cname.trimmed().isEmpty()) {
cname = pfc.takeCWord();
ccmn.prepend(cname);
}
ccmn.prepend(typedef_type + " "_a);
parseClass(nullptr, ccmn, false);
} else if (typedef_type == s_enum) {
tmp = pfc.takeCWord();
pfc.trim();
MetaMap meta = maybeMeta(pfc);
if (tmp == s_class || tmp == s_struct) {
tmp = pfc.takeCWord();
pfc.trim();
MetaMap smeta = maybeMeta(pfc);
meta << smeta;
}
ccmn = pfc.takeRange('{', '}');
if (tmp.isEmpty()) {
tmp = pfc.takeCWord();
}
// piCout << "pfc E" << cur_namespace << "," << tmp;
parseEnum(nullptr, cur_namespace + tmp, ccmn, meta);
} else {
pfc.prepend(typedef_type);
}
PIString last = pfc.takeLeft(pfc.find(';')).trim();
if (last.isNotEmpty()) {
typedefs << parseTypedef(last);
if (typedefs.back().first.isEmpty()) if (typedefs.back().first.isEmpty())
typedefs.pop_back(); typedefs.pop_back();
else else
root_.typedefs << typedefs.back(); root_.typedefs << typedefs.back();
}
pfc.takeSymbol(); pfc.takeSymbol();
continue; continue;
} }
@@ -567,15 +611,14 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
Visibility vis = cur_def_vis; Visibility vis = cur_def_vis;
cur_def_vis = (is_class ? Private : Public); cur_def_vis = (is_class ? Private : Public);
PIString cn = cd.mid(6).trim(); PIString cn = cd.mid(6).trim();
bool has_name = !cn.isEmpty(); bool is_anonymous = cn.isEmpty();
if (cn.isEmpty()) cn = PIStringAscii("<unnamed_") + PIString::fromNumber(anon_num++) + '>'; if (cn.isEmpty()) cn = PIStringAscii("<unnamed_") + PIString::fromNumber(anon_num++) + '>';
// piCout << "found " << typename_ << cn; // piCout << "found " << typename_ << cn;
if (cn.isEmpty()) return nullptr;
Entity * e = new Entity(); Entity * e = new Entity();
e->meta = meta; e->meta = meta;
e->name = cur_namespace + cn; e->name = cur_namespace + cn;
e->type = typename_; e->type = typename_;
e->has_name = has_name; e->is_anonymous = is_anonymous;
e->parents = parents; e->parents = parents;
e->visibility = vis; e->visibility = vis;
e->file = cur_file; e->file = cur_file;
@@ -584,7 +627,7 @@ PICodeParser::Entity * PICodeParser::parseClassDeclaration(const PIString & fc)
} }
void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace) { PICodeParser::Entity * PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace) {
static const PIString s_ns = PIStringAscii("::"); static const PIString s_ns = PIStringAscii("::");
static const PIString s_public = PIStringAscii("public"); static const PIString s_public = PIStringAscii("public");
static const PIString s_protected = PIStringAscii("protected"); static const PIString s_protected = PIStringAscii("protected");
@@ -599,7 +642,7 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
static const PIString s_template = PIStringAscii("template"); static const PIString s_template = PIStringAscii("template");
Visibility prev_vis = cur_def_vis; Visibility prev_vis = cur_def_vis;
int dind = fc.find('{'), find = fc.find(';'), end = 0; int dind = fc.find('{'), find = fc.find(';'), end = 0;
if (dind < 0 && find < 0) return; if (dind < 0 && find < 0) return nullptr;
// piCout << "parse class <****\n" << fc << "\n****>"; // piCout << "parse class <****\n" << fc << "\n****>";
Entity * ce = parent; Entity * ce = parent;
if (!is_namespace) { if (!is_namespace) {
@@ -608,7 +651,6 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
} }
// piCout << "found class <****\n" << fc << "\n****>"; // piCout << "found class <****\n" << fc << "\n****>";
if (ce) { if (ce) {
if (parent) parent->children << ce;
ce->parent_scope = parent; ce->parent_scope = parent;
} }
int ps = -1; int ps = -1;
@@ -650,11 +692,29 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
fc.takeSymbol(); fc.takeSymbol();
continue; continue;
} }
tmp = fc.takeLeft(fc.find('{')); tmp = fc.takeLeft(fc.find('{')).trim();
stmp = fc.takeRange('{', '}'); stmp = fc.takeRange('{', '}');
fc.takeSymbol();
stmp = cw + ' ' + tmp + '{' + stmp + '}'; stmp = cw + ' ' + tmp + '{' + stmp + '}';
parseClass(ce, stmp, false); auto new_entity = parseClass(ce, stmp, false);
// piCout << "!!! > \"" << fc << "\"";
PIStringList vars;
PIString var;
do {
var = fc.takeCWord();
if (var.isNotEmpty()) vars << var;
if (fc.takeSymbol() == ";") break;
} while (var.isNotEmpty());
if (new_entity) {
Member me;
me.visibility = cur_def_vis;
me.type = new_entity->name;
if (tmp.isEmpty() && vars.isEmpty()) vars = {""};
for (const auto & v: vars) {
me.name = v;
ce->members << me;
}
}
// piCout << "!!! <" << vars;
continue; continue;
} }
if (cw == s_enum) { if (cw == s_enum) {
@@ -710,6 +770,7 @@ void PICodeParser::parseClass(Entity * parent, PIString & fc, bool is_namespace)
} }
cur_def_vis = prev_vis; cur_def_vis = prev_vis;
cur_namespace = prev_namespace; cur_namespace = prev_namespace;
return ce;
} }
@@ -766,7 +827,7 @@ bool PICodeParser::parseEnum(Entity * parent, const PIString & name, PIString fc
PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) { PICodeParser::Typedef PICodeParser::parseTypedef(PIString fc) {
// piCout << "parse typedef" << fc; // piCout << "parse typedef \"" << fc << "\"";
Typedef td; Typedef td;
fc.replaceAll('\t', ' '); fc.replaceAll('\t', ' ');
@@ -1197,7 +1258,7 @@ void PICodeParser::replaceMeta(PIString & dn) {
PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) { PICodeParser::Entity * PICodeParser::findEntityByName(const PIString & en) {
for (auto * e: entities) for (auto * e: entities)
if (e->name == en) return e; if (e->name == en) return e;
return 0; return nullptr;
} }

View File

@@ -1,8 +1,13 @@
/*! \file picodeparser.h /*! \file picodeparser.h
* \ingroup Code * \addtogroup Code
* \~\brief * \{
* \~
* \brief
* \~english C++ code parser * \~english C++ code parser
* \~russian Разбор C++ кода * \~russian Разбор C++ кода
* \details
* \~english Parser for analyzing C++ source files. Extracts information about classes, structures, enums, macros, functions, and members.
* \~russian Парсер для анализа C++ исходных файлов. Извлекает информацию о классах, структурах, перечислениях, макросах, функциях и членах.
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
@@ -39,6 +44,8 @@ inline bool _isCChar(const PIString & c) {
class PIP_EXPORT PICodeParser { class PIP_EXPORT PICodeParser {
public: public:
//! \~english Default constructor.
//! \~russian Конструктор по умолчанию.
PICodeParser(); PICodeParser();
enum Visibility { enum Visibility {
@@ -63,18 +70,27 @@ public:
typedef PIPair<PIString, PIString> Typedef; typedef PIPair<PIString, PIString> Typedef;
typedef PIMap<PIString, PIString> MetaMap; typedef PIMap<PIString, PIString> MetaMap;
//! \~english Represents a preprocessor macro.
//! \~russian Представляет препроцессорный макрос.
struct PIP_EXPORT Macro { struct PIP_EXPORT Macro {
Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) { Macro(const PIString & n = PIString(), const PIString & v = PIString(), const PIStringList & a = PIStringList()) {
name = n; name = n;
value = v; value = v;
args = a; args = a;
} }
//! \~english Expand macro with given arguments.
//! \~russian Раскрыть макрос с заданными аргументами.
//! \param args_ Arguments string
//! \param ok Output flag indicating success
//! \return Expanded macro value
PIString expand(PIString args_, bool * ok = 0) const; PIString expand(PIString args_, bool * ok = 0) const;
PIString name; PIString name;
PIString value; PIString value;
PIStringList args; PIStringList args;
}; };
//! \~english Represents a class/struct member variable or function.
//! \~russian Представляет переменную-член или функцию класса/структуры.
struct PIP_EXPORT Member { struct PIP_EXPORT Member {
Member() { Member() {
visibility = Global; visibility = Global;
@@ -83,6 +99,8 @@ public:
is_type_ptr = false; is_type_ptr = false;
attributes = NoAttributes; attributes = NoAttributes;
} }
//! \~english Check if member is a bitfield.
//! \~russian Проверить, является ли член битовым полем.
bool isBitfield() const { return bits > 0; } bool isBitfield() const { return bits > 0; }
MetaMap meta; MetaMap meta;
PIString type; PIString type;
@@ -97,10 +115,12 @@ public:
int bits; int bits;
}; };
//! \~english Represents a parsed entity (class, struct, namespace, etc.).
//! \~russian Представляет разобранную сущность (класс, структуру, пространство имен и т.д.).
struct PIP_EXPORT Entity { struct PIP_EXPORT Entity {
Entity() { Entity() {
visibility = Global; visibility = Global;
has_name = true; is_anonymous = false;
size = 0; size = 0;
parent_scope = 0; parent_scope = 0;
} }
@@ -110,15 +130,16 @@ public:
PIString file; PIString file;
Visibility visibility; Visibility visibility;
int size; int size;
bool has_name; bool is_anonymous;
Entity * parent_scope; Entity * parent_scope;
PIVector<Entity *> parents; PIVector<Entity *> parents;
PIVector<Entity *> children;
PIVector<Member> functions; PIVector<Member> functions;
PIVector<Member> members; PIVector<Member> members;
PIVector<Typedef> typedefs; PIVector<Typedef> typedefs;
}; };
//! \~english Represents an enumerator value.
//! \~russian Представляет значение перечисления.
struct PIP_EXPORT EnumeratorInfo { struct PIP_EXPORT EnumeratorInfo {
EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) { EnumeratorInfo(const PIString & n = PIString(), int v = 0, const MetaMap & m = MetaMap()) {
name = n; name = n;
@@ -130,6 +151,8 @@ public:
int value; int value;
}; };
//! \~english Represents a parsed enum type.
//! \~russian Представляет разобранный тип перечисления.
struct PIP_EXPORT Enum { struct PIP_EXPORT Enum {
Enum(const PIString & n = PIString()) { name = n; } Enum(const PIString & n = PIString()) { name = n; }
MetaMap meta; MetaMap meta;
@@ -137,25 +160,89 @@ public:
PIVector<EnumeratorInfo> members; PIVector<EnumeratorInfo> members;
}; };
//! \~english Parse C++ source file.
//! \~russian Разбор C++ исходного файла.
//! \param file Path to source file
//! \param follow_includes Whether to follow include directives
void parseFile(const PIString & file, bool follow_includes = true); void parseFile(const PIString & file, bool follow_includes = true);
//! \~english Parse multiple C++ source files.
//! \~russian Разбор нескольких C++ исходных файлов.
//! \param files List of file paths
//! \param follow_includes Whether to follow include directives
void parseFiles(const PIStringList & files, bool follow_includes = true); void parseFiles(const PIStringList & files, bool follow_includes = true);
//! \~english Parse C++ source from string content.
//! \~russian Разбор C++ исходного кода из строки.
//! \param fc Source code content
void parseFileContent(PIString fc); void parseFileContent(PIString fc);
//! \~english Add directory to search for include files.
//! \~russian Добавить директорию для поиска включаемых файлов.
//! \param dir Directory path
void includeDirectory(const PIString & dir) { includes << dir; } void includeDirectory(const PIString & dir) { includes << dir; }
//! \~english Add custom macro definition.
//! \~russian Добавить пользовательское определение макроса.
//! \param def_name Macro name
//! \param def_value Macro value
void addDefine(const PIString & def_name, const PIString & def_value) { custom_defines << Define(def_name, def_value); } void addDefine(const PIString & def_name, const PIString & def_value) { custom_defines << Define(def_name, def_value); }
//! \~english Check if name refers to an enum type.
//! \~russian Проверить, является ли имя типом перечисления.
//! \param name Name to check
//! \return true if name is an enum
bool isEnum(const PIString & name); bool isEnum(const PIString & name);
//! \~english Find entity by name.
//! \~russian Найти сущность по имени.
//! \param en Entity name
//! \return Pointer to entity or nullptr
Entity * findEntityByName(const PIString & en); Entity * findEntityByName(const PIString & en);
//! \~english Get list of parsed files.
//! \~russian Получить список разобранных файлов.
//! \return List of file paths
PIStringList parsedFiles() const { return PIStringList(proc_files.toVector()); } PIStringList parsedFiles() const { return PIStringList(proc_files.toVector()); }
//! \~english Get main file path.
//! \~russian Получить путь к главному файлу.
//! \return Main file path
PIString mainFile() const { return main_file; } PIString mainFile() const { return main_file; }
//! \~english Get global scope entity.
//! \~russian Получить сущность глобальной области видимости.
//! \return Pointer to global entity
const PICodeParser::Entity * global() const { return &root_; } const PICodeParser::Entity * global() const { return &root_; }
//! \~english Get maximum iterations for macros substitution.
//! \~russian Получить максимальное количество итераций для подстановки макросов.
//! \return Maximum iterations count
int macrosSubstitutionMaxIterations() const { return macros_iter; } int macrosSubstitutionMaxIterations() const { return macros_iter; }
//! \~english Set maximum iterations for macros substitution.
//! \~russian Установить максимальное количество итераций для подстановки макросов.
//! \param value Maximum iterations count
void setMacrosSubstitutionMaxIterations(int value) { macros_iter = value; } void setMacrosSubstitutionMaxIterations(int value) { macros_iter = value; }
//! \~english List of defined macros.
//! \~russian Список определенных макросов.
PIVector<Define> defines, custom_defines; PIVector<Define> defines, custom_defines;
//! \~english List of macro definitions with expansion.
//! \~russian Список определений макросов с подстановкой.
PIVector<Macro> macros; PIVector<Macro> macros;
//! \~english List of enumerated types.
//! \~russian Список типов перечислений.
PIVector<Enum> enums; PIVector<Enum> enums;
//! \~english List of type definitions.
//! \~russian Список определений типов.
PIVector<Typedef> typedefs; PIVector<Typedef> typedefs;
//! \~english List of parsed entities (classes, structs, etc.).
//! \~russian Список разобранных сущностей (классов, структур и т.д.).
PIVector<Entity *> entities; PIVector<Entity *> entities;
private: private:
@@ -164,7 +251,7 @@ private:
bool parseFileContent(PIString & fc, bool main); bool parseFileContent(PIString & fc, bool main);
bool parseDirective(PIString d); bool parseDirective(PIString d);
Entity * parseClassDeclaration(const PIString & fc); Entity * parseClassDeclaration(const PIString & fc);
void parseClass(Entity * parent, PIString & fc, bool is_namespace); Entity * parseClass(Entity * parent, PIString & fc, bool is_namespace);
MetaMap parseMeta(PIString & fc); MetaMap parseMeta(PIString & fc);
bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta); bool parseEnum(Entity * parent, const PIString & name, PIString fc, const MetaMap & meta);
Typedef parseTypedef(PIString fc); Typedef parseTypedef(PIString fc);
@@ -196,4 +283,7 @@ private:
PIMap<PIString, MetaMap> tmp_meta; PIMap<PIString, MetaMap> tmp_meta;
}; };
/*! \}
*/
#endif // PICODEPARSER_H #endif // PICODEPARSER_H

View File

@@ -177,13 +177,29 @@ public:
//! Returns exit key, default 'Q' //! Returns exit key, default 'Q'
int exitKey() const { return exit_key; } int exitKey() const { return exit_key; }
//! \brief
//! \~english Returns double click interval in seconds
//! \~russian Возвращает интервал двойного клика в секундах
double doubleClickInterval() const { return dbl_interval; } double doubleClickInterval() const { return dbl_interval; }
//! \brief
//! \~english Sets double click interval
//! \~russian Устанавливает интервал двойного клика
void setDoubleClickInterval(double v) { dbl_interval = v; } void setDoubleClickInterval(double v) { dbl_interval = v; }
//! \brief
//! \~english Reads keyboard input
//! \~russian Читает ввод с клавиатуры
void readKeyboard(); void readKeyboard();
//! \brief
//! \~english Stops keyboard listening
//! \~russian Останавливает прослушивание клавиатуры
void stop(); void stop();
//! \brief
//! \~english Stops and waits for completion
//! \~russian Останавливает и ожидает завершения
bool stopAndWait(PISystemTime timeout = {}); bool stopAndWait(PISystemTime timeout = {});
//! Returns if keyboard listening is active (not running!) //! Returns if keyboard listening is active (not running!)

View File

@@ -1,9 +1,11 @@
/*! \file piscreen.h //! \file piscreen.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Console tiling manager //! \~english Console tiling manager
* \~russian Консольный тайловый менеджер //! \~russian Консольный тайловый менеджер
*/ //! \details
//! \~english Main console screen manager providing tile-based UI rendering and keyboard input.
//! \~russian Основной менеджер консольного экрана, обеспечивающий отрисовку UI на основе тайлов и ввод с клавиатуры.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Console GUI Console GUI
@@ -31,6 +33,9 @@
#include "piscreentile.h" #include "piscreentile.h"
//! \brief
//! \~english Console tiling manager
//! \~russian Консольный тайловый менеджер
class PIP_CONSOLE_EXPORT PIScreen class PIP_CONSOLE_EXPORT PIScreen
: public PIThread : public PIThread
, public PIScreenTypes::PIScreenBase { , public PIScreenTypes::PIScreenBase {
@@ -38,46 +43,126 @@ class PIP_CONSOLE_EXPORT PIScreen
class SystemConsole; class SystemConsole;
public: public:
//! Constructs %PIScreen with key handler "slot" and if "startNow" start it //! \brief
//! \~english Constructs PIScreen
//! \~russian Создает PIScreen
//! \param startNow Start immediately / Запустить немедленно
//! \param slot Keyboard handler function / Обработчик клавиатуры
PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0); PIScreen(bool startNow = true, PIKbdListener::KBFunc slot = 0);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
~PIScreen(); ~PIScreen();
//! Directly call function from \a PIKbdListener //! \brief
//! \~english Enables exit capture with key
//! \~russian Включает захват выхода по клавише
void enableExitCapture(int key = 'Q') { listener->enableExitCapture(key); } void enableExitCapture(int key = 'Q') { listener->enableExitCapture(key); }
//! Directly call function from \a PIKbdListener //! \brief
//! \~english Disables exit capture
//! \~russian Отключает захват выхода
void disableExitCapture() { listener->disableExitCapture(); } void disableExitCapture() { listener->disableExitCapture(); }
//! Directly call function from \a PIKbdListener //! \brief
//! \~english Checks if exit is captured
//! \~russian Проверяет, захвачен ли выход
bool exitCaptured() const { return listener->exitCaptured(); } bool exitCaptured() const { return listener->exitCaptured(); }
//! Directly call function from \a PIKbdListener //! \brief
//! \~english Returns exit key
//! \~russian Возвращает клавишу выхода
int exitKey() const { return listener->exitKey(); } int exitKey() const { return listener->exitKey(); }
//! \brief
//! \~english Returns window width
//! \~russian Возвращает ширину окна
int windowWidth() const { return console.width; } int windowWidth() const { return console.width; }
//! \brief
//! \~english Returns window height
//! \~russian Возвращает высоту окна
int windowHeight() const { return console.height; } int windowHeight() const { return console.height; }
//! \brief
//! \~english Checks if mouse is enabled
//! \~russian Проверяет, включена ли мышь
bool isMouseEnabled() const { return mouse_; } bool isMouseEnabled() const { return mouse_; }
//! \brief
//! \~english Sets mouse enabled state
//! \~russian Устанавливает состояние мыши
void setMouseEnabled(bool on); void setMouseEnabled(bool on);
//! \brief
//! \~english Returns root tile
//! \~russian Возвращает корневой тайл
PIScreenTile * rootTile() { return &root; } PIScreenTile * rootTile() { return &root; }
//! \brief
//! \~english Finds tile by name
//! \~russian Находит тайл по имени
PIScreenTile * tileByName(const PIString & name); PIScreenTile * tileByName(const PIString & name);
//! \brief
//! \~english Sets dialog tile
//! \~russian Устанавливает диалоговый тайл
void setDialogTile(PIScreenTile * t); void setDialogTile(PIScreenTile * t);
//! \brief
//! \~english Returns current dialog tile
//! \~russian Возвращает текущий диалоговый тайл
PIScreenTile * dialogTile() const { return tile_dialog; } PIScreenTile * dialogTile() const { return tile_dialog; }
//! \brief
//! \~english Returns screen drawer
//! \~russian Возвращает отрисовщик экрана
PIScreenDrawer * drawer() { return &drawer_; } PIScreenDrawer * drawer() { return &drawer_; }
//! \brief
//! \~english Clears the screen
//! \~russian Очищает экран
void clear() { drawer_.clear(); } void clear() { drawer_.clear(); }
//! \brief
//! \~english Resizes screen
//! \~russian Изменяет размер экрана
void resize(int w, int h) { console.resize(w, h); } void resize(int w, int h) { console.resize(w, h); }
//! \brief
//! \~english Waits for finish
//! \~russian Ожидает завершения
EVENT_HANDLER0(void, waitForFinish); EVENT_HANDLER0(void, waitForFinish);
//! \brief
//! \~english Starts screen
//! \~russian Запускает экран
EVENT_HANDLER0(void, start) { start(false); } EVENT_HANDLER0(void, start) { start(false); }
//! \brief
//! \~english Starts screen
//! \~russian Запускает экран
EVENT_HANDLER1(void, start, bool, wait); EVENT_HANDLER1(void, start, bool, wait);
//! \brief
//! \~english Stops screen
//! \~russian Останавливает экран
EVENT_HANDLER0(void, stop) { stop(false); } EVENT_HANDLER0(void, stop) { stop(false); }
//! \brief
//! \~english Stops screen
//! \~russian Останавливает экран
EVENT_HANDLER1(void, stop, bool, clear); EVENT_HANDLER1(void, stop, bool, clear);
//! \brief
//! \~english Raised on key pressed
//! \~russian Вызывается при нажатии клавиши
EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data); EVENT2(keyPressed, PIKbdListener::KeyEvent, key, void *, data);
//! \brief
//! \~english Raised on tile event
//! \~russian Вызывается при событии тайла
EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e); EVENT2(tileEvent, PIScreenTile *, tile, PIScreenTypes::TileEvent, e);
//! \handlers //! \handlers

View File

@@ -1,9 +1,11 @@
/*! \file piscreenconsole.h //! \file piscreenconsole.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Tile for PIScreen with PIConsole API //! \~english Tile for PIScreen with PIConsole API
* \~russian Тайл для PIScreen с API PIConsole //! \~russian Тайл для PIScreen с API PIConsole
*/ //! \details
//! \~english Provides tiles for displaying variable data and console-like content.
//! \~russian Обеспечивает тайлы для отображения данных переменных и консольного контента.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Tile for PIScreen with PIConsole API Tile for PIScreen with PIConsole API
@@ -32,17 +34,36 @@
/// NOTE: incomplete class /// NOTE: incomplete class
/// TODO: write TileVars /// TODO: write TileVars
//! \brief
//! \~english Tile for displaying variable data
//! \~russian Тайл для отображения данных переменных
//! \addtogroup Console
//! \{
//! \brief
//! \~english Tile for displaying variable data
//! \~russian Тайл для отображения данных переменных
class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile { class PIP_CONSOLE_EXPORT TileVars: public PIScreenTile {
public: public:
TileVars(const PIString & n = PIString()); //! \brief
//! \~english Constructs TileVars
//! \~russian Создает TileVars
//! \param n Tile name / Имя тайла
explicit TileVars(const PIString & n = PIString());
protected: protected:
//! \brief Variable data structure
struct PIP_CONSOLE_EXPORT Variable { struct PIP_CONSOLE_EXPORT Variable {
Variable() { Variable() {
nx = ny = type = offset = bitFrom = bitCount = size = 0; nx = ny = type = offset = bitFrom = bitCount = size = 0;
format = PIScreenTypes::CellFormat(); format = PIScreenTypes::CellFormat();
ptr = 0; ptr = 0;
} }
//! \brief
//! \~english Checks if variable is empty
//! \~russian Проверяет, пустая ли переменная
bool isEmpty() const { return (ptr == 0); } bool isEmpty() const { return (ptr == 0); }
PIString name; PIString name;
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
@@ -67,16 +88,38 @@ protected:
ptr = src.ptr; ptr = src.ptr;
}*/ }*/
}; };
//! \brief
//! \~english Returns variables
//! \~russian Возвращает переменные
PIVector<Variable> variables; PIVector<Variable> variables;
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
}; };
//! \brief
//! \~english Console-style tile for PIScreen
//! \~russian Консольный тайл для PIScreen
//! \brief
//! \~english Console-style tile for PIScreen
//! \~russian Консольный тайл для PIScreen
class PIP_CONSOLE_EXPORT PIScreenConsoleTile: public PIScreenTile { class PIP_CONSOLE_EXPORT PIScreenConsoleTile: public PIScreenTile {
public: public:
PIScreenConsoleTile(); //! \brief
//! \~english Constructs PIScreenConsoleTile
//! \~russian Создает PIScreenConsoleTile
explicit PIScreenConsoleTile();
}; };
#endif // PISCREENCONSOLE_H #endif // PISCREENCONSOLE_H

View File

@@ -1,9 +1,11 @@
/*! \file piscreendrawer.h //! \file piscreendrawer.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Drawer for PIScreen //! \~english Drawer for PIScreen
* \~russian Отрисовщик для PIScreen //! \~russian Отрисовщик для PIScreen
*/ //! \details
//! \~english Provides drawing primitives for console screen rendering.
//! \~russian Обеспечивает примитивы отрисовки для рендеринга консольного экрана.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Drawer for PIScreen Drawer for PIScreen
@@ -30,31 +32,54 @@
#include "piscreentypes.h" #include "piscreentypes.h"
#include "pistring.h" #include "pistring.h"
//! \brief Screen drawer for console rendering
//! \~english Console screen drawer for rendering graphics
//! \~russian Отрисовщик консольного экрана для рендеринга графики
//! \brief
//! \~english Console screen drawer for rendering graphics
//! \~russian Отрисовщик консольного экрана для рендеринга графики
class PIP_CONSOLE_EXPORT PIScreenDrawer { class PIP_CONSOLE_EXPORT PIScreenDrawer {
friend class PIScreen; friend class PIScreen;
PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell>> & c); PIScreenDrawer(PIVector<PIVector<PIScreenTypes::Cell>> & c);
public: public:
//! \brief ASCII art characters
enum ArtChar { enum ArtChar {
LineVertical = 1, LineVertical = 1, //!< Vertical line / Вертикальная линия
LineHorizontal, LineHorizontal, //!< Horizontal line / Горизонтальная линия
Cross, Cross, //!< Cross / Крест
CornerTopLeft, CornerTopLeft, //!< Top-left corner / Угол сверху-слева
CornerTopRight, CornerTopRight, //!< Top-right corner / Угол сверху-справа
CornerBottomLeft, CornerBottomLeft, //!< Bottom-left corner / Угол снизу-слева
CornerBottomRight, CornerBottomRight, //!< Bottom-right corner / Угол снизу-справа
Unchecked, Unchecked, //!< Unchecked box / Неотмеченная клетка
Checked Checked //!< Checked box / Отмеченная клетка
}; };
//! \brief
//! \~english Clears the screen
//! \~russian Очищает экран
void clear(); void clear();
//! \brief
//! \~english Clears rectangle
//! \~russian Очищает прямоугольник
void clearRect(int x0, int y0, int x1, int y1) { fillRect(x0, y0, x1, y1, ' '); } void clearRect(int x0, int y0, int x1, int y1) { fillRect(x0, y0, x1, y1, ' '); }
//! \brief
//! \~english Draws pixel
//! \~russian Рисует пиксель
void drawPixel(int x, void drawPixel(int x,
int y, int y,
const PIChar & c, const PIChar & c,
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Draws line
//! \~russian Рисует линию
void drawLine(int x0, void drawLine(int x0,
int y0, int y0,
int x1, int x1,
@@ -63,6 +88,10 @@ public:
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Draws rectangle
//! \~russian Рисует прямоугольник
void drawRect(int x0, void drawRect(int x0,
int y0, int y0,
int x1, int x1,
@@ -71,6 +100,10 @@ public:
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Draws frame
//! \~russian Рисует рамку
void drawFrame(int x0, void drawFrame(int x0,
int y0, int y0,
int x1, int x1,
@@ -78,12 +111,20 @@ public:
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Draws text
//! \~russian Рисует текст
void drawText(int x, void drawText(int x,
int y, int y,
const PIString & s, const PIString & s,
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Transparent, PIScreenTypes::Color col_back = PIScreenTypes::Transparent,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Fills rectangle
//! \~russian Заполняет прямоугольник
void fillRect(int x0, void fillRect(int x0,
int y0, int y0,
int x1, int x1,
@@ -92,10 +133,20 @@ public:
PIScreenTypes::Color col_char = PIScreenTypes::Default, PIScreenTypes::Color col_char = PIScreenTypes::Default,
PIScreenTypes::Color col_back = PIScreenTypes::Default, PIScreenTypes::Color col_back = PIScreenTypes::Default,
PIScreenTypes::CharFlags flags_char = 0); PIScreenTypes::CharFlags flags_char = 0);
//! \brief
//! \~english Fills rectangle with content
//! \~russian Заполняет прямоугольник содержимым
void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell>> & content); void fillRect(int x0, int y0, int x1, int y1, PIVector<PIVector<PIScreenTypes::Cell>> & content);
//! \brief
//! \~english Returns art character by type
//! \~russian Возвращает символ искусства по типу
PIChar artChar(const ArtChar type) const { return arts_.value(type, PIChar(' ')); } PIChar artChar(const ArtChar type) const { return arts_.value(type, PIChar(' ')); }
//! \brief
//! \~english Clears cell matrix
//! \~russian Очищает матрицу ячеек
static void clear(PIVector<PIVector<PIScreenTypes::Cell>> & cells); static void clear(PIVector<PIVector<PIScreenTypes::Cell>> & cells);
private: private:

View File

@@ -1,9 +1,11 @@
/*! \file piscreentile.h //! \file piscreentile.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Basic PIScreen tile //! \~english Basic PIScreen tile
* \~russian Базовый тайл для PIScreen //! \~russian Базовый тайл для PIScreen
*/ //! \details
//! \~english Base class for all screen tiles providing layout and event handling.
//! \~russian Базовый класс для всех экранных тайлов, обеспечивающий компоновку и обработку событий.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Basic PIScreen tile Basic PIScreen tile
@@ -32,27 +34,92 @@
class PIScreenDrawer; class PIScreenDrawer;
//! \brief
//! \~english Base tile class for console screen
//! \~russian Базовый класс тайла для консольного экрана
//! \brief
//! \~english Base tile class for console screen
//! \~russian Базовый класс тайла для консольного экрана
class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject { class PIP_CONSOLE_EXPORT PIScreenTile: public PIObject {
friend class PIScreen; friend class PIScreen;
PIOBJECT_SUBCLASS(PIScreenTile, PIObject); PIOBJECT_SUBCLASS(PIScreenTile, PIObject);
public: public:
//! \brief
//! \~english Constructs PIScreenTile
//! \~russian Создает PIScreenTile
//! \param n Tile name / Имя тайла
//! \param d Layout direction / Направление компоновки
//! \param p Size policy / Политика размера
PIScreenTile(const PIString & n = PIString(), PIScreenTile(const PIString & n = PIString(),
PIScreenTypes::Direction d = PIScreenTypes::Vertical, PIScreenTypes::Direction d = PIScreenTypes::Vertical,
PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred); PIScreenTypes::SizePolicy p = PIScreenTypes::Preferred);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIScreenTile(); virtual ~PIScreenTile();
//! \brief
//! \~english Adds child tile
//! \~russian Добавляет дочерний тайл
void addTile(PIScreenTile * t); void addTile(PIScreenTile * t);
//! \brief
//! \~english Takes ownership of tile
//! \~russian Забирает владение тайла
void takeTile(PIScreenTile * t); void takeTile(PIScreenTile * t);
//! \brief
//! \~english Removes child tile
//! \~russian Удаляет дочерний тайл
void removeTile(PIScreenTile * t); void removeTile(PIScreenTile * t);
//! \brief
//! \~english Returns parent tile
//! \~russian Возвращает родительский тайл
PIScreenTile * parentTile() const { return parent; } PIScreenTile * parentTile() const { return parent; }
//! \brief
//! \~english Returns child tiles
//! \~russian Возвращает дочерние тайлы
//! \param only_visible Only visible tiles / Только видимые тайлы
PIVector<PIScreenTile *> children(bool only_visible = false); PIVector<PIScreenTile *> children(bool only_visible = false);
//! \brief
//! \~english Returns child under mouse position
//! \~russian Возвращает тайл под мышью
PIScreenTile * childUnderMouse(int x, int y); PIScreenTile * childUnderMouse(int x, int y);
//! \brief
//! \~english Shows tile
//! \~russian Показывает тайл
void show() { visible = true; } void show() { visible = true; }
//! \brief
//! \~english Hides tile
//! \~russian Скрывает тайл
void hide() { visible = false; } void hide() { visible = false; }
//! \brief
//! \~english Sets focus to this tile
//! \~russian Устанавливает фокус на этот тайл
void setFocus(); void setFocus();
//! \brief
//! \~english Checks if tile has focus
//! \~russian Проверяет, имеет ли тайл фокус
bool hasFocus() const { return has_focus; } bool hasFocus() const { return has_focus; }
//! \brief
//! \~english Sets all margins
//! \~russian Устанавливает все отступы
void setMargins(int m) { marginLeft = marginRight = marginTop = marginBottom = m; } void setMargins(int m) { marginLeft = marginRight = marginTop = marginBottom = m; }
//! \brief
//! \~english Sets individual margins
//! \~russian Устанавливает отдельные отступы
void setMargins(int l, int r, int t, int b) { void setMargins(int l, int r, int t, int b) {
marginLeft = l; marginLeft = l;
marginRight = r; marginRight = r;
@@ -60,9 +127,24 @@ public:
marginBottom = b; marginBottom = b;
} }
//! \brief
//! \~english Returns tile X position
//! \~russian Возвращает позицию X тайла
int x() const { return x_; } int x() const { return x_; }
//! \brief
//! \~english Returns tile Y position
//! \~russian Возвращает позицию Y тайла
int y() const { return y_; } int y() const { return y_; }
//! \brief
//! \~english Returns tile width
//! \~russian Возвращает ширину тайла
int width() const { return width_; } int width() const { return width_; }
//! \brief
//! \~english Returns tile height
//! \~russian Возвращает высоту тайла
int height() const { return height_; } int height() const { return height_; }
PIScreenTypes::Direction direction; PIScreenTypes::Direction direction;
@@ -77,29 +159,64 @@ public:
bool visible; bool visible;
protected: protected:
//! Returns desired tile size in "w" and "h" //! \brief
//! \~english Returns desired tile size in "w" and "h"
//! \~russian Возвращает желаемый размер тайла в "w" и "h"
virtual void sizeHint(int & w, int & h) const; virtual void sizeHint(int & w, int & h) const;
//! Tile has been resized to "w"x"h" //! \brief
//! \~english Tile has been resized to "w"x"h"
//! \~russian Тайл был изменен на "w"x"h"
virtual void resizeEvent(int w, int h) {} virtual void resizeEvent(int w, int h) {}
//! Draw tile with drawer "d" in world-space coordinates //! \brief
//! \~english Draw tile with drawer "d" in world-space coordinates
//! \~russian Рисует тайл отрисовщиком "d" в мировых координатах
virtual void drawEvent(PIScreenDrawer * d) {} virtual void drawEvent(PIScreenDrawer * d) {}
//! Return "true" if you process key //! \brief
//! \~english Return "true" if you process key
//! \~russian Возвращает "true" если вы обрабатываете клавишу
virtual bool keyEvent(PIKbdListener::KeyEvent key) { return false; } virtual bool keyEvent(PIKbdListener::KeyEvent key) { return false; }
//! Return "true" if you process event //! \brief
//! \~english Return "true" if you process event
//! \~russian Возвращает "true" если вы обрабатываете событие
virtual bool mouseEvent(PIKbdListener::MouseEvent me) { return false; } virtual bool mouseEvent(PIKbdListener::MouseEvent me) { return false; }
//! Return "true" if you process wheel //! \brief
//! \~english Return "true" if you process wheel
//! \~russian Возвращает "true" если вы обрабатываете колесо
virtual bool wheelEvent(PIKbdListener::WheelEvent we) { return false; } virtual bool wheelEvent(PIKbdListener::WheelEvent we) { return false; }
//! \brief
//! \~english Raises tile event
//! \~russian Вызывает событие тайла
void raiseEvent(PIScreenTypes::TileEvent e); void raiseEvent(PIScreenTypes::TileEvent e);
//! \brief
//! \~english Sets screen reference
//! \~russian Устанавливает ссылку на экран
void setScreen(PIScreenTypes::PIScreenBase * s); void setScreen(PIScreenTypes::PIScreenBase * s);
//! \brief
//! \~english Deletes all children
//! \~russian Удаляет всех потомков
void deleteChildren(); void deleteChildren();
//! \brief
//! \~english Internal draw event
//! \~russian Внутреннее событие отрисовки
void drawEventInternal(PIScreenDrawer * d); void drawEventInternal(PIScreenDrawer * d);
//! \brief
//! \~english Performs layout
//! \~russian Выполняет компоновку
void layout(); void layout();
//! \brief
//! \~english Checks if layout is needed
//! \~russian Проверяет, нужна ли компоновка
bool needLayout() { return size_policy != PIScreenTypes::Ignore; } bool needLayout() { return size_policy != PIScreenTypes::Ignore; }
PIVector<PIScreenTile *> tiles; PIVector<PIScreenTile *> tiles;

View File

@@ -1,9 +1,11 @@
/*! \file piscreentiles.h //! \file piscreentiles.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Various tiles for PIScreen //! \~english Various tiles for PIScreen
* \~russian Различные тайлы для PIScreen //! \~russian Различные тайлы для PIScreen
*/ //! \details
//! \~english Provides ready-to-use tile implementations for common UI elements.
//! \~russian Обеспечивает готовые к использованию реализации тайлов для общих элементов UI.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Various tiles for PIScreen Various tiles for PIScreen
@@ -30,125 +32,326 @@
#include "piscreentile.h" #include "piscreentile.h"
//! \brief
//! \~english Tile for displaying simple text content
//! \~russian Тайл для отображения простого текстового контента
class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile { class PIP_CONSOLE_EXPORT TileSimple: public PIScreenTile {
PIOBJECT_SUBCLASS(TileSimple, PIScreenTile); PIOBJECT_SUBCLASS(TileSimple, PIScreenTile);
public: public:
//! \brief Row type
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
//! \brief
//! \~english Constructs TileSimple
//! \~russian Создает TileSimple
//! \param n Tile name / Имя тайла
TileSimple(const PIString & n = PIString()); TileSimple(const PIString & n = PIString());
//! \brief
//! \~english Constructs TileSimple with row
//! \~russian Создает TileSimple со строкой
//! \param r Row content / Содержимое строки
TileSimple(const Row & r); TileSimple(const Row & r);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileSimple() {} virtual ~TileSimple() {}
//! \brief Tile content rows
PIVector<Row> content; PIVector<Row> content;
//! \brief Text alignment
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
}; };
class TileList; class TileList;
//! \brief
//! \~english Scrollbar for list containers
//! \~russian Полоса прокрутки для списков
class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile { class PIP_CONSOLE_EXPORT TileScrollBar: public PIScreenTile {
PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile); PIOBJECT_SUBCLASS(TileScrollBar, PIScreenTile);
friend class TileList; friend class TileList;
public: public:
//! \brief
//! \~english Constructs TileScrollBar
//! \~russian Создает TileScrollBar
//! \param n Tile name / Имя тайла
TileScrollBar(const PIString & n = PIString()); TileScrollBar(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileScrollBar() {} virtual ~TileScrollBar() {}
//! \brief
//! \~english Sets minimum value
//! \~russian Устанавливает минимальное значение
void setMinimum(int v); void setMinimum(int v);
//! \brief
//! \~english Sets maximum value
//! \~russian Устанавливает максимальное значение
void setMaximum(int v); void setMaximum(int v);
//! \brief
//! \~english Sets current value
//! \~russian Устанавливает текущее значение
void setValue(int v); void setValue(int v);
//! \brief
//! \~english Returns minimum value
//! \~russian Возвращает минимальное значение
int minimum() const { return minimum_; } int minimum() const { return minimum_; }
//! \brief
//! \~english Returns maximum value
//! \~russian Возвращает максимальное значение
int maximum() const { return maximum_; } int maximum() const { return maximum_; }
//! \brief
//! \~english Returns current value
//! \~russian Возвращает текущее значение
int value() const { return value_; } int value() const { return value_; }
//! \brief Scrollbar thickness
int thickness; int thickness;
protected: protected:
//! \brief Validates scrollbar state
//! \~english Validates scrollbar state
//! \~russian Проверяет состояние полосы прокрутки
void _check(); void _check();
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
int minimum_, maximum_, value_; int minimum_, maximum_, value_;
PIChar line_char; PIChar line_char;
}; };
//! \brief
//! \~english Scrollable list tile
//! \~russian Прокручиваемый список
class PIP_CONSOLE_EXPORT TileList: public PIScreenTile { class PIP_CONSOLE_EXPORT TileList: public PIScreenTile {
PIOBJECT_SUBCLASS(TileList, PIScreenTile); PIOBJECT_SUBCLASS(TileList, PIScreenTile);
public: public:
//! \brief Selection mode
enum SelectionMode { enum SelectionMode {
NoSelection, NoSelection, //!< No selection / Без выделения
SingleSelection, SingleSelection, //!< Single item selection / Выделение одного элемента
MultiSelection MultiSelection //!< Multiple items selection / Выделение нескольких элементов
};
enum EventType {
SelectionChanged,
RowPressed
}; };
//! \brief Event type
enum EventType {
SelectionChanged, //!< Selection changed / Выделение изменено
RowPressed //!< Row pressed / Строка нажата
};
//! \brief
//! \~english Constructs TileList
//! \~russian Создает TileList
//! \param n Tile name / Имя тайла
//! \param sm Selection mode / Режим выделения
TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection); TileList(const PIString & n = PIString(), SelectionMode sm = NoSelection);
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileList() {} virtual ~TileList() {}
//! \brief Row type
typedef PIPair<PIString, PIScreenTypes::CellFormat> Row; typedef PIPair<PIString, PIScreenTypes::CellFormat> Row;
//! \brief List content
PIDeque<Row> content; PIDeque<Row> content;
//! \brief Text alignment
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
//! \brief Selection mode
SelectionMode selection_mode; SelectionMode selection_mode;
//! \brief Selected indices
PISet<int> selected; PISet<int> selected;
//! \brief Line height
int lhei, cur, offset; int lhei, cur, offset;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Called when resized
//! \~russian Вызывается при изменении размера
void resizeEvent(int w, int h) override; void resizeEvent(int w, int h) override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
//! \brief
//! \~english Handles wheel events
//! \~russian Обрабатывает события колеса
bool wheelEvent(PIKbdListener::WheelEvent we) override; bool wheelEvent(PIKbdListener::WheelEvent we) override;
TileScrollBar * scroll; TileScrollBar * scroll;
bool mouse_sel; bool mouse_sel;
}; };
//! \brief
//! \~english Clickable button tile
//! \~russian Кликабельная кнопка
class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile { class PIP_CONSOLE_EXPORT TileButton: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButton, PIScreenTile); PIOBJECT_SUBCLASS(TileButton, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileButton
//! \~russian Создает TileButton
//! \param n Tile name / Имя тайла
TileButton(const PIString & n = PIString()); TileButton(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileButton() {} virtual ~TileButton() {}
//! \brief Event type
enum EventType { enum EventType {
ButtonClicked ButtonClicked //!< Button clicked / Кнопка нажата
}; };
//! \brief Button format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Button text
PIString text; PIString text;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
}; };
//! \brief
//! \~english Group of buttons with selection
//! \~russian Группа кнопок с выбором
class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile { class PIP_CONSOLE_EXPORT TileButtons: public PIScreenTile {
PIOBJECT_SUBCLASS(TileButtons, PIScreenTile); PIOBJECT_SUBCLASS(TileButtons, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileButtons
//! \~russian Создает TileButtons
//! \param n Tile name / Имя тайла
TileButtons(const PIString & n = PIString()); TileButtons(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileButtons() {} virtual ~TileButtons() {}
//! \brief Event type
enum EventType { enum EventType {
ButtonSelected ButtonSelected //!< Button selected / Кнопка выбрана
}; };
//! \brief Button type
typedef PIPair<PIString, PIScreenTypes::CellFormat> Button; typedef PIPair<PIString, PIScreenTypes::CellFormat> Button;
//! \brief Button alignment
PIScreenTypes::Alignment alignment; PIScreenTypes::Alignment alignment;
//! \brief Button content
PIVector<Button> content; PIVector<Button> content;
//! \brief Current selection
int cur; int cur;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
//! \brief Button rectangle
struct Rect { struct Rect {
Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0), y0(_y0), x1(_x1), y1(_y1) {} Rect(int _x0 = 0, int _y0 = 0, int _x1 = 0, int _y1 = 0): x0(_x0), y0(_y0), x1(_x1), y1(_y1) {}
int x0, y0, x1, y1; int x0, y0, x1, y1;
@@ -157,74 +360,198 @@ protected:
}; };
//! \brief
//! \~english Checkbox with toggle state
//! \~russian Флажок с переключаемым состоянием
class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile { class PIP_CONSOLE_EXPORT TileCheck: public PIScreenTile {
PIOBJECT_SUBCLASS(TileCheck, PIScreenTile); PIOBJECT_SUBCLASS(TileCheck, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileCheck
//! \~russian Создает TileCheck
//! \param n Tile name / Имя тайла
TileCheck(const PIString & n = PIString()); TileCheck(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileCheck() {} virtual ~TileCheck() {}
//! \brief Event type
enum EventType { enum EventType {
Toggled Toggled //!< State toggled / Состояние переключено
}; };
//! \brief Checkbox format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Checkbox text
PIString text; PIString text;
//! \brief Checkbox state
bool toggled; bool toggled;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Handles mouse events
//! \~russian Обрабатывает события мыши
bool mouseEvent(PIKbdListener::MouseEvent me) override; bool mouseEvent(PIKbdListener::MouseEvent me) override;
}; };
//! \brief
//! \~english Progress bar for displaying progress
//! \~russian Индикатор прогресса
class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile { class PIP_CONSOLE_EXPORT TileProgress: public PIScreenTile {
PIOBJECT_SUBCLASS(TileProgress, PIScreenTile); PIOBJECT_SUBCLASS(TileProgress, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileProgress
//! \~russian Создает TileProgress
//! \param n Tile name / Имя тайла
TileProgress(const PIString & n = PIString()); TileProgress(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileProgress() {} virtual ~TileProgress() {}
//! \brief Progress format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Prefix text
PIString prefix; PIString prefix;
//! \brief Suffix text
PIString suffix; PIString suffix;
//! \brief Maximum value
double maximum; double maximum;
//! \brief Current value
double value; double value;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
}; };
//! \brief
//! \~english Tile for displaying console output
//! \~russian Тайл для отображения консольного вывода
//! \brief
//! \~english Tile for displaying console output
//! \~russian Тайл для отображения консольного вывода
class PIP_CONSOLE_EXPORT TilePICout: public TileList { class PIP_CONSOLE_EXPORT TilePICout: public TileList {
PIOBJECT_SUBCLASS(TilePICout, PIScreenTile); PIOBJECT_SUBCLASS(TilePICout, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TilePICout
//! \~russian Создает TilePICout
//! \param n Tile name / Имя тайла
TilePICout(const PIString & n = PIString()); TilePICout(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TilePICout() {} virtual ~TilePICout() {}
//! \brief Output format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Maximum lines
int max_lines; int max_lines;
protected: protected:
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
}; };
//! \brief
//! \~english Text input tile
//! \~russian Тайл текстового ввода
//! \brief
//! \~english Text input tile
//! \~russian Тайл текстового ввода
class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile { class PIP_CONSOLE_EXPORT TileInput: public PIScreenTile {
PIOBJECT_SUBCLASS(TileInput, PIScreenTile); PIOBJECT_SUBCLASS(TileInput, PIScreenTile);
public: public:
//! \brief
//! \~english Constructs TileInput
//! \~russian Создает TileInput
//! \param n Tile name / Имя тайла
TileInput(const PIString & n = PIString()); TileInput(const PIString & n = PIString());
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~TileInput() {} virtual ~TileInput() {}
//! \brief Input format
PIScreenTypes::CellFormat format; PIScreenTypes::CellFormat format;
//! \brief Input text
PIString text; PIString text;
//! \brief Maximum text length
int max_length; int max_length;
protected: protected:
//! \brief
//! \~english Calculates tile size hint
//! \~russian Вычисляет рекомендуемый размер тайла
void sizeHint(int & w, int & h) const override; void sizeHint(int & w, int & h) const override;
//! \brief
//! \~english Draws tile content
//! \~russian Рисует содержимое тайла
void drawEvent(PIScreenDrawer * d) override; void drawEvent(PIScreenDrawer * d) override;
//! \brief
//! \~english Handles key events
//! \~russian Обрабатывает события клавиатуры
bool keyEvent(PIKbdListener::KeyEvent key) override; bool keyEvent(PIKbdListener::KeyEvent key) override;
//! \brief
//! \~english Resets cursor position
//! \~russian Сбрасывает позицию курсора
void reserCursor(); void reserCursor();
int cur, offset; int cur, offset;
bool inv; bool inv;

View File

@@ -1,9 +1,11 @@
/*! \file piscreentypes.h //! \file piscreentypes.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Types for PIScreen //! \~english Types for PIScreen
* \~russian Типы для PIScreen //! \~russian Типы для PIScreen
*/ //! \details
//! \~english Provides common types used by screen tiles and drawer.
//! \~russian Обеспечивает общие типы, используемые тайлами и отрисовщиком экрана.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Types for PIScreen Types for PIScreen
@@ -34,7 +36,9 @@ class PIScreenTile;
namespace PIScreenTypes { namespace PIScreenTypes {
//! Color for chars or background //! \brief Color for chars or background
//! \~english Console color values
//! \~russian Значения цветов консоли
enum Color { enum Color {
Default /** Default */, Default /** Default */,
Black /** Black */, Black /** Black */,
@@ -48,7 +52,9 @@ enum Color {
Transparent /** Save previous color */ Transparent /** Save previous color */
}; };
//! Flags for chars //! \brief Flags for chars
//! \~english Character formatting flags
//! \~russian Флаги форматирования символов
enum CharFlag { enum CharFlag {
Bold /** Bold or bright */ = 0x1, Bold /** Bold or bright */ = 0x1,
Blink /** Blink text */ = 0x2, Blink /** Blink text */ = 0x2,
@@ -56,14 +62,18 @@ enum CharFlag {
Inverse = 0x08 Inverse = 0x08
}; };
//! Alignment //! \brief Alignment
//! \~english Text alignment modes
//! \~russian Режимы выравнивания текста
enum Alignment { enum Alignment {
Left /** Left */, Left /** Left */,
Center /** Center */, Center /** Center */,
Right /** Right */ Right /** Right */
}; };
//! Size policy //! \brief Size policy
//! \~english Tile sizing policies
//! \~russian Политики размеров тайлов
enum SizePolicy { enum SizePolicy {
Fixed /** Fixed size */, Fixed /** Fixed size */,
Preferred /** Preferred size */, Preferred /** Preferred size */,
@@ -71,13 +81,17 @@ enum SizePolicy {
Ignore /** Ignore layout logic */ Ignore /** Ignore layout logic */
}; };
//! Direction //! \brief Direction
//! \~english Layout directions
//! \~russian Направления компоновки
enum Direction { enum Direction {
Horizontal /** Horizontal */, Horizontal /** Horizontal */,
Vertical /** Vertical */ Vertical /** Vertical */
}; };
//! Focus flags //! \brief Focus flags
//! \~english Tile focus behavior flags
//! \~russian Флаги поведения фокуса тайла
enum FocusFlag { enum FocusFlag {
CanHasFocus /** Tile can has focus */ = 0x1, CanHasFocus /** Tile can has focus */ = 0x1,
NextByTab /** Focus passed to next tile by tab key */ = 0x2, NextByTab /** Focus passed to next tile by tab key */ = 0x2,
@@ -92,8 +106,19 @@ enum FocusFlag {
typedef PIFlags<CharFlag> CharFlags; typedef PIFlags<CharFlag> CharFlags;
typedef PIFlags<FocusFlag> FocusFlags; typedef PIFlags<FocusFlag> FocusFlags;
//! \brief Cell format union
//! \~english Packed cell formatting data
//! \~russian Упакованные данные форматирования ячейки
union PIP_CONSOLE_EXPORT CellFormat { union PIP_CONSOLE_EXPORT CellFormat {
//! \brief
//! \~english Constructs CellFormat from raw value
//! \~russian Создает CellFormat из сырого значения
CellFormat(ushort f = 0) { raw_format = f; } CellFormat(ushort f = 0) { raw_format = f; }
//! \brief
//! \~english Constructs CellFormat from color and flags
//! \~russian Создает CellFormat из цвета и флагов
CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) { CellFormat(Color col_char, Color col_back = Default, CharFlags flags_ = 0) {
color_char = col_char; color_char = col_char;
color_back = col_back; color_back = col_back;
@@ -105,19 +130,49 @@ union PIP_CONSOLE_EXPORT CellFormat {
ushort color_back: 4; ushort color_back: 4;
ushort flags : 8; ushort flags : 8;
}; };
//! \brief
//! \~english Equality operator
//! \~russian Оператор равенства
bool operator==(const CellFormat & c) const { return raw_format == c.raw_format; } bool operator==(const CellFormat & c) const { return raw_format == c.raw_format; }
//! \brief
//! \~english Inequality operator
//! \~russian Оператор неравенства
bool operator!=(const CellFormat & c) const { return raw_format != c.raw_format; } bool operator!=(const CellFormat & c) const { return raw_format != c.raw_format; }
}; };
//! \brief Screen cell
//! \~english Single character cell with formatting
//! \~russian Одна символьная ячейка с форматированием
struct PIP_CONSOLE_EXPORT Cell { struct PIP_CONSOLE_EXPORT Cell {
//! \brief
//! \~english Constructs Cell
//! \~russian Создает Cell
Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) { Cell(PIChar c = PIChar(' '), CellFormat f = CellFormat()) {
symbol = c; symbol = c;
format = f; format = f;
} }
//! \brief Cell format
CellFormat format; CellFormat format;
//! \brief Cell character
PIChar symbol; PIChar symbol;
//! \brief
//! \~english Equality operator
//! \~russian Оператор равенства
bool operator==(const Cell & c) const { return format == c.format && symbol == c.symbol; } bool operator==(const Cell & c) const { return format == c.format && symbol == c.symbol; }
//! \brief
//! \~english Inequality operator
//! \~russian Оператор неравенства
bool operator!=(const Cell & c) const { return format != c.format || symbol != c.symbol; } bool operator!=(const Cell & c) const { return format != c.format || symbol != c.symbol; }
//! \brief
//! \~english Assignment operator
//! \~russian Оператор присваивания
Cell & operator=(const Cell & c) { Cell & operator=(const Cell & c) {
symbol = c.symbol; symbol = c.symbol;
if (c.format.color_back == Transparent) { if (c.format.color_back == Transparent) {
@@ -129,18 +184,52 @@ struct PIP_CONSOLE_EXPORT Cell {
} }
}; };
//! \brief Tile event data
//! \~english Event data passed to tiles
//! \~russian Данные события, передаваемые тайлам
struct PIP_CONSOLE_EXPORT TileEvent { struct PIP_CONSOLE_EXPORT TileEvent {
//! \brief
//! \~english Constructs TileEvent
//! \~russian Создает TileEvent
//! \param t Event type / Тип события
//! \param d Event data / Данные события
TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {} TileEvent(int t = -1, const PIVariant & d = PIVariant()): type(t), data(d) {}
//! \brief Event type
int type; int type;
//! \brief Event data
PIVariant data; PIVariant data;
}; };
//! \brief Base screen interface
//! \~english Base interface for screen tiles
//! \~russian Базовый интерфейс для экранных тайлов
class PIP_CONSOLE_EXPORT PIScreenBase { class PIP_CONSOLE_EXPORT PIScreenBase {
public: public:
//! \brief
//! \~english Constructs PIScreenBase
//! \~russian Создает PIScreenBase
PIScreenBase() {} PIScreenBase() {}
//! \brief
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIScreenBase() {} virtual ~PIScreenBase() {}
//! \brief
//! \~english Handles internal tile event
//! \~russian Обрабатывает внутреннее событие тайла
virtual void tileEventInternal(PIScreenTile *, TileEvent) {} virtual void tileEventInternal(PIScreenTile *, TileEvent) {}
//! \brief
//! \~english Handles tile removal
//! \~russian Обрабатывает удаление тайла
virtual void tileRemovedInternal(PIScreenTile *) {} virtual void tileRemovedInternal(PIScreenTile *) {}
//! \brief
//! \~english Handles tile focus change
//! \~russian Обрабатывает изменение фокуса тайла
virtual void tileSetFocusInternal(PIScreenTile *) {} virtual void tileSetFocusInternal(PIScreenTile *) {}
}; };

View File

@@ -1,9 +1,11 @@
/*! \file piterminal.h //! \file piterminal.h
* \ingroup Console //! \ingroup Console
* \~\brief //! \brief
* \~english Virtual terminal //! \~english Virtual terminal
* \~russian Виртуальный терминал //! \~russian Виртуальный терминал
*/ //! \details
//! \~english Provides terminal emulation for reading console input and output.
//! \~russian Обеспечивает эмуляцию терминала для чтения ввода и вывода консоли.
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Virtual terminal Virtual terminal
@@ -31,26 +33,73 @@
#include "piscreentypes.h" #include "piscreentypes.h"
//! \brief
//! \~english Virtual terminal
//! \~russian Виртуальный терминал
class PIP_CONSOLE_EXPORT PITerminal: public PIThread { class PIP_CONSOLE_EXPORT PITerminal: public PIThread {
PIOBJECT_SUBCLASS(PITerminal, PIThread); PIOBJECT_SUBCLASS(PITerminal, PIThread);
public: public:
//! Constructs %PITerminal //! \brief
//! \~english Constructs PITerminal
//! \~russian Создает PITerminal
PITerminal(); PITerminal();
//! \brief
//! \~english Destructor
//! \~russian Деструктор
~PITerminal(); ~PITerminal();
//! \brief
//! \~english Returns number of columns
//! \~russian Возвращает количество колонок
int columns() const { return size_x; } int columns() const { return size_x; }
//! \brief
//! \~english Returns number of rows
//! \~russian Возвращает количество строк
int rows() const { return size_y; } int rows() const { return size_y; }
//! \brief
//! \~english Resizes terminal
//! \~russian Изменяет размер терминала
//! \param cols Number of columns / Количество колонок
//! \param rows Number of rows / Количество строк
bool resize(int cols, int rows); bool resize(int cols, int rows);
//! \brief
//! \~english Writes data to terminal
//! \~russian Записывает данные в терминал
void write(const PIByteArray & d); void write(const PIByteArray & d);
//! \brief
//! \~english Writes special key to terminal
//! \~russian Записывает специальную клавишу в терминал
void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m); void write(PIKbdListener::SpecialKey k, PIKbdListener::KeyModifiers m);
//! \brief
//! \~english Writes key event to terminal
//! \~russian Записывает событие клавиши в терминал
void write(PIKbdListener::KeyEvent ke); void write(PIKbdListener::KeyEvent ke);
//! \brief
//! \~english Returns terminal content
//! \~russian Возвращает содержимое терминала
PIVector<PIVector<PIScreenTypes::Cell>> content(); PIVector<PIVector<PIScreenTypes::Cell>> content();
//! \brief
//! \~english Checks if key is special
//! \~russian Проверяет, является ли клавиша специальной
static bool isSpecialKey(int k); static bool isSpecialKey(int k);
//! \brief
//! \~english Initializes terminal
//! \~russian Инициализирует терминал
bool initialize(); bool initialize();
//! \brief
//! \~english Destroys terminal
//! \~russian Уничтожает терминал
void destroy(); void destroy();
private: private:

View File

@@ -49,14 +49,28 @@
#include <type_traits> #include <type_traits>
//! \~english Reverse wrapper template class for iterating containers in reverse order.
//! \~russian Класс-обертка для обратного обхода контейнера через итераторы.
template<typename C> template<typename C>
class _PIReverseWrapper { class _PIReverseWrapper {
public: public:
//! \~english Constructor from non-const container reference.
//! \~russian Конструктор из неконстантной ссылки на контейнер.
_PIReverseWrapper(C & c): c_(c) {} _PIReverseWrapper(C & c): c_(c) {}
//! \~english Constructor from const container reference.
//! \~russian Конструктор из константной ссылки на контейнер.
_PIReverseWrapper(const C & c): c_(const_cast<C &>(c)) {} _PIReverseWrapper(const C & c): c_(const_cast<C &>(c)) {}
//! \~english Returns reverse iterator to the first element.
//! \~russian Возвращает обратный итератор на первый элемент.
typename C::reverse_iterator begin() { return c_.rbegin(); } typename C::reverse_iterator begin() { return c_.rbegin(); }
//! \~english Returns reverse iterator past the last element.
//! \~russian Возвращает обратный итератор за последний элемент.
typename C::reverse_iterator end() { return c_.rend(); } typename C::reverse_iterator end() { return c_.rend(); }
//! \~english Returns const reverse iterator to the first element.
//! \~russian Возвращает константный обратный итератор на первый элемент.
typename C::const_reverse_iterator begin() const { return c_.rbegin(); } typename C::const_reverse_iterator begin() const { return c_.rbegin(); }
//! \~english Returns const reverse iterator past the last element.
//! \~russian Возвращает константный обратный итератор за последний элемент.
typename C::const_reverse_iterator end() const { return c_.rend(); } typename C::const_reverse_iterator end() const { return c_.rend(); }
private: private:
@@ -64,32 +78,47 @@ private:
}; };
//! \~english Base class for container constants calculation.
//! \~russian Базовый класс для вычисления констант контейнера.
class PIP_EXPORT _PIContainerConstantsBase { class PIP_EXPORT _PIContainerConstantsBase {
public: public:
//! \~english Calculate minimum elements count for power of two growth.
//! \~russian Вычисляет минимальное количество элементов для роста кратного двум.
static size_t calcMinCountPoT(size_t szof); static size_t calcMinCountPoT(size_t szof);
//! \~english Calculate maximum elements count for power of two growth.
//! \~russian Вычисляет максимальное количество элементов для роста кратного двум.
static size_t calcMaxCountForPoT(size_t szof); static size_t calcMaxCountForPoT(size_t szof);
//! \~english Calculate step size after power of two growth.
//! \~russian Вычисляет размер шага после роста кратного двум.
static size_t calcStepAfterPoT(size_t szof); static size_t calcStepAfterPoT(size_t szof);
}; };
//! \~english Template class for container constants based on element type size.
//! \~russian Шаблонный класс для констант контейнера на основе размера типа элемента.
template<typename T> template<typename T>
class _PIContainerConstants { class _PIContainerConstants {
public: public:
// minimum elements for container //! \~english Get minimum elements count for power of two growth.
//! \~russian Возвращает минимальное количество элементов для роста кратного двум.
static size_t minCountPoT() { static size_t minCountPoT() {
static const size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T)); static const size_t ret = _PIContainerConstantsBase::calcMinCountPoT(sizeof(T));
return ret; return ret;
} }
// maximum elements for 2^n growth //! \~english Get maximum elements count for power of two growth.
//! \~russian Возвращает максимальное количество элементов для роста кратного двум.
static size_t maxCountForPoT() { static size_t maxCountForPoT() {
static const size_t ret = _PIContainerConstantsBase::calcMaxCountForPoT(sizeof(T)); static const size_t ret = _PIContainerConstantsBase::calcMaxCountForPoT(sizeof(T));
return ret; return ret;
} }
// add elements after 2^n growth //! \~english Get step size after power of two growth.
//! \~russian Возвращает размер шага после роста кратного двум.
static size_t stepAfterPoT() { static size_t stepAfterPoT() {
static const size_t ret = _PIContainerConstantsBase::calcStepAfterPoT(sizeof(T)); static const size_t ret = _PIContainerConstantsBase::calcStepAfterPoT(sizeof(T));
return ret; return ret;
} }
//! \~english Calculate new container size based on old and requested size.
//! \~russian Вычисляет новый размер контейнера на основе старого и запрошенного размера.
static size_t calcNewSize(size_t old_size, size_t new_size) { static size_t calcNewSize(size_t old_size, size_t new_size) {
if (new_size == 0) return 0; if (new_size == 0) return 0;
if (new_size < maxCountForPoT()) { if (new_size < maxCountForPoT()) {

View File

@@ -365,8 +365,8 @@ public:
return *this; return *this;
} }
if (other.size() == 2) { if (other.size() == 2) {
insert(other.pim_index[0].key, other.pim_content[0]); insert(other.pim_index[0].key, other.pim_content[other.pim_index[0].index]);
insert(other.pim_index[1].key, other.pim_content[1]); insert(other.pim_index[1].key, other.pim_content[other.pim_index[1].index]);
return *this; return *this;
} }
for (int i = 0; i < other.pim_index.size_s(); ++i) { for (int i = 0; i < other.pim_index.size_s(); ++i) {

View File

@@ -1,8 +1,17 @@
/*! \file piset.h //! \addtogroup Containers
* \brief Set container //! \{
* //! \file piset.h
* This file declare PISet //! \brief
*/ //! \~english Declares \a PISet
//! \~russian Объявление \a PISet
//! \~\authors
//! \~english
//! Ivan Pelipenko peri4ko@yandex.ru;
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Иван Пелипенко peri4ko@yandex.ru;
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Set container Set container
@@ -27,13 +36,33 @@
#include "pimap.h" #include "pimap.h"
/*! \brief Set of any type //! \addtogroup Containers
* \details This class used to store collection of unique elements //! \{
* of any type. You can only add values to set with \a operator<< or //! \class PISet
* with function \a insert(). You can discover if value already in //! \brief
* set with \a operator[] or with function \a find(). These function //! \~english A set is a collection of unique elements.
* has logarithmic complexity. //! \~russian Множество - это коллекция уникальных элементов.
*/ //! \~\}
//! \details
//! \~english
//! This class is used to store a collection of unique elements of any type.
//! You can add values to the set using \a operator<< or the \a insert() function.
//! You can check if a value already exists in the set using \a operator[] or the \a contains() function.
//! These operations have logarithmic complexity.
//! To iterate over all elements, use STL-style iterators \a begin() and \a end().
//!
//! The set is implemented as a wrapper around \a PIMap, where keys are the elements
//! and values are dummy byte values (used only for storage).
//! \~russian
//! Этот класс используется для хранения коллекции уникальных элементов любого типа.
//! Вы можете добавлять значения в множество с помощью \a operator<< или функции \a insert().
//! Вы можете проверить, существует ли значение в множестве, используя \a operator[] или функцию \a contains().
//! Эти операции имеют логарифмическую сложность.
//! Для перебора всех элементов используйте итераторы в стиле STL \a begin() и \a end().
//!
//! Множество реализовано как обёртка над \a PIMap, где ключами являются элементы,
//! а значениями являются фиктивные байтовые значения (используются только для хранения).
//! \~\sa \a PIMap, \a PIVector
template<typename T> template<typename T>
class PISet: public PIMap<T, uchar> { class PISet: public PIMap<T, uchar> {
typedef PIMap<T, uchar> _CSet; typedef PIMap<T, uchar> _CSet;
@@ -43,26 +72,31 @@ class PISet: public PIMap<T, uchar> {
friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PISet<T1> & v); friend PIBinaryStream<P> & operator>>(PIBinaryStream<P> & s, PISet<T1> & v);
public: public:
//! Contructs an empty set //! \~english Constructs an empty set.
//! \~russian Создает пустое множество.
PISet() {} PISet() {}
//! Contructs set with one element "value" //! \~english Constructs a set with one element `value`.
//! \~russian Создает множество с одним элементом `value`.
explicit PISet(const T & value) { _CSet::insert(value, 0); } explicit PISet(const T & value) { _CSet::insert(value, 0); }
//! Contructs set with elements "v0" and "v1" //! \~english Constructs a set with two elements `v0` and `v1`.
//! \~russian Создает множество с двумя элементами `v0` и `v1`.
PISet(const T & v0, const T & v1) { PISet(const T & v0, const T & v1) {
_CSet::insert(v0, 0); _CSet::insert(v0, 0);
_CSet::insert(v1, 0); _CSet::insert(v1, 0);
} }
//! Contructs set with elements "v0", "v1" and "v2" //! \~english Constructs a set with three elements `v0`, `v1` and `v2`.
//! \~russian Создает множество с тремя элементами `v0`, `v1` и `v2`.
PISet(const T & v0, const T & v1, const T & v2) { PISet(const T & v0, const T & v1, const T & v2) {
_CSet::insert(v0, 0); _CSet::insert(v0, 0);
_CSet::insert(v1, 0); _CSet::insert(v1, 0);
_CSet::insert(v2, 0); _CSet::insert(v2, 0);
} }
//! Contructs set with elements "v0", "v1", "v2" and "v3" //! \~english Constructs a set with four elements `v0`, `v1`, `v2` and `v3`.
//! \~russian Создает множество с четырьмя элементами `v0`, `v1`, `v2` и `v3`.
PISet(const T & v0, const T & v1, const T & v2, const T & v3) { PISet(const T & v0, const T & v1, const T & v2, const T & v3) {
_CSet::insert(v0, 0); _CSet::insert(v0, 0);
_CSet::insert(v1, 0); _CSet::insert(v1, 0);
@@ -154,7 +188,8 @@ public:
inline const_iterator begin() const { return const_iterator(this, 0); } inline const_iterator begin() const { return const_iterator(this, 0); }
inline const_iterator end() const { return const_iterator(this, _CSet::size()); } inline const_iterator end() const { return const_iterator(this, _CSet::size()); }
//! Contructs set from vector of elements //! \~english Constructs a set from a vector of elements.
//! \~russian Создает множество из вектора элементов.
explicit PISet(const PIVector<T> & values) { explicit PISet(const PIVector<T> & values) {
if (values.isEmpty()) return; if (values.isEmpty()) return;
for (int i = 0; i < values.size_s(); ++i) { for (int i = 0; i < values.size_s(); ++i) {
@@ -162,7 +197,8 @@ public:
} }
} }
//! Contructs set from deque of elements //! \~english Constructs a set from a deque of elements.
//! \~russian Создает множество из deque элементов.
explicit PISet(const PIDeque<T> & values) { explicit PISet(const PIDeque<T> & values) {
if (values.isEmpty()) return; if (values.isEmpty()) return;
for (int i = 0; i < values.size_s(); ++i) { for (int i = 0; i < values.size_s(); ++i) {
@@ -172,6 +208,8 @@ public:
typedef T key_type; typedef T key_type;
//! \~english Inserts element `t` into the set.
//! \~russian Вставляет элемент `t` в множество.
PISet<T> & operator<<(const T & t) { PISet<T> & operator<<(const T & t) {
_CSet::insert(t, 0); _CSet::insert(t, 0);
return *this; return *this;
@@ -185,52 +223,62 @@ public:
return *this; return *this;
} }
//! \~english Tests if element `key` exists in the set. //! \~english Tests if element `t` exists in the set.
//! \~russian Проверяет наличие элемента `key` в массиве. //! \~russian Проверяет наличие элемента `t` в множестве.
inline bool contains(const T & t) const { return _CSet::contains(t); } inline bool contains(const T & t) const { return _CSet::contains(t); }
//! Returns if element "t" exists in this set //! \~english Tests if element `t` exists in the set.
//! \~russian Проверяет наличие элемента `t` в множестве.
bool operator[](const T & t) const { return _CSet::contains(t); } bool operator[](const T & t) const { return _CSet::contains(t); }
//! Returns if element "t" exists in this set //! \~english Removes element `t` from the set.
//! \~russian Удаляет элемент `t` из множества.
PISet<T> & remove(const T & t) { PISet<T> & remove(const T & t) {
_CSet::remove(t); _CSet::remove(t);
return *this; return *this;
} }
//! Unite set with "v" //! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet<T> & unite(const PISet<T> & v) { PISet<T> & unite(const PISet<T> & v) {
for (const auto & i: v) for (const auto & i: v)
_CSet::insert(i, 0); _CSet::insert(i, 0);
return *this; return *this;
} }
//! Subtract set with "v" //! \~english Returns the difference of this set and set `v`.
//! \~russian Возвращает разность этого множества и множества `v`.
PISet<T> & subtract(const PISet<T> & v) { PISet<T> & subtract(const PISet<T> & v) {
for (const auto & i: v) for (const auto & i: v)
_CSet::remove(i); _CSet::remove(i);
return *this; return *this;
} }
//! Intersect set with "v" //! \~english Returns the intersection of this set with set `v`.
//! \~russian Возвращает пересечение этого множества с множеством `v`.
PISet<T> & intersect(const PISet<T> & v) { PISet<T> & intersect(const PISet<T> & v) {
_CSet::removeWhere([&v](const T & k, uchar) { return !v.contains(k); }); _CSet::removeWhere([&v](const T & k, uchar) { return !v.contains(k); });
return *this; return *this;
} }
//! Unite set with "v" //! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet<T> & operator+=(const PISet<T> & v) { return unite(v); } PISet<T> & operator+=(const PISet<T> & v) { return unite(v); }
//! Unite set with "v" //! \~english Returns the union of this set with set `v`.
//! \~russian Возвращает объединение этого множества с множеством `v`.
PISet<T> & operator|=(const PISet<T> & v) { return unite(v); } PISet<T> & operator|=(const PISet<T> & v) { return unite(v); }
//! Subtract set with "v" //! \~english Returns the difference of this set and set `v`.
//! \~russian Возвращает разность этого множества и множества `v`.
PISet<T> & operator-=(const PISet<T> & v) { return subtract(v); } PISet<T> & operator-=(const PISet<T> & v) { return subtract(v); }
//! Intersect set with "v" //! \~english Returns the intersection of this set with set `v`.
//! \~russian Возвращает пересечение этого множества с множеством `v`.
PISet<T> & operator&=(const PISet<T> & v) { return intersect(v); } PISet<T> & operator&=(const PISet<T> & v) { return intersect(v); }
//! Returns content of set as PIVector //! \~english Converts the set to a vector.
//! \~russian Преобразует множество в вектор.
PIVector<T> toVector() const { PIVector<T> toVector() const {
PIVector<T> ret; PIVector<T> ret;
for (const auto & i: *this) for (const auto & i: *this)
@@ -238,7 +286,8 @@ public:
return ret; return ret;
} }
//! Returns content of set as PIDeque //! \~english Converts the set to a deque.
//! \~russian Преобразует множество в deque.
PIDeque<T> toDeque() const { PIDeque<T> toDeque() const {
PIDeque<T> ret; PIDeque<T> ret;
for (const auto & i: *this) for (const auto & i: *this)
@@ -248,7 +297,8 @@ public:
}; };
//! \relatesalso PISet \brief Returns unite of two sets //! \~english Returns the union of two sets.
//! \~russian Возвращает объединение двух множеств.
template<typename T> template<typename T>
PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) { PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0); PISet<T> ret(v0);
@@ -256,7 +306,8 @@ PISet<T> operator+(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet \brief Returns subtraction of two sets //! \~english Returns the difference of two sets.
//! \~russian Возвращает разность двух множеств.
template<typename T> template<typename T>
PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) { PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0); PISet<T> ret(v0);
@@ -264,7 +315,8 @@ PISet<T> operator-(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet \brief Returns unite of two sets //! \~english Returns the union of two sets.
//! \~russian Возвращает объединение двух множеств.
template<typename T> template<typename T>
PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) { PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0); PISet<T> ret(v0);
@@ -272,7 +324,8 @@ PISet<T> operator|(const PISet<T> & v0, const PISet<T> & v1) {
return ret; return ret;
} }
//! \relatesalso PISet \brief Returns intersetion of two sets //! \~english Returns the intersection of two sets.
//! \~russian Возвращает пересечение двух множеств.
template<typename T> template<typename T>
PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) { PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) {
PISet<T> ret(v0); PISet<T> ret(v0);
@@ -281,6 +334,9 @@ PISet<T> operator&(const PISet<T> & v0, const PISet<T> & v1) {
} }
//! \relatesalso PICout
//! \~english Output operator to \a PICout
//! \~russian Оператор вывода в \a PICout
template<typename Type> template<typename Type>
inline PICout operator<<(PICout s, const PISet<Type> & v) { inline PICout operator<<(PICout s, const PISet<Type> & v) {
s.space(); s.space();
@@ -297,4 +353,6 @@ inline PICout operator<<(PICout s, const PISet<Type> & v) {
return s; return s;
} }
//! \}
#endif // PISET_H #endif // PISET_H

View File

@@ -835,8 +835,8 @@ public:
//! piCout << v.contains({1,4}); // true //! piCout << v.contains({1,4}); // true
//! piCout << v.contains({1,5}); // false //! piCout << v.contains({1,5}); // false
//! \endcode //! \endcode
//! \~\sa \a every(), \a any(), \a entries(), \a forEach() //! \~\sa \a every(), \a any(), \a entries(), \a forEach(), \a contains()
inline bool contains(const PIVector<T> & v, ssize_t start = 0) const { inline bool containsAll(const PIVector<T> & v, ssize_t start = 0) const {
if (start < 0) { if (start < 0) {
start = piv_size + start; start = piv_size + start;
if (start < 0) start = 0; if (start < 0) start = 0;
@@ -854,6 +854,24 @@ public:
return true; return true;
} }
//! \~english Tests if any element of `v` exists in the array.
//! \~russian Проверяет наличие хотя бы одного из элементов `v` в массиве.
//! \~\sa \a containsAll(), \a contains()
inline bool containsAny(const PIVector<T> & v, ssize_t start = 0) const {
if (start < 0) {
start = piv_size + start;
if (start < 0) start = 0;
}
for (const T & e: v) {
for (size_t i = start; i < piv_size; ++i) {
if (e == piv_data[i]) {
return true;
}
}
}
return false;
}
//! \~english Count elements equal `e` in the array. //! \~english Count elements equal `e` in the array.
//! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве. //! \~russian Подсчитывает количество элементов, совпадающих с элементом `e` в массиве.
//! \~\details //! \~\details
@@ -1303,14 +1321,16 @@ public:
//! piCout << v; // {1, 3, 7, 5} //! piCout << v; // {1, 3, 7, 5}
//! \endcode //! \endcode
//! \~\sa \a append(), \a prepend(), \a remove() //! \~\sa \a append(), \a prepend(), \a remove()
inline PIVector<T> & insert(size_t index, const T & e = T()) { inline PIVector<T> & insert(size_t index, const T & e = T(), size_t count = 1) {
alloc(piv_size + 1); alloc(piv_size + count);
if (index < piv_size - 1) { if (index < piv_size - count) {
const size_t os = piv_size - index - 1; const size_t os = piv_size - index - count;
memmove(reinterpret_cast<void *>(piv_data + index + 1), reinterpret_cast<const void *>(piv_data + index), os * sizeof(T)); memmove(reinterpret_cast<void *>(piv_data + index + count), reinterpret_cast<const void *>(piv_data + index), os * sizeof(T));
}
PIINTROSPECTION_CONTAINER_USED(T, count)
for (size_t i = 0; i < count; ++i) {
elementNew(piv_data + index + i, e);
} }
PIINTROSPECTION_CONTAINER_USED(T, 1)
elementNew(piv_data + index, e);
return *this; return *this;
} }

View File

@@ -1,8 +1,15 @@
/*! \file pivector2d.h //! \addtogroup Containers
* \brief 2D wrapper around PIVector //! \{
* //! \file pivector2d.h
* This file declares PIVector //! \brief
*/ //! \~english Declares \a PIVector2D
//! \~russian Объявление \a PIVector2D
//! \~\authors
//! \~english
//! Andrey Bychkov work.a.b@yandex.ru;
//! \~russian
//! Андрей Бычков work.a.b@yandex.ru;
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
2D wrapper around PIVector 2D wrapper around PIVector
@@ -27,29 +34,111 @@
#include "pivector.h" #include "pivector.h"
/*! \brief 2D array, //! \addtogroup Containers
* \details This class used to store 2D array of any type elements as plain vector. //! \{
* You can read/write any element via operators [][], first dimension - row, second - column. //! \class PIVector2D
* The first dimension is Row, and you can operate with Row as PIVector<T>: modify any element, assign to another Row and etc. //! \brief
* You can't add values to array, but you can modify any elements or create another PIVector2D. //! \~english 2D array container.
* PIVector2D has constructors from PIVector<T> and PIVector<PIVector<T> > //! \~russian Двумерный контейнер-массив.
*/ //! \details
//! \~english
//! This class is used to store a 2D array of elements of any type as a single continuous block of memory (a plain PIVector).
//! Elements can be accessed using the `[][]` operators, where the first index is the row and the second is the column.
//! Rows can be manipulated as \a PIVector objects, allowing modification of individual elements or assignment of entire rows.
//! You cannot directly add or remove elements to change the dimensions of the array after construction
//! (use \a resize(), \a addRow(), \a removeRow(), \a removeColumn() instead), but you can modify the values of existing elements.
//! \~russian
//! Этот класс используется для хранения двумерного массива элементов любого типа в виде единого непрерывного блока памяти (обычного
//! \a PIVector). Доступ к элементам осуществляется с помощью операторов `[][]`, где первый индекс — это строка, а второй — столбец. Со
//! строками можно работать как с объектами \a PIVector, что позволяет изменять отдельные элементы или присваивать целые строки. Нельзя
//! напрямую добавлять или удалять элементы, чтобы изменить размеры массива после создания (используйте \a resize(), \a addRow(), \a
//! removeRow(), \a removeColumn() для этого), но можно изменять значения существующих элементов.
template<typename T> template<typename T>
class PIVector2D { class PIVector2D {
public: public:
//! \brief
//! \~english Index structure for 2D array elements (row, column).
//! \~russian Структура индекса для элементов двумерного массива (строка, столбец).
struct Index {
//! \~english Row index in the 2D array.
//! \~russian Индекс строки в двумерном массиве.
ssize_t row = -1;
//! \~english Column index in the 2D array.
//! \~russian Индекс столбца в двумерном массиве.
ssize_t col = -1;
//! \~english Default constructor. Initializes row and col to -1 (invalid index).
//! \~russian Конструктор по умолчанию. Инициализирует row и col значениями -1 (некорректный индекс).
inline Index() = default;
//! \~english Constructs an Index with the given row and column values.
//! \~russian Создаёт Index с заданными значениями строки и столбца.
inline Index(ssize_t r, ssize_t c): row(r), col(c) {}
//! \~english Checks if the index is valid (both row and column are non-negative).
//! \~russian Проверяет, является ли индекс корректным (строка и столбец неотрицательны).
//! \~\sa isNotValid()
inline bool isValid() const { return row >= 0 && col >= 0; }
//! \~english Checks if the index is invalid (either row or column is negative).
//! \~russian Проверяет, является ли индекс некорректным (строка или столбец отрицательны).
//! \~\sa isValid()
inline bool isNotValid() const { return !isValid(); }
};
//! \~english Constructs an empty 2D array. No memory is allocated.
//! \~russian Создаёт пустой двумерный массив. Память не выделяется.
//! \details
//! \~english After this constructor, \a rows() and \a cols() return 0, and \a isEmpty() returns true.
//! \~russian После этого конструктора \a rows() и \a cols() возвращают 0, а \a isEmpty() возвращает true.
//! \~\sa PIVector::PIVector()
inline PIVector2D() { rows_ = cols_ = 0; } inline PIVector2D() { rows_ = cols_ = 0; }
//! \~english Constructs a 2D array with the given dimensions, filled with copies of `f`.
//! \~russian Создаёт двумерный массив заданного размера, заполненный копиями `f`.
//! \details
//! \~english The underlying storage is a single contiguous block of memory of size `rows * cols`.
//! All elements are initialized with the value `f`.
//! \~russian Внутреннее хранилище представляет собой единый непрерывный блок памяти размером `rows * cols`.
//! Все элементы инициализируются значением `f`.
//! \~\sa PIVector::PIVector(size_t, const T&)
inline PIVector2D(size_t rows, size_t cols, const T & f = T()) { inline PIVector2D(size_t rows, size_t cols, const T & f = T()) {
rows_ = rows; rows_ = rows;
cols_ = cols; cols_ = cols;
mat.resize(rows * cols, f); mat.resize(rows * cols, f);
} }
//! \~english Constructs a 2D array from an existing 1D vector, reshaping it.
//! \~russian Создаёт двумерный массив из существующего одномерного вектора, изменяя его форму.
//! \details
//! \~english The constructor copies the data from `v` into the internal flat vector.
//! If `v` is larger than `rows * cols`, the excess elements are ignored (the vector is truncated).
//! If `v` is smaller, other values filled whith default cunstructor T()
//! \~russian Конструктор копирует данные из `v` во внутренний плоский вектор.
//! Если `v` больше, чем `rows * cols`, лишние элементы игнорируются (вектор обрезается).
//! Если `v` меньше, остальные значения будут заполнены из конструктора по умолчанию T()
//! \~\sa PIVector::PIVector(const PIVector&), reshape()
inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v): rows_(rows), cols_(cols), mat(v) { mat.resize(rows * cols); } inline PIVector2D(size_t rows, size_t cols, const PIVector<T> & v): rows_(rows), cols_(cols), mat(v) { mat.resize(rows * cols); }
//! \~english Move constructs a 2D array from an existing 1D vector, reshaping it.
//! \~russian Конструктор перемещения из существующего одномерного вектора, изменяя его форму.
//! \details
//! \~english The data is moved from `v` into the internal flat vector, avoiding a copy.
//! After construction, `v` is left in a valid but unspecified state.
//! \~russian Данные перемещаются из `v` во внутренний плоский вектор, что позволяет избежать копирования.
//! После завершения конструктора `v` остаётся в корректном, но неопределённом состоянии.
//! \~\sa PIVector::PIVector(PIVector&&)
inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v): rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows * cols); } inline PIVector2D(size_t rows, size_t cols, PIVector<T> && v): rows_(rows), cols_(cols), mat(std::move(v)) { mat.resize(rows * cols); }
//! \~english Constructs a 2D array from a vector of vectors (jagged array). Assumes all inner vectors have the same size.
//! \~russian Создаёт двумерный массив из вектора векторов (рваного массива). Предполагается, что все внутренние векторы имеют
//! одинаковый размер.
//! \details
//! \~english If the input is empty, the constructed array is also empty. Otherwise, the number of columns is taken from the size of the
//! first inner vector. All inner vectors are concatenated in the internal flat storage.
//! \~russian Если входной массив пуст, создаётся пустой двумерный массив. В противном случае количество столбцов берётся из размера
//! первого внутреннего вектора. Все внутренние векторы конкатенируются во внутреннем плоском хранилище. \sa PIVector::append()
inline PIVector2D(const PIVector<PIVector<T>> & v) { inline PIVector2D(const PIVector<PIVector<T>> & v) {
rows_ = v.size(); rows_ = v.size();
if (rows_) { if (rows_) {
@@ -63,219 +152,858 @@ public:
if (mat.isEmpty()) rows_ = cols_ = 0; if (mat.isEmpty()) rows_ = cols_ = 0;
} }
//! \~english Returns the number of rows in the 2D array.
//! \~russian Возвращает количество строк в двумерном массиве.
//! \return Number of rows.
//! \details
//! \~english The result is always non-negative. If the array is empty, returns 0.
//! \~russian Результат всегда неотрицательный. Если массив пуст, возвращает 0.
//! \~\sa cols(), size(), PIVector::size()
inline size_t rows() const { return rows_; } inline size_t rows() const { return rows_; }
//! \~english Returns the number of columns in the 2D array.
//! \~russian Возвращает количество столбцов в двумерном массиве.
//! \return Number of columns.
//! \details
//! \~english The result is always non-negative. If the array is empty, returns 0.
//! \~russian Результат всегда неотрицательный. Если массив пуст, возвращает 0.
//! \~\sa rows(), size(), PIVector::size()
inline size_t cols() const { return cols_; } inline size_t cols() const { return cols_; }
//! \~english Returns the total number of elements (`rows * cols`).
//! \~russian Возвращает общее количество элементов (`строки * столбцы`).
//! \return Total number of elements.
//! \details
//! \~english This is equivalent to the size of the underlying flat vector.
//! \~russian Это эквивалентно размеру внутреннего плоского вектора.
//! \~\sa rows(), cols(), PIVector::size()
inline size_t size() const { return mat.size(); } inline size_t size() const { return mat.size(); }
//! \~english Returns the total number of elements as a signed value.
//! \~russian Возвращает общее количество элементов в виде знакового числа.
//! \return Signed size.
//! \~\sa size(), PIVector::size_s()
inline ssize_t size_s() const { return mat.size_s(); } inline ssize_t size_s() const { return mat.size_s(); }
//! \~english Returns the total number of elements (same as \a size()).
//! \~russian Возвращает общее количество элементов (то же, что и \a size()).
//! \return Total number of elements.
//! \~\sa size(), PIVector::length()
inline size_t length() const { return mat.length(); } inline size_t length() const { return mat.length(); }
//! \~english Returns the number of elements that the underlying container has currently allocated space for.
//! \~russian Возвращает количество элементов, для которого сейчас выделена память во внутреннем контейнере.
//! \return Capacity of the flat vector.
//! \details
//! \~english This value may be larger than \a size(). It indicates how many elements can be added before a reallocation is needed.
//! \~russian Это значение может быть больше, чем \a size(). Оно показывает, сколько элементов можно добавить до того, как потребуется
//! перераспределение памяти. \sa reserve(), PIVector::capacity()
inline size_t capacity() const { return mat.capacity(); } inline size_t capacity() const { return mat.capacity(); }
//! \~english Checks if the array has no elements.
//! \~russian Проверяет, пуст ли массив.
//! \return \c true if the array is empty, \c false otherwise.
//! \details
//! \~english An empty array has both rows and columns equal to 0.
//! \~russian Пустой массив имеет и строки, и столбцы равные 0.
//! \~\sa isNotEmpty(), PIVector::isEmpty()
inline bool isEmpty() const { return mat.isEmpty(); } inline bool isEmpty() const { return mat.isEmpty(); }
//! \~english Checks if the array has at least one element.
//! \~russian Проверяет, не пуст ли массив.
//! \return \c true if the array is not empty, \c false otherwise.
//! \~\sa isEmpty(), PIVector::isNotEmpty()
inline bool isNotEmpty() const { return mat.isNotEmpty(); } inline bool isNotEmpty() const { return mat.isNotEmpty(); }
class Row { class RowConst;
friend class PIVector2D<T>; class ColConst;
class Row;
class Col;
private:
inline Row(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
st_ = p->cols_ * row;
sz_ = p->cols_;
}
PIVector<T> * p_;
size_t st_, sz_;
public:
inline size_t size() const { return sz_; }
inline T & operator[](size_t index) { return (*p_)[st_ + index]; }
inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; }
inline T * data(size_t index = 0) { return p_->data(st_ + index); }
inline const T * data(size_t index = 0) const { return p_->data(st_ + index); }
inline Row & operator=(const Row & other) {
if (p_ == other.p_ && st_ == other.st_) return *this;
const size_t sz = piMin<size_t>(sz_, other.sz_);
p_->_copyRaw(p_->data(st_), other.data(), sz);
return *this;
}
inline Row & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(sz_, other.size());
p_->_copyRaw(p_->data(st_), other.data(), sz);
return *this;
}
inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); }
};
class Col {
friend class PIVector2D<T>;
private:
inline Col(PIVector2D<T> * p, size_t row): p_(&(p->mat)) {
step_ = p->cols_;
row_ = row;
sz_ = p->rows_;
}
PIVector<T> * p_;
size_t step_, row_, sz_;
public:
inline size_t size() const { return sz_; }
inline T & operator[](size_t index) { return (*p_)[index * step_ + row_]; }
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + row_]; }
inline T * data(size_t index = 0) { return p_->data(index * step_ + row_); }
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + row_); }
inline Col & operator=(const Col & other) {
if (p_ == other.p_ && row_ == other.row_) return *this;
const size_t sz = piMin<size_t>(sz_, other.sz_);
for (int i = 0; i < sz; ++i)
(*p_)[i * step_ + row_] = other[i];
return *this;
}
inline Row & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(sz_, other.size());
for (int i = 0; i < sz; ++i)
(*p_)[i * step_ + row_] = other[i];
return *this;
}
inline PIVector<T> toVector() const {
PIVector<T> ret;
ret.reserve(sz_);
for (size_t i = 0; i < sz_; i++)
ret << (*p_)[i * step_ + row_];
return ret;
}
};
//! \class RowConst
//! \brief
//! \~english Proxy class representing a single read-only row in a \a PIVector2D.
//! \~russian Прокси-класс, представляющий одну строку в \a PIVector2D только для чтения.
//! \details
//! \~english Returned by const \a operator[] or \a row(). Provides const access to row elements.
//! \~russian Возвращается константными версиями \a operator[] или \a row(). Предоставляет константный доступ к элементам строки.
//! \~\sa Row, ColConst
class RowConst { class RowConst {
friend class PIVector2D<T>; friend class PIVector2D<T>;
private: protected:
inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) { inline RowConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)), st_(p->cols_ * row), sz_(p->cols_) {}
st_ = p->cols_ * row;
sz_ = p->cols_;
}
const PIVector<T> * p_; const PIVector<T> * p_;
size_t st_, sz_; const size_t st_, sz_;
public: public:
//! \~english Copy constructor from modifiable Row to read-only RowConst.
//! \~russian Конструктор копирования из модифицируемого класса Row в константный RowConst.
//! \~\sa Row
inline RowConst(const PIVector2D<T>::Row & r): p_(r.p_), st_(r.st_), sz_(r.sz_) {}
//! \~english Size of the row (number of columns).
//! \~russian Размер строки (количество столбцов).
inline size_t size() const { return sz_; } inline size_t size() const { return sz_; }
//! \~english Const access to the element at the given column index within the row.
//! \~russian Константный доступ к элементу по заданному индексу столбца в строке.
inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; } inline const T & operator[](size_t index) const { return (*p_)[st_ + index]; }
//! \~english Returns a const pointer to the row data starting at an optional offset.
//! \~russian Возвращает константный указатель на данные строки, начиная с опционального смещения.
inline const T * data(size_t index = 0) const { return p_->data(st_ + index); } inline const T * data(size_t index = 0) const { return p_->data(st_ + index); }
//! \~english Converts the row to a \a PIVector.
//! \~russian Преобразует строку в \a PIVector.
inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); } inline PIVector<T> toVector() const { return PIVector<T>(p_->data(st_), sz_); }
//! \~english Returns the first index of element `e` in the row, starting from `start`.
//! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`.
//! \details
//! \~english See \a PIVector::indexOf() for details on negative start handling.
//! \~russian Подробнее об обработке отрицательного `start` см. \a PIVector::indexOf().
//! \~\sa PIVector::indexOf()
inline ssize_t indexOf(const T & e, ssize_t start = 0) const {
if (start < 0) start = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if ((*p_)[st_ + i] == e) return (ssize_t)i;
}
return -1;
}
//! \~english Returns the last index of element `e` in the row, searching backwards from `start`.
//! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`.
//! \return Index if found, -1 otherwise.
//! \~\sa PIVector::lastIndexOf()
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start;
for (ssize_t i = from; i >= 0; --i) {
if ((*p_)[st_ + i] == e) return i;
}
return -1;
}
//! \~english Returns the first index where the predicate `test` returns true, starting from `start`.
//! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`.
//! \~\sa PIVector::indexWhere()
inline ssize_t indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
if (start < 0) start = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if (test((*p_)[st_ + i])) return (ssize_t)i;
}
return -1;
}
//! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`.
//! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true,
//! выполняя поиск в обратном направлении от `start`.
//! \~\sa PIVector::lastIndexWhere()
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start;
for (ssize_t i = from; i >= 0; --i) {
if (test((*p_)[st_ + i])) return i;
}
return -1;
}
//! \~english Applies a function to each element of the row (read-only).
//! \~russian Применяет функцию к каждому элементу строки (только чтение).
//! \details
//! \~english The function can't modify the elements.
//! \~russian Функция не может изменять элементы.
//! \~\sa forEach (modifiable)
inline void forEach(std::function<void(const T &)> func) const {
for (size_t i = 0; i < sz_; ++i) {
func((*p_)[st_ + i]);
}
}
//! \~english Checks if the row contains the element `e`.
//! \~russian Проверяет, содержит ли строка элемент `e`.
//! \~\sa PIVector::contains()
inline bool contains(const T & e, ssize_t start = 0) const { return indexOf(e, start) != -1; }
//! \~english Counts occurrences of `e` in the row.
//! \~russian Подсчитывает количество вхождений `e` в строке.
//! \~\sa PIVector::entries()
inline int entries(const T & e, ssize_t start = 0) const {
if (start < 0) start = 0;
int count = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if ((*p_)[st_ + i] == e) ++count;
}
return count;
}
//! \~english Counts elements in the row that pass the `test`.
//! \~russian Подсчитывает элементы в строке, проходящие `test`.
//! \~\sa PIVector::entries(std::function)
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
if (start < 0) start = 0;
int count = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if (test((*p_)[st_ + i])) ++count;
}
return count;
}
//! \~english Tests if any element in the row passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в строке `test`.
//! \~\sa PIVector::any()
inline bool any(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < sz_; ++i) {
if (test((*p_)[st_ + i])) return true;
}
return false;
}
//! \~english Tests if all elements in the row pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в строке `test`.
//! \~\sa PIVector::every()
inline bool every(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < sz_; ++i) {
if (!test((*p_)[st_ + i])) return false;
}
return true;
}
}; };
//! \class ColConst
//! \brief
//! \~english Proxy class representing a single read-only column in a \a PIVector2D.
//! \~russian Прокси-класс, представляющий один столбец в \a PIVector2D только для чтения.
//! \details
//! \~english Returned by const \a col(). Provides const access to column elements.
//! \~russian Возвращается константной версией \a col(). Предоставляет константный доступ к элементам столбца.
//! \~\sa Col, RowConst
class ColConst { class ColConst {
friend class PIVector2D<T>; friend class PIVector2D<T>;
private: protected:
inline ColConst(const PIVector2D<T> * p, size_t row): p_(&(p->mat)) { inline ColConst(const PIVector2D<T> * p, size_t col): p_(&(p->mat)), step_(p->cols_), col_(col), sz_(p->rows_) {}
step_ = p->cols_;
row_ = row;
sz_ = p->rows_;
}
const PIVector<T> * p_; const PIVector<T> * p_;
size_t step_, row_, sz_; const size_t step_, col_, sz_;
public: public:
inline size_t size() const { return p_->rows_; } //! \~english Copy constructor from modifiable Col to read-only ColConst.
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + row_]; } //! \~russian Конструктор копирования из модифицируемого класса Col в константный ColConst.
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + row_); } //! \~\sa Col
inline ColConst(const PIVector2D<T>::Col & c): p_(c.p_), step_(c.step_), col_(c.col_), sz_(c.sz_) {}
//! \~english Size of the column (number of rows).
//! \~russian Размер столбца (количество строк).
inline size_t size() const { return sz_; }
//! \~english Const access to the element at the given row index within the column.
//! \~russian Константный доступ к элементу по заданному индексу строки в столбце.
inline const T & operator[](size_t index) const { return (*p_)[index * step_ + col_]; }
//! \~english Returns a const pointer to the column data starting at an optional row offset.
//! \~russian Возвращает константный указатель на данные столбца, начиная с опционального смещения по строкам.
inline const T * data(size_t index = 0) const { return p_->data(index * step_ + col_); }
//! \~english Converts the column to a \a PIVector.
//! \~russian Преобразует столбец в \a PIVector.
inline PIVector<T> toVector() const { inline PIVector<T> toVector() const {
PIVector<T> ret; PIVector<T> ret;
ret.reserve(sz_); ret.reserve(sz_);
for (int i = 0; i < size(); i++) for (size_t i = 0; i < size(); i++)
ret << (*p_)[i * step_ + row_]; ret << (*p_)[i * step_ + col_];
return ret; return ret;
} }
//! \~english Returns the first index of element `e` in the row, starting from `start`.
//! \~russian Возвращает первый индекс элемента `e` в строке, начиная с позиции `start`.
//! \details
//! \~english See \a PIVector::indexOf() for details on negative start handling.
//! \~russian Подробнее об обработке отрицательного `start` см. \a PIVector::indexOf().
//! \~\sa PIVector::indexOf()
inline ssize_t indexOf(const T & e, ssize_t start = 0) const {
if (start < 0) start = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if ((*p_)[i * step_ + col_] == e) return (ssize_t)i;
}
return -1;
}
//! \~english Returns the last index of element `e` in the row, searching backwards from `start`.
//! \~russian Возвращает последний индекс элемента `e` в строке, выполняя поиск в обратном направлении от `start`.
//! \~\sa PIVector::lastIndexOf()
inline ssize_t lastIndexOf(const T & e, ssize_t start = -1) const {
ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start;
for (ssize_t i = from; i >= 0; --i) {
if ((*p_)[i * step_ + col_] == e) return i;
}
return -1;
}
//! \~english Returns the first index where the predicate `test` returns true, starting from `start`.
//! \~russian Возвращает первый индекс, для которого предикат `test` возвращает true, начиная с `start`.
//! \~\sa PIVector::indexWhere()
inline ssize_t indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
if (start < 0) start = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if (test((*p_)[i * step_ + col_])) return (ssize_t)i;
}
return -1;
}
//! \~english Returns the last index where the predicate `test` returns true, searching backwards from `start`.
//! \~russian Возвращает последний индекс, для которого предикат `test` возвращает true,
//! выполняя поиск в обратном направлении от `start`.
//! \~\sa PIVector::lastIndexWhere()
inline ssize_t lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
ssize_t from = (start < 0 || (size_t)start >= sz_) ? (ssize_t)sz_ - 1 : start;
for (ssize_t i = from; i >= 0; --i) {
if (test((*p_)[i * step_ + col_])) return i;
}
return -1;
}
//! \~english Applies a function to each element of the column (read-only).
//! \~russian Применяет функцию к каждому элементу столбца (только чтение).
//! \details
//! \~english The function can't modify the elements.
//! \~russian Функция не может изменять элементы.
//! \~\sa forEach (modifiable)
inline void forEach(std::function<void(const T &)> func) const {
for (size_t i = 0; i < sz_; ++i) {
func((*p_)[i * step_ + col_]);
}
}
//! \~english Checks if the column contains the element `e`.
//! \~russian Проверяет, содержит ли столбец элемент `e`.
//! \~\sa PIVector::contains()
inline bool contains(const T & e, ssize_t start = 0) const { return indexOf(e, start) != -1; }
//! \~english Counts occurrences of `e` in the column.
//! \~russian Подсчитывает количество вхождений `e` в столбце.
//! \~\sa PIVector::entries()
inline int entries(const T & e, ssize_t start = 0) const {
if (start < 0) start = 0;
int count = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if ((*p_)[i * step_ + col_] == e) ++count;
}
return count;
}
//! \~english Counts elements in the column that pass the `test`.
//! \~russian Подсчитывает элементы в столбце, проходящие `test`.
//! \~\sa PIVector::entries(std::function)
inline int entries(std::function<bool(const T & e)> test, ssize_t start = 0) const {
if (start < 0) start = 0;
int count = 0;
for (size_t i = (size_t)start; i < sz_; ++i) {
if (test((*p_)[i * step_ + col_])) ++count;
}
return count;
}
//! \~english Tests if any element in the column passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в столбце `test`.
//! \~\sa PIVector::any()
inline bool any(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < sz_; ++i) {
if (test((*p_)[i * step_ + col_])) return true;
}
return false;
}
//! \~english Tests if all elements in the column pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в столбце `test`.
//! \~\sa PIVector::every()
inline bool every(std::function<bool(const T & e)> test) const {
for (size_t i = 0; i < sz_; ++i) {
if (!test((*p_)[i * step_ + col_])) return false;
}
return true;
}
}; };
inline T & element(size_t row, size_t col) { return mat[row * cols_ + col]; } //! \class Row
inline const T & element(size_t row, size_t col) const { return mat[row * cols_ + col]; } //! \brief
inline const T & at(size_t row, size_t col) const { return mat[row * cols_ + col]; } //! \~english Proxy class representing a single row in a \a PIVector2D for modification.
inline Row operator[](size_t index) { return Row(this, index); } //! \~russian Прокси-класс, представляющий одну строку в \a PIVector2D для модификации.
inline RowConst operator[](size_t index) const { return RowConst(this, index); } //! \details
inline T * data(size_t index = 0) { return mat.data(index); } //! \~english Objects of this class are returned by non-const \a operator[] or \a row().
inline const T * data(size_t index = 0) const { return mat.data(index); } //! They provide array-like access to the elements of a specific row and allow operations such as assignment from another row or a \a
//! PIVector, searching, filling, and iteration.
//! \~russian Объекты этого класса возвращаются неконстантными операторами \a operator[] или методом \a row().
//! Они предоставляют доступ к элементам конкретной строки, подобный массиву, и позволяют выполнять такие операции, как присваивание из
//! другой строки или \a PIVector, поиск, заполнение и итерацию. \sa Col, RowConst
class Row: public RowConst {
friend class PIVector2D<T>;
inline Row row(size_t index) { return Row(this, index); } private:
inline RowConst row(size_t index) const { return RowConst(this, index); } inline Row(PIVector2D<T> * p, size_t row): RowConst(p, row), p_(&(p->mat)) {}
inline Col col(size_t index) { return Col(this, index); } PIVector<T> * p_;
inline ColConst col(size_t index) const { return ColConst(this, index); }
inline PIVector2D<T> & setRow(size_t row, const Row & other) { public:
const size_t sz = piMin<size_t>(cols_, other.sz_); using RowConst::operator[];
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); using RowConst::data;
using RowConst::size;
//! \~english Accesses the element at the given column index within the row.
//! \~russian Доступ к элементу по заданному индексу столбца в строке.
//! \details
//! \~english No bounds checking is performed; use with caution.
//! \~russian Проверка границ не выполняется; используйте с осторожностью.
//! \~\sa PIVector::operator[]
inline T & operator[](size_t index) { return (*p_)[this->st_ + index]; }
//! \~english Returns a pointer to the row data starting at an optional offset.
//! \~russian Возвращает указатель на данные строки, начиная с опционального смещения.
//! \details
//! \~english The pointer can be used for direct memory operations. It remains valid as long as the underlying 2D array is not
//! reallocated.
//! \~russian Указатель можно использовать для прямых операций с памятью. Он остаётся действительным, пока не произойдёт
//! перераспределение памяти внутреннего двумерного массива. \sa PIVector::data()
inline T * data(size_t index = 0) { return p_->data(this->st_ + index); }
//! \~english Assigns the contents of another Row to this row.
//! \~russian Присваивает этой строке содержимое другой строки.
//! \details
//! \~english Only the minimum of the two row sizes is copied; if this row is shorter, excess elements in `other` are ignored.
//! \~russian Копируется только минимум из размеров двух строк; если эта строка короче, лишние элементы из `other` игнорируются.
//! \~\sa PIVector::operator=
inline Row & operator=(const Row & other) {
if (p_ == other.p_ && this->st_ == other.st_) return *this;
const size_t sz = piMin<size_t>(this->sz_, other.sz_);
p_->_copyRaw(p_->data(this->st_), other.data(), sz);
return *this; return *this;
} }
//! \~english Assigns the contents of a \a PIVector to this row.
//! \~russian Присваивает этой строке содержимое \a PIVector.
//! \details
//! \~english Only the minimum of the row size and vector size is copied.
//! \~russian Копируется только минимум из размера строки и размера вектора.
//! \~\sa PIVector::operator=
inline Row & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(this->sz_, other.size());
p_->_copyRaw(p_->data(this->st_), other.data(), sz);
return *this;
}
//! \~english Applies a function to each element of the row (modifiable).
//! \~russian Применяет функцию к каждому элементу строки (с возможностью изменения).
//! \param func Function that takes a reference to T.
//! \details
//! \~english The function can modify the elements.
//! \~russian Функция может изменять элементы.
//! \~\sa PIVector::forEach()
inline void forEach(std::function<void(T &)> func) {
for (size_t i = 0; i < this->sz_; ++i) {
func((*p_)[this->st_ + i]);
}
}
//! \~english Fills the row with copies of `value`.
//! \~russian Заполняет строку копиями `value`.
//! \~\sa PIVector::fill()
inline void fill(const T & value) {
for (size_t i = 0; i < this->sz_; ++i) {
(*p_)[this->st_ + i] = value;
}
}
};
//! \class Col
//! \brief
//! \~english Proxy class representing a single column in a \a PIVector2D for modification.
//! \~russian Прокси-класс, представляющий один столбец в \a PIVector2D для модификации.
//! \details
//! \~english Objects of this class are returned by non-const \a col(). They provide column-wise access and operations similar to \a
//! Row.
//! \~russian Объекты этого класса возвращаются неконстантным методом \a col(). Они предоставляют доступ к столбцам и операции,
//! аналогичные \a Row. \sa Row, ColConst
class Col: public ColConst {
friend class PIVector2D<T>;
private:
inline Col(PIVector2D<T> * p, size_t col): ColConst(p, col), p_(&(p->mat)) {}
PIVector<T> * p_;
public:
using ColConst::operator[];
using ColConst::data;
using ColConst::size;
//! \~english Accesses the element at the given row index within the column.
//! \~russian Доступ к элементу по заданному индексу строки в столбце.
//! \return Reference to the element.
inline T & operator[](size_t index) { return (*p_)[index * this->step_ + this->col_]; }
//! \~english Returns a pointer to the column data starting at an optional row offset.
//! \~russian Возвращает указатель на данные столбца, начиная с опционального смещения по строкам.
//! \details
//! \~english Note that column elements are not stored contiguously in memory, so this pointer cannot be used to iterate over the
//! whole column.
//! \~russian Обратите внимание, что элементы столбца не хранятся в памяти непрерывно, поэтому этот указатель нельзя использовать
//! для итерации по всему столбцу.
inline T * data(size_t index = 0) { return p_->data(index * this->step_ + this->col_); }
//! \~english Assigns the contents of another Col to this column.
//! \~russian Присваивает этому столбцу содержимое другого столбца.
inline Col & operator=(const Col & other) {
if (p_ == other.p_ && this->col_ == other.col_) return *this;
const size_t sz = piMin<size_t>(this->sz_, other.sz_);
for (size_t i = 0; i < sz; ++i)
(*p_)[i * this->step_ + this->col_] = other[i];
return *this;
}
//! \~english Assigns the contents of a \a PIVector to this column.
//! \~russian Присваивает этому столбцу содержимое \a PIVector.
inline Col & operator=(const PIVector<T> & other) {
const size_t sz = piMin<size_t>(this->sz_, other.size());
for (size_t i = 0; i < sz; ++i)
(*p_)[i * this->step_ + this->col_] = other[i];
return *this;
}
//! \~english Applies a function to each element of the column (modifiable).
//! \~russian Применяет функцию к каждому элементу столбца (с возможностью изменения).
//! \details
//! \~english The function can modify the elements.
//! \~russian Функция может изменять элементы.
//! \~\sa PIVector::forEach()
inline void forEach(std::function<void(T &)> func) {
for (size_t i = 0; i < this->sz_; ++i) {
func((*p_)[i * this->step_ + this->col_]);
}
}
//! \~english Fills the column with copies of `value`.
//! \~russian Заполняет столбец копиями `value`.
//! \~\sa PIVector::fill()
inline void fill(const T & value) {
for (size_t i = 0; i < this->sz_; ++i) {
(*p_)[i * this->step_ + this->col_] = value;
}
}
};
//! \~english Returns a reference to the element at the given row and column.
//! \~russian Возвращает ссылку на элемент по заданной строке и столбцу.
//! \details
//! \~english No bounds checking is performed.
//! \~russian Проверка границ не выполняется.
//! \~\sa at() (const version), PIVector::operator[]
inline T & element(size_t row, size_t col) { return mat[row * cols_ + col]; }
//! \~english Returns a const reference to the element at the given row and column.
//! \~russian Возвращает константную ссылку на элемент по заданной строке и столбцу.
inline const T & element(size_t row, size_t col) const { return mat[row * cols_ + col]; }
//! \~english Returns a const reference to the element at the given row and column
//! \~russian Возвращает константную ссылку на элемент по заданной строке и столбцу
//! \details
//! \~english No bounds checking is performed.
//! \~russian Проверка границ не выполняется.
inline const T & at(size_t row, size_t col) const { return mat[row * cols_ + col]; }
//! \~english Returns a reference to the element at the given Index.
//! \~russian Возвращает ссылку на элемент по заданному Index.
inline T & operator[](const Index & idx) { return element(idx.row, idx.col); }
//! \~english Returns a const reference to the element at the given Index.
//! \~russian Возвращает константную ссылку на элемент по заданному Index.
inline const T & operator[](const Index & idx) const { return element(idx.row, idx.col); }
//! \~english Returns a reference to the element at the given Index.
//! \~russian Возвращает ссылку на элемент по заданному Index.
inline T & element(const Index & idx) { return element(idx.row, idx.col); }
//! \~english Returns a const reference to the element at the given Index.
//! \~russian Возвращает константную ссылку на элемент по заданному Index.
inline const T & element(const Index & idx) const { return element(idx.row, idx.col); }
//! \~english Returns a const reference to the element at the given Index (bounds-checked only in debug).
//! \~russian Возвращает константную ссылку на элемент по заданному Index (проверка границ только в отладочном режиме).
inline const T & at(const Index & idx) const { return at(idx.row, idx.col); }
//! \~english Returns a proxy object for the row at the given index for modification.
//! \~russian Возвращает прокси-объект для строки по заданному индексу для модификации.
//! \~\sa row(), Col
inline Row operator[](size_t index) { return Row(this, index); }
//! \~english Returns a proxy object for the row at the given index for read-only access.
//! \~russian Возвращает прокси-объект для строки по заданному индексу только для чтения.
inline RowConst operator[](size_t index) const { return RowConst(this, index); }
//! \~english Returns a pointer to the underlying flat data starting at an optional offset.
//! \~russian Возвращает указатель на внутренние плоские данные, начиная с опционального смещения.
//! \~\sa PIVector::data()
inline T * data(size_t index = 0) { return mat.data(index); }
//! \~english Returns a const pointer to the underlying flat data starting at an optional offset.
//! \~russian Возвращает константный указатель на внутренние плоские данные, начиная с опционального смещения.
inline const T * data(size_t index = 0) const { return mat.data(index); }
//! \~english Returns a proxy object for the row at the given index for modification.
//! \~russian Возвращает прокси-объект для строки по заданному индексу для модификации.
//! \~\sa operator[]
inline Row row(size_t index) { return Row(this, index); }
//! \~english Returns a proxy object for the row at the given index for read-only access.
//! \~russian Возвращает прокси-объект для строки по заданному индексу только для чтения.
inline RowConst row(size_t index) const { return RowConst(this, index); }
//! \~english Returns a proxy object for the column at the given index for modification.
//! \~russian Возвращает прокси-объект для столбца по заданному индексу для модификации.
//! \~\sa col() const
inline Col col(size_t index) { return Col(this, index); }
//! \~english Returns a proxy object for the column at the given index for read-only access.
//! \~russian Возвращает прокси-объект для столбца по заданному индексу только для чтения.
inline ColConst col(size_t index) const { return ColConst(this, index); }
//! \~english Replaces a row with the contents of a read-only RowConst object.
//! \~russian Заменяет строку содержимым объекта RowConst только для чтения.
inline PIVector2D<T> & setRow(size_t row, const RowConst & other) { inline PIVector2D<T> & setRow(size_t row, const RowConst & other) {
const size_t sz = piMin<size_t>(cols_, other.sz_); const size_t sz = piMin<size_t>(cols_, other.sz_);
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
return *this; return *this;
} }
//! \~english Replaces a row with the contents of a \a PIVector.
//! \~russian Заменяет строку содержимым \a PIVector.
inline PIVector2D<T> & setRow(size_t row, const PIVector<T> & other) { inline PIVector2D<T> & setRow(size_t row, const PIVector<T> & other) {
const size_t sz = piMin<size_t>(cols_, other.size()); const size_t sz = piMin<size_t>(cols_, other.size());
mat._copyRaw(mat.data(cols_ * row), other.data(), sz); mat._copyRaw(mat.data(cols_ * row), other.data(), sz);
return *this; return *this;
} }
inline PIVector2D<T> & addRow(const Row & other) {
if (cols_ == 0) cols_ = other.sz_; //! \~english Appends a new row to the bottom of the array from another Row object.
const size_t sz = piMin<size_t>(cols_, other.sz_); //! \~russian Добавляет новую строку в конец массива из другого объекта Row.
const size_t ps = mat.size(); //! \details
mat.resize(mat.size() + cols_); //! \~english If the array was empty, its column count is set to the size of the source row.
mat._copyRaw(mat.data(ps), other.data(), sz); //! Otherwise, only `min(cols(), other.size())` elements are copied; the rest of the new row is default-initialized.
rows_++; //! \~russian Если массив был пуст, количество столбцов устанавливается равным размеру исходной строки.
return *this; //! В противном случае копируется только `min(cols(), other.size())` элементов; остальные элементы новой строки инициализируются по
} //! умолчанию.
//! \~\sa PIVector::push_back()
inline PIVector2D<T> & addRow(const RowConst & other) { inline PIVector2D<T> & addRow(const RowConst & other) {
if (cols_ == 0) cols_ = other.sz_; if (cols_ == 0) cols_ = other.sz_;
const size_t sz = piMin<size_t>(cols_, other.sz_); mat.append(other.toVector());
const size_t ps = mat.size();
mat.resize(mat.size() + cols_);
mat._copyRaw(mat.data(ps), other.data(), sz);
rows_++;
return *this;
}
inline PIVector2D<T> & addRow(const PIVector<T> & other) {
if (cols_ == 0) cols_ = other.size();
const size_t sz = piMin<size_t>(cols_, other.size());
const size_t ps = mat.size();
mat.resize(mat.size() + cols_);
mat._copyRaw(mat.data(ps), other.data(), sz);
rows_++; rows_++;
mat.resize(rows_ * cols_);
return *this; return *this;
} }
inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) { //! \~english Appends a new row to the bottom of the array from a \a PIVector.
mat.resize(rows * cols_, f); //! \~russian Добавляет новую строку в конец массива из \a PIVector.
rows_ = rows; inline PIVector2D<T> & addRow(const PIVector<T> & other) {
const int cs = (cols - cols_); if (cols_ == 0) cols_ = other.size();
if (cs < 0) { mat.append(other);
for (size_t r = 0; r < rows; ++r) { rows_++;
mat.remove(r * cols + cols, -cs); mat.resize(rows_ * cols_);
return *this;
} }
//! \~english Appends \a count new empty rows to the bottom of the array, filled with value \a f.
//! \~russian Добавляет \a count новых пустых строк в конец массива, заполненных значением \a f.
//! \details
//! \~english If the array was empty (no columns defined), the column count is set to 1.
//! The new rows are filled with the default value \a f.
//! \~russian Если массив был пуст (количество столбцов не определено), количество столбцов устанавливается равным 1.
//! Новые строки заполняются значением по умолчанию \a f.
//! \~\sa addRow(), appendColumns()
inline PIVector2D<T> & appendRows(size_t count, const T & f = T()) {
if (count == 0) return *this;
if (cols_ == 0) ++cols_;
mat.resize(mat.size() + count * cols_, f);
rows_ += count;
return *this;
} }
mat.resize(rows * cols, f);
if (!mat.isEmpty()) { //! \~english Appends \a count new empty columns to the end of each row of the array.
if (cs > 0) { //! \~russian Добавляет \a count новых пустых столбцов в конец каждой строки массива.
//! \details
//! \~english If the array was empty (rows not defined), the array becomes a single row with \a count columns.
//! If the array already has rows, new elements are inserted at the end of each existing row.
//! \~russian Если массив был пуст (строки не определены), массив становится одной строкой с \a count столбцов.
//! Если массив уже содержит строки, новые элементы добавляются в конец каждой существующей строки.
//! \~\sa appendRows(), addColumn()
inline PIVector2D<T> & appendColumns(size_t count, const T & f = T()) {
if (count == 0) return *this;
if (rows_ == 0) {
mat.resize(count, f);
rows_ = 1;
cols_ = count;
return *this;
}
const size_t newCols = cols_ + count;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
mat.insert(r * cols_, f, count);
}
cols_ = newCols;
return *this;
}
//! \~english Deletes `count` rows starting from the specified row index.
//! \~russian Удаляет `count` строк, начиная с указанного индекса строки.
//! \details
//! \~english Removes the specified rows from the array and updates the row count. If all elements are deleted (array becomes empty),
//! both rows and columns are set to 0.
//! \~russian Удаляет указанные строки из массива и обновляет количество строк. Если все элементы удалены (массив становится пустым),
//! количество строк и столбцов устанавливается в 0.
//! \~\sa deleteColumns()
inline PIVector2D<T> & deleteRows(size_t row_start, size_t count) {
if (row_start >= rows_ || count == 0) return *this;
mat.remove(row_start * cols_, cols_ * count);
if (isEmpty()) {
cols_ = 0;
rows_ = 0;
} else {
rows_ -= count;
}
return *this;
}
//! \~english Removes the specified columns from the array and updates the column count.
//! \~russian Удаляет указанные столбцы из массива и обновляет количество столбцов.
//! \details
//! \~english Removes \a count columns starting from \a col_start. If \a col_start is out of range or \a count is 0,
//! the function does nothing. If \a count extends beyond the last column, only available columns are deleted.
//! \~russian Удаляет \a count столбцов начиная с \a col_start. Если \a col_start выходит за границы или \a count равен 0,
//! функция ничего не делает. Если \a count выходит за последний столбец, удаляются только доступные столбцы.
//! \~\sa removeColumn(), deleteRows()
inline PIVector2D<T> & deleteColumns(size_t col_start, size_t count) {
if (col_start >= cols_ || rows_ == 0) return *this;
count = piMin(count, cols_ - col_start);
if (count == 0) return *this;
for (size_t r = 0; r < rows_; ++r) { for (size_t r = 0; r < rows_; ++r) {
for (int i = 0; i < cs; ++i) mat.remove(r * (cols_ - count) + col_start, count);
mat.insert(r * cols + cols_, mat.take_back()); }
cols_ -= count;
mat.resize(rows_ * cols_);
return *this;
}
//! \~english Appends a new column to the right of the array from a \a ColConst.
//! \~russian Добавляет новую строку в конец массива из \a ColConst.
inline PIVector2D<T> & addColumn(const ColConst & other) {
if (other.size() == 0) return *this;
if (isEmpty()) {
mat.reserve(other.size());
for (size_t r = 0; r < other.size(); ++r) {
mat.append(other[r]);
}
rows_ = mat.size();
cols_ = 1;
return *this;
}
const size_t newCols = cols_ + 1;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
if (r - 1 < other.size()) {
mat.insert(r * cols_, other[r - 1]);
} else {
mat.insert(r * cols_);
} }
} }
cols_ = newCols;
return *this;
} }
//! \~english Appends a new column to the right of the array from a \a PIVector.
//! \~russian Добавляет новую строку в конец массива из \a PIVector.
inline PIVector2D<T> & addColumn(const PIVector<T> & other) {
if (other.size() == 0) return *this;
if (isEmpty()) {
mat.append(other);
rows_ = mat.size();
cols_ = 1;
return *this;
}
const size_t newCols = cols_ + 1;
mat.reserve(rows_ * newCols);
for (size_t r = rows_; r > 0; --r) {
if (r - 1 < other.size()) {
mat.insert(r * cols_, other[r - 1]);
} else {
mat.insert(r * cols_);
}
}
cols_ = newCols;
return *this;
}
//! \~english Resizes the 2D array to new dimensions.
//! \~russian Изменяет размер двумерного массива.
//! \details
//! \~english If the new dimensions are larger, new elements are appended and filled with copies of `f`.
//! If they are smaller, the array is truncated (excess elements are destroyed). The underlying memory may be reallocated.
//! \~russian Если новые размеры больше текущих, новые элементы добавляются в конец и заполняются копиями `f`.
//! Если новые размеры меньше, массив усекается (лишние элементы уничтожаются). Внутренняя память может быть перераспределена.
//! \code
//! PIVector2D<int> mat(2, 3, 0); // 2x3 matrix filled with 0
//! mat.resize(3, 4, 1); // becomes 3x4, new elements filled with 1
//! \endcode
//! \~\sa PIVector::resize()
inline PIVector2D<T> & resize(size_t rows, size_t cols, const T & f = T()) {
if (rows == rows_ && cols == cols_) return *this;
if (rows_ == 0 || cols_ == 0) {
mat.resize(rows * cols, f);
rows_ = rows;
cols_ = cols; cols_ = cols;
return *this; return *this;
} }
if (rows != rows_ && cols == cols_) {
mat.resize(rows * cols_, f);
rows_ = rows;
return *this;
}
if (cols > cols_) {
appendColumns(cols - cols_, f);
}
if (rows > rows_) {
appendRows(rows - rows_, f);
}
if (cols < cols_) {
deleteColumns(cols, cols_ - cols);
}
if (rows < rows_) {
deleteRows(rows, rows_ - rows);
}
return *this;
}
//! \~english Equality operator.
//! \~russian Оператор равенства.
//! \~\sa PIVector::operator==
inline bool operator==(const PIVector2D<T> & t) const { inline bool operator==(const PIVector2D<T> & t) const {
if (cols_ != t.cols_ || rows_ != t.rows_) return false; if (cols_ != t.cols_ || rows_ != t.rows_) return false;
return mat == t.mat; return mat == t.mat;
} }
//! \~english Inequality operator.
//! \~russian Оператор неравенства.
inline bool operator!=(const PIVector2D<T> & t) const { return !(*this == t); } inline bool operator!=(const PIVector2D<T> & t) const { return !(*this == t); }
//! \~english Converts the 2D array to a vector of vectors (PIVector<PIVector<T>>).
//! \~russian Преобразует двумерный массив в вектор векторов (PIVector<PIVector<T>>).
//! \details
//! \~english Each row vector is a copy of the corresponding row.
//! \~russian Каждый вектор-строка является копией соответствующей строки.
//! \~\sa fromVectors(), PIVector::PIVector(const T*, size_t)
inline PIVector<PIVector<T>> toVectors() const { inline PIVector<PIVector<T>> toVectors() const {
PIVector<PIVector<T>> ret; PIVector<PIVector<T>> ret;
ret.reserve(rows_); ret.reserve(rows_);
@@ -284,18 +1012,31 @@ public:
return ret; return ret;
} }
//! \~english Returns a const reference to the underlying flat \a PIVector.
//! \~russian Возвращает константную ссылку на внутренний плоский \a PIVector.
inline const PIVector<T> & asPlainVector() const { return mat; }
//! \~english Returns a reference to the underlying flat \a PIVector.
//! \~russian Возвращает ссылку на внутренний плоский \a PIVector.
inline PIVector<T> & asPlainVector() { return mat; }
//! \~english Returns a copy of the underlying flat \a PIVector.
//! \~russian Возвращает копию внутреннего плоского \a PIVector.
inline PIVector<T> toPlainVector() const { return mat; } inline PIVector<T> toPlainVector() const { return mat; }
inline PIVector<T> & plainVector() { return mat; } //! \~english Swaps this 2D array with another.
//! \~russian Меняет местами этот двумерный массив с другим.
inline const PIVector<T> & plainVector() const { return mat; } //! \details
//! \~english Swaps the flat vectors and the dimension members. Very fast, no memory allocation.
//! \~russian Обменивает внутренние плоские векторы и члены, хранящие размеры. Очень быстро, без выделения памяти.
//! \~\sa PIVector::swap()
inline void swap(PIVector2D<T> & other) { inline void swap(PIVector2D<T> & other) {
mat.swap(other.mat); mat.swap(other.mat);
piSwap<size_t>(rows_, other.rows_); piSwap<size_t>(rows_, other.rows_);
piSwap<size_t>(cols_, other.cols_); piSwap<size_t>(cols_, other.cols_);
} }
//! \internal
template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0> template<typename T1 = T, typename std::enable_if<std::is_trivially_copyable<T1>::value, int>::type = 0>
inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) { inline PIVector2D<T> & _resizeRaw(size_t r, size_t c) {
rows_ = r; rows_ = r;
@@ -304,29 +1045,348 @@ public:
return *this; return *this;
} }
//! \~english Clears the array, removing all elements and setting dimensions to 0.
//! \~russian Очищает массив, удаляя все элементы и устанавливая размеры в 0.
//! \details
//! \~english The capacity of the underlying flat vector may remain unchanged.
//! \~russian Ёмкость внутреннего плоского вектора может остаться неизменной.
//! \~\sa PIVector::clear()
inline void clear() { inline void clear() {
rows_ = cols_ = 0; rows_ = cols_ = 0;
mat.clear(); mat.clear();
} }
template<typename ST>
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const { //! \~english Checks if the underlying flat vector contains the element `e`.
return PIVector2D<ST>(rows_, cols_, mat.map(f)); //! \~russian Проверяет, содержит ли внутренний плоский вектор элемент `e`.
//! \~\sa PIVector::contains()
inline bool contains(const T & e) const { return mat.contains(e); }
//! \~english Counts occurrences of `e` in the underlying flat vector.
//! \~russian Подсчитывает количество вхождений `e` во внутреннем плоском векторе.
//! \~\sa PIVector::entries()
inline int entries(const T & e) const { return mat.entries(e); }
//! \~english Counts elements in the flat vector that pass the `test`.
//! \~russian Подсчитывает элементы в плоском векторе, проходящие `test`.
//! \~\sa PIVector::entries(std::function)
inline int entries(std::function<bool(const T & e)> test) const { return mat.entries(test); }
//! \~english Returns the first index (row, col) of `e` in the 2D array.
//! \~russian Возвращает первый индекс (строка, столбец) элемента `e` в двумерном массиве.
//! \~\sa PIVector::indexOf()
inline Index indexOf(const T & e) const {
ssize_t flat = mat.indexOf(e);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
} }
inline void forEach(std::function<void(const T &)> f) const { mat.forEach(f); } //! \~english Returns the first index (row, col) in the 2D array that passes the `test`.
//! \~russian Возвращает первый индекс (строка, столбец) в двумерном массиве, проходящий `test`.
//! \~\sa PIVector::indexWhere()
inline Index indexWhere(std::function<bool(const T & e)> test, ssize_t start = 0) const {
ssize_t flat = mat.indexWhere(test, start);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
}
inline PIVector2D<T> & forEach(std::function<void(T &)> f) { //! \~english Returns the last index (row, col) of `e` in the 2D array.
mat.forEach(f); //! \~russian Возвращает последний индекс (строка, столбец) элемента `e` в двумерном массиве.
//! \~\sa PIVector::lastIndexOf()
inline Index lastIndexOf(const T & e, ssize_t start = -1) const {
ssize_t flat = mat.lastIndexOf(e, start);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
}
//! \~english Returns the last index (row, col) in the 2D array that passes the `test`.
//! \~russian Возвращает последний индекс (строка, столбец) в двумерном массиве, проходящий `test`.
//! \~\sa PIVector::lastIndexWhere()
inline Index lastIndexWhere(std::function<bool(const T & e)> test, ssize_t start = -1) const {
ssize_t flat = mat.lastIndexWhere(test, start);
if (flat < 0 || cols_ == 0) return Index{-1, -1};
return Index{flat / static_cast<ssize_t>(cols_), flat % static_cast<ssize_t>(cols_)};
}
//! \~english Tests if any element in the flat vector passes the `test`.
//! \~russian Проверяет, проходит ли какой-либо элемент в плоском векторе `test`.
//! \~\sa PIVector::any()
inline bool any(std::function<bool(const T & e)> test) const { return mat.any(test); }
//! \~english Tests if all elements in the flat vector pass the `test`.
//! \~russian Проверяет, проходят ли все элементы в плоском векторе `test`.
//! \~\sa PIVector::every()
inline bool every(std::function<bool(const T & e)> test) const { return mat.every(test); }
//! \~english Fills the entire 2D array with copies of `e`.
//! \~russian Заполняет весь двумерный массив копиями `e`.
//! \~\sa PIVector::fill()
inline PIVector2D<T> & fill(const T & e = T()) {
mat.fill(e);
return *this; return *this;
} }
//! \~english Fills the entire 2D array using a generator function `f` based on flat index.
//! \~russian Заполняет весь двумерный массив, используя функцию-генератор `f` на основе плоского индекса.
//! \~\sa PIVector::fill(std::function)
inline PIVector2D<T> & fill(std::function<T(size_t i)> f) {
mat.fill(f);
return *this;
}
//! \~english Same as \a fill().
//! \~russian То же, что и \a fill().
inline PIVector2D<T> & assign(const T & e = T()) { return fill(e); }
//! \~english Assigns new size and fills with value.
//! \~russian Задаёт новый размер и заполняет значением.
//! \~\sa PIVector::assign(size_t, const T&)
inline PIVector2D<T> & assign(size_t rows, size_t cols, const T & f = T()) {
mat.assign(rows * cols, f);
rows_ = rows;
cols_ = cols;
return *this;
}
//! \~english Returns a transposed 2D array (rows become columns and vice versa).
//! \~russian Возвращает транспонированный двумерный массив (строки становятся столбцами и наоборот).
//! \details
//! \~english The element at (r, c) in the original becomes at (c, r) in the result.
//! \~russian Элемент (r, c) исходного массива становится элементом (c, r) в результате.
//! \code
//! PIVector2D<int> mat(2, 3, ...);
//! auto t = mat.transposed(); // now 3x2
//! \endcode
inline PIVector2D<T> transposed() const {
if (isEmpty()) return PIVector2D<T>();
PIVector2D<T> result(cols_, rows_);
for (size_t r = 0; r < rows_; ++r) {
for (size_t c = 0; c < cols_; ++c) {
result.element(c, r) = element(r, c);
}
}
return result;
}
//! \~english Reverses the order of rows in place.
//! \~russian Изменяет порядок строк на обратный на месте.
//! \~\sa reverseColumns(), PIVector::reverse()
inline PIVector2D<T> & reverseRows() {
const size_t half = rows_ / 2;
for (size_t i = 0; i < half; ++i) {
T * row1 = data(i * cols_);
T * row2 = data((rows_ - 1 - i) * cols_);
for (size_t j = 0; j < cols_; ++j) {
piSwap(row1[j], row2[j]);
}
}
return *this;
}
//! \~english Reverses the order of columns in each row in place.
//! \~russian Изменяет порядок столбцов в каждой строке на обратный на месте.
//! \~\sa reverseRows(), PIVector::reverse()
inline PIVector2D<T> & reverseColumns() {
for (size_t r = 0; r < rows_; ++r) {
Row currentRow = row(r);
const size_t half = cols_ / 2;
for (size_t c = 0; c < half; ++c) {
piSwap<T>(currentRow[c], currentRow[cols_ - 1 - c]);
}
}
return *this;
}
//! \~english Returns a sub-2D array (a range of rows and columns).
//! \~russian Возвращает подмассив (диапазон строк и столбцов).
//! \details
//! \~english If the range exceeds the array boundaries, it is clipped. If rowCount or colCount is 0, an empty array is returned.
//! \~russian Если диапазон выходит за границы массива, он обрезается. Если rowCount или colCount равны 0, возвращается пустой массив.
//! \~\sa PIVector::getRange()
inline PIVector2D<T> getRange(size_t rowStart, size_t rowCount, size_t colStart, size_t colCount) const {
if (rowStart >= rows_ || colStart >= cols_ || rowCount == 0 || colCount == 0) return PIVector2D<T>();
const size_t actualRowCount = piMin<size_t>(rowCount, rows_ - rowStart);
const size_t actualColCount = piMin<size_t>(colCount, cols_ - colStart);
PIVector2D<T> result(actualRowCount, actualColCount);
for (size_t r = 0; r < actualRowCount; ++r) {
for (size_t c = 0; c < actualColCount; ++c) {
result.element(r, c) = element(rowStart + r, colStart + c);
}
}
return result;
}
//! \~english Applies a function to each element and returns a new 2D array of a different type.
//! \~russian Применяет функцию к каждому элементу и возвращает новый двумерный массив другого типа.
//! \details
//! \~english The original array is not modified.
//! \~russian Исходный массив не изменяется.
//! \~\sa PIVector::map()
template<typename ST>
inline PIVector2D<ST> map(std::function<ST(const T & e)> f) const {
return PIVector2D<ST>(rows_, cols_, mat.template map<ST>(f));
}
//! \~english Applies a function (with row and col indices) to each element and returns a new 2D array.
//! \~russian Применяет функцию (с индексами строки и столбца) к каждому элементу и возвращает новый двумерный массив.
//! \~\sa PIVector::mapIndexed()
template<typename ST>
inline PIVector2D<ST> mapIndexed(std::function<ST(size_t row, size_t col, const T & e)> f) const {
PIVector<ST> mappedMat;
mappedMat.reserve(size());
for (size_t r = 0; r < rows_; ++r) {
for (size_t c = 0; c < cols_; ++c) {
mappedMat << f(r, c, element(r, c));
}
}
return PIVector2D<ST>(rows_, cols_, std::move(mappedMat));
}
//! \~english Applies a function to each row (modifiable).
//! \~russian Применяет функцию к каждой строке (с возможностью изменения).
//! \~\sa forEachRow() const, PIVector::forEach()
inline PIVector2D<T> & forEachRow(std::function<void(Row)> f) {
for (size_t r = 0; r < rows_; ++r)
f(row(r));
return *this;
}
//! \~english Applies a function to each row (read-only).
//! \~russian Применяет функцию к каждой строке (только чтение).
inline void forEachRow(std::function<void(RowConst)> f) const {
for (size_t r = 0; r < rows_; ++r)
f(row(r));
}
//! \~english Applies a function to each column (modifiable).
//! \~russian Применяет функцию к каждому столбцу (с возможностью изменения).
inline PIVector2D<T> & forEachColumn(std::function<void(Col)> f) {
for (size_t c = 0; c < cols_; ++c)
f(col(c));
return *this;
}
//! \~english Applies a function to each column (read-only).
//! \~russian Применяет функцию к каждому столбцу (только чтение).
//! \param f Function taking a \a ColConst.
inline void forEachColumn(std::function<void(ColConst)> f) const {
for (size_t c = 0; c < cols_; ++c)
f(col(c));
}
//! \~english Accumulates a value across all elements.
//! \~russian Аккумулирует значение по всем элементам.
//! \~\sa PIVector::reduce()
template<typename ST>
inline ST reduce(std::function<ST(const T & e, const ST & acc)> f, const ST & initial = ST()) const {
return mat.template reduce<ST>(f, initial);
}
//! \~english Accumulates a value across all elements with indices.
//! \~russian Аккумулирует значение по всем элементам с индексами.
//! \~\sa PIVector::reduceIndexed()
template<typename ST>
inline ST reduceIndexed(std::function<ST(size_t row, size_t col, const T & e, const ST & acc)> f, const ST & initial = ST()) const {
ST ret(initial);
for (size_t r = 0; r < rows_; ++r) {
for (size_t c = 0; c < cols_; ++c) {
ret = f(r, c, element(r, c), ret);
}
}
return ret;
}
//! \~english Removes a row from the 2D array.
//! \~russian Удаляет строку из двумерного массива.
//! \details
//! \~english If the last row is removed and the array becomes empty, \a cols() is set to 0.
//! \~russian Если удаляется последняя строка и массив становится пустым, \a cols() устанавливается в 0.
//! \~\sa removeColumn(), PIVector::remove()
inline PIVector2D<T> & removeRow(size_t row) { return deleteRows(row, 1); }
//! \~english Removes a column from the 2D array.
//! \~russian Удаляет столбец из двумерного массива.
//! \details
//! \~english This operation is more expensive than removing a row because elements must be moved.
//! \~russian Эта операция дороже, чем удаление строки, поскольку требуется перемещение элементов.
//! \~\sa removeRow(), PIVector::remove()
inline PIVector2D<T> & removeColumn(size_t col) { return deleteColumns(col, 1); }
//! \~english Removes all rows that satisfy a condition.
//! \~russian Удаляет все строки, удовлетворяющие условию.
//! \details
//! \~english Rows are removed from the bottom to avoid index shifting issues.
//! \~russian Строки удаляются снизу вверх, чтобы избежать проблем со смещением индексов.
//! \~\sa removeColumnsWhere(), PIVector::removeWhere()
inline PIVector2D<T> & removeRowsWhere(std::function<bool(const RowConst &)> test) {
ssize_t r = rows_;
while (--r >= 0) {
if (test(RowConst(this, r))) {
removeRow(r);
}
}
return *this;
}
//! \~english Removes all columns that satisfy a condition.
//! \~russian Удаляет все столбцы, удовлетворяющие условию.
//! \~\sa removeRowsWhere()
inline PIVector2D<T> & removeColumnsWhere(std::function<bool(const ColConst &)> test) {
ssize_t c = cols_;
while (--c >= 0) {
if (test(ColConst(this, c))) {
removeColumn(c);
}
}
return *this;
}
//! \~english Returns a new 2D array containing only the rows that pass the test.
//! \~russian Возвращает новый двумерный массив, содержащий только строки, прошедшие проверку.
//! \~\sa filterColumns(), PIVector::filter()
inline PIVector2D<T> filterRows(std::function<bool(const RowConst &)> test) const {
PIVector2D<T> result;
for (size_t r = 0; r < rows_; ++r) {
RowConst currentRow = row(r);
if (test(currentRow)) {
result.addRow(currentRow);
}
}
return result;
}
//! \~english Returns a new 2D array containing only the columns that pass the test.
//! \~russian Возвращает новый двумерный массив, содержащий только столбцы, прошедшие проверку.
//! \~\sa filterRows()
inline PIVector2D<T> filterColumns(std::function<bool(const ColConst &)> test) const {
if (isEmpty()) return PIVector2D<T>();
PIVector<size_t> goodCols;
for (size_t c = 0; c < cols_; ++c) {
if (test(col(c))) {
goodCols << c;
}
}
PIVector2D<T> result;
for (size_t gc = 0; gc < goodCols.size(); ++gc) {
result.addColumn(col(goodCols[gc]));
}
return result;
}
protected: protected:
size_t rows_, cols_; size_t rows_, cols_;
PIVector<T> mat; PIVector<T> mat;
}; };
//! \relatesalso PICout
//! \~english Output operator for \a PIVector2D to \a PICout.
//! \~russian Оператор вывода \a PIVector2D в \a PICout.
template<typename T> template<typename T>
inline PICout operator<<(PICout s, const PIVector2D<T> & v) { inline PICout operator<<(PICout s, const PIVector2D<T> & v) {
s.saveAndSetControls(0); s.saveAndSetControls(0);
@@ -346,5 +1406,6 @@ inline PICout operator<<(PICout s, const PIVector2D<T> & v) {
return s; return s;
} }
//! \}
#endif // PIVECTOR2D_H #endif // PIVECTOR2D_H

View File

@@ -245,6 +245,9 @@ inline constexpr T piAbs(const T & v) {
} }
//! \~\brief
//! \~english Templated function return minimum of two values
//! \~russian Шаблонный метод, возвращающий минимум из двух значений
template<typename T> template<typename T>
constexpr T piMin(const T & f, const T & s) { constexpr T piMin(const T & f, const T & s) {
return ((f > s) ? s : f); return ((f > s) ? s : f);
@@ -282,6 +285,9 @@ constexpr T piMin(const T & f, const T & s, const Args &... args) {
} }
//! \~\brief
//! \~english Templated function return maximum of two values
//! \~russian Шаблонный метод, возвращающий максимум из двух значений
template<typename T> template<typename T>
constexpr T piMax(const T & f, const T & s) { constexpr T piMax(const T & f, const T & s) {
return ((f < s) ? s : f); return ((f < s) ? s : f);

View File

@@ -333,9 +333,10 @@ typedef long long ssize_t;
__PrivateInitializer__ __privateinitializer__; __PrivateInitializer__ __privateinitializer__;
# define PRIVATE_DEFINITION_START(c) struct c::__Private__ { # define PRIVATE_DEFINITION_START(c) struct c::__Private__ {
# define PRIVATE_DEFINITION_END(c) \ # define PRIVATE_DEFINITION_END_NO_INITIALIZE(c) \
} \ } \
; \ ;
# define PRIVATE_DEFINITION_INITIALIZE(c) \
c::__PrivateInitializer__::__PrivateInitializer__() { \ c::__PrivateInitializer__::__PrivateInitializer__() { \
p = new c::__Private__(); \ p = new c::__Private__(); \
} \ } \
@@ -350,6 +351,10 @@ typedef long long ssize_t;
p = new c::__Private__(); \ p = new c::__Private__(); \
return *this; \ return *this; \
} }
# define PRIVATE_DEFINITION_END(c) \
PRIVATE_DEFINITION_END_NO_INITIALIZE \
(c) PRIVATE_DEFINITION_INITIALIZE(c)
# define PRIVATE (__privateinitializer__.p) # define PRIVATE (__privateinitializer__.p)
# define PRIVATEWB __privateinitializer__.p # define PRIVATEWB __privateinitializer__.p

View File

@@ -100,14 +100,14 @@
#endif #endif
//! \ingroup Core /// \~english Helper to collect and retrieve classes to groups.
//! \~\brief /// \~russian Помощник для создания и получения классов в группы.
//! \~english Helper to collect and retrieve classes to groups.
//! \~russian Помощник для создания и получения классов в группы.
class PIP_EXPORT PICollection { class PIP_EXPORT PICollection {
friend class __PICollectionInitializer; friend class __PICollectionInitializer;
public: public:
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
PICollection() { ; } PICollection() { ; }
//! \~english Returns all existing groups by their names //! \~english Returns all existing groups by their names
@@ -118,10 +118,14 @@ public:
//! \~russian Возвращает все элементы группы "group" //! \~russian Возвращает все элементы группы "group"
static PIVector<const PIObject *> groupElements(const PIString & group); static PIVector<const PIObject *> groupElements(const PIString & group);
//! \~english Add element "element" to group "group"
//! \~russian Добавляет элемент "element" в группу "group"
static bool addToGroup(const PIString & group, const PIObject * element); static bool addToGroup(const PIString & group, const PIObject * element);
class PIP_EXPORT CollectionAdder { class PIP_EXPORT CollectionAdder {
public: public:
//! \~english Constructor that adds element to group
//! \~russian Конструктор, который добавляет элемент в группу
CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false); CollectionAdder(const PIString & group, const PIObject * element, const PIString & name = PIString(), bool own = false);
}; };

View File

@@ -64,7 +64,16 @@ PIP_EXPORT PIString errorString();
//! \~russian Сброс последней ошибки //! \~russian Сброс последней ошибки
PIP_EXPORT void errorClear(); PIP_EXPORT void errorClear();
//! \ingroup Core
//! \brief
//! \~english Initialize random number generator
//! \~russian Инициализация генератора случайных чисел
PIP_EXPORT void randomize(); PIP_EXPORT void randomize();
//! \ingroup Core
//! \brief
//! \~english Returns random integer value
//! \~russian Возвращает случайное целое число
PIP_EXPORT int randomi(); PIP_EXPORT int randomi();
//! \ingroup Core //! \ingroup Core

View File

@@ -1,10 +1,13 @@
/*! \file piinit.h //! \addtogroup Core
* \ingroup Core //! \{
* \~\brief //! \file piinit.h
* \~english Library initialization //! \brief
* \~russian Инициализация библиотеки //! \~english Library initialization
*/ //! \~russian Инициализация библиотеки
/* //! \details
//! \~english This file provides initialization and build information for the PIP library.
//! \~russian Этот файл предоставляет инициализацию и информацию о сборке для библиотеки PIP.
/*!
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Initialization Initialization
Ivan Pelipenko peri4ko@yandex.ru Ivan Pelipenko peri4ko@yandex.ru
@@ -37,6 +40,8 @@ class PIFile;
class PIStringList; class PIStringList;
//! \~english Internal initializer class for automatic library initialization
//! \~russian Внутренний класс инициализации для автоматической инициализации библиотеки
class PIP_EXPORT __PIInit_Initializer__ { class PIP_EXPORT __PIInit_Initializer__ {
public: public:
__PIInit_Initializer__(); __PIInit_Initializer__();
@@ -48,6 +53,8 @@ public:
static __PIInit_Initializer__ __piinit_initializer__; static __PIInit_Initializer__ __piinit_initializer__;
//! \~english Provides library initialization and build information
//! \~russian Предоставляет инициализацию библиотеки и информацию о сборке
class PIP_EXPORT PIInit { class PIP_EXPORT PIInit {
friend class __PIInit_Initializer__; friend class __PIInit_Initializer__;
friend class PIFile; friend class PIFile;
@@ -69,6 +76,8 @@ public:
boCloud /*! \~english PICloud transport support \~russian Поддержка облачного транспорта PICloud */ = 0x200, boCloud /*! \~english PICloud transport support \~russian Поддержка облачного транспорта PICloud */ = 0x200,
boConsole /*! \~english Console graphics support \~russian Поддержка графики в консоли */ = 0x400, boConsole /*! \~english Console graphics support \~russian Поддержка графики в консоли */ = 0x400,
}; };
//! \~english Returns singleton instance of PIInit
//! \~russian Возвращает синглтон экземпляр PIInit
static PIInit * instance() { return __PIInit_Initializer__::__instance__; } static PIInit * instance() { return __PIInit_Initializer__::__instance__; }
//! \ingroup Core //! \ingroup Core
@@ -89,4 +98,5 @@ private:
#endif // MICRO_PIP #endif // MICRO_PIP
//! \}
#endif // PIINIT_H #endif // PIINIT_H

View File

@@ -45,11 +45,15 @@ public:
s = size_; s = size_;
} }
//! \~english Copy constructor
//! \~russian Конструктор копирования
PIMemoryBlock(const PIMemoryBlock & o) { PIMemoryBlock(const PIMemoryBlock & o) {
d = o.d; d = o.d;
s = o.s; s = o.s;
} }
//! \~english Assignment operator
//! \~russian Оператор присваивания
PIMemoryBlock & operator=(const PIMemoryBlock & o) { PIMemoryBlock & operator=(const PIMemoryBlock & o) {
d = o.d; d = o.d;
s = o.s; s = o.s;

View File

@@ -1,9 +1,15 @@
/*! \file piobject.h //! \addtogroup Core
* \ingroup Core //! \{
* \~\brief //! \file piobject.h
* \~english Base object //! \brief
* \~russian Базовый класс //! \~english Base object class providing event -> handler mechanism
*/ //! \~russian Базовый класс объектов, обеспечивающий механизм событий -> обработчиков
//! \details
//! \~english PIObject is the base class for all PIP classes that need event-driven communication.
//! It provides signal-slot mechanism, property system, and object lifetime management.
//! \~russian PIObject является базовым классом для всех классов PIP, которым необходима событийная коммуникация.
//! Он обеспечивает механизм сигналов-слотов, систему свойств и управление жизненным циклом объектов.
//! \~
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
@@ -34,10 +40,8 @@
#include "pivariant.h" #include "pivariant.h"
#include "pivariantsimple.h" #include "pivariantsimple.h"
//! \ingroup Core //! \~english Base class for classes using event -> handler mechanism
//! \~\brief //! \~russian Базовый класс для классов, использующих механизм событий -> обработчиков
//! \~english This is base class for any classes which use events -> handlers mechanism.
//! \~russian Этот класс является базовым для использования механизма события -> обработчики.
class PIP_EXPORT PIObject { class PIP_EXPORT PIObject {
#ifndef MICRO_PIP #ifndef MICRO_PIP
friend class PIObjectManager; friend class PIObjectManager;
@@ -50,7 +54,7 @@ class PIP_EXPORT PIObject {
public: public:
NO_COPY_CLASS(PIObject); NO_COPY_CLASS(PIObject);
//! \~english Contructs %PIObject with name "name" //! \~english Constructs %PIObject with name "name"
//! \~russian Создает %PIObject с именем "name" //! \~russian Создает %PIObject с именем "name"
explicit PIObject(const PIString & name = PIString()); explicit PIObject(const PIString & name = PIString());
@@ -93,7 +97,7 @@ public:
int args_count; int args_count;
public: public:
//! \~english Contructs invalid %Connection //! \~english Constructs invalid %Connection
//! \~russian Создает недействительный %Connection //! \~russian Создает недействительный %Connection
Connection(); Connection();
@@ -175,17 +179,31 @@ public:
bool isPropertyExists(const char * name) const { return properties_.contains(piHashData((const uchar *)name, strlen(name))); } bool isPropertyExists(const char * name) const { return properties_.contains(piHashData((const uchar *)name, strlen(name))); }
void setThreadSafe(bool yes) { thread_safe_ = yes; } void setThreadSafe(bool yes) { thread_safe_ = yes; }
//! \~english Returns if object is thread safe
//! \~russian Возвращает является ли объект потокобезопасным
bool isThreadSafe() const { return thread_safe_; } bool isThreadSafe() const { return thread_safe_; }
//! \~english Executes method with specified arguments
//! \~russian Выполняет метод с указанными аргументами
bool execute(const PIString & method, const PIVector<PIVariantSimple> & vl); bool execute(const PIString & method, const PIVector<PIVariantSimple> & vl);
//! \~english Executes method without arguments
//! \~russian Выполняет метод без аргументов
bool execute(const PIString & method) { return execute(method, PIVector<PIVariantSimple>()); } bool execute(const PIString & method) { return execute(method, PIVector<PIVariantSimple>()); }
//! \~english Executes method with one argument
//! \~russian Выполняет метод с одним аргументом
bool execute(const PIString & method, const PIVariantSimple & v0) { return execute(method, PIVector<PIVariantSimple>() << v0); } bool execute(const PIString & method, const PIVariantSimple & v0) { return execute(method, PIVector<PIVariantSimple>() << v0); }
//! \~english Executes method with two arguments
//! \~russian Выполняет метод с двумя аргументами
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) { bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return execute(method, PIVector<PIVariantSimple>() << v0 << v1); return execute(method, PIVector<PIVariantSimple>() << v0 << v1);
} }
//! \~english Executes method with three arguments
//! \~russian Выполняет метод с тремя аргументами
bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { bool execute(const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {
return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2); return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
} }
//! \~english Executes method with four arguments
//! \~russian Выполняет метод с четырьмя аргументами
bool execute(const PIString & method, bool execute(const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
const PIVariantSimple & v1, const PIVariantSimple & v1,
@@ -194,16 +212,26 @@ public:
return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return execute(method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Executes method queued with performer
//! \~russian Выполняет метод в очереди с исполнителем
bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl); bool executeQueued(PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl);
//! \~english Executes method without arguments queued with performer
//! \~russian Выполняет метод без аргументов в очереди с исполнителем
bool executeQueued(PIObject * performer, const PIString & method) { bool executeQueued(PIObject * performer, const PIString & method) {
return executeQueued(performer, method, PIVector<PIVariantSimple>()); return executeQueued(performer, method, PIVector<PIVariantSimple>());
} }
//! \~english Executes method with one argument queued with performer
//! \~russian Выполняет метод с одним аргументом в очереди с исполнителем
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0) { bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0);
} }
//! \~english Executes method with two arguments queued with performer
//! \~russian Выполняет метод с двумя аргументами в очереди с исполнителем
bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) { bool executeQueued(PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1);
} }
//! \~english Executes method with three arguments queued with performer
//! \~russian Выполняет метод с тремя аргументами в очереди с исполнителем
bool executeQueued(PIObject * performer, bool executeQueued(PIObject * performer,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -211,6 +239,8 @@ public:
const PIVariantSimple & v2) { const PIVariantSimple & v2) {
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
} }
//! \~english Executes method with four arguments queued with performer
//! \~russian Выполняет метод с четырьмя аргументами в очереди с исполнителем
bool executeQueued(PIObject * performer, bool executeQueued(PIObject * performer,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -220,18 +250,30 @@ public:
return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return executeQueued(performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Executes method on object with specified arguments
//! \~russian Выполняет метод на объекте с указанными аргументами
static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariantSimple> & vl) { return o->execute(method, vl); } static bool execute(PIObject * o, const PIString & method, const PIVector<PIVariantSimple> & vl) { return o->execute(method, vl); }
//! \~english Executes method on object without arguments
//! \~russian Выполняет метод на объекте без аргументов
static bool execute(PIObject * o, const PIString & method) { return execute(o, method, PIVector<PIVariantSimple>()); } static bool execute(PIObject * o, const PIString & method) { return execute(o, method, PIVector<PIVariantSimple>()); }
//! \~english Executes method on object with one argument
//! \~russian Выполняет метод на объекте с одним аргументом
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0) { static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0) {
return execute(o, method, PIVector<PIVariantSimple>() << v0); return execute(o, method, PIVector<PIVariantSimple>() << v0);
} }
//! \~english Executes method on object with two arguments
//! \~russian Выполняет метод на объекте с двумя аргументами
static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) { static bool execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1); return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1);
} }
//! \~english Executes method on object with three arguments
//! \~russian Выполняет метод на объекте с тремя аргументами
static bool static bool
execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) { execute(PIObject * o, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1, const PIVariantSimple & v2) {
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2); return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
} }
//! \~english Executes method on object with four arguments
//! \~russian Выполняет метод на объекте с четырьмя аргументами
static bool execute(PIObject * o, static bool execute(PIObject * o,
const PIString & method, const PIString & method,
const PIVariantSimple & v0, const PIVariantSimple & v0,
@@ -241,19 +283,29 @@ public:
return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return execute(o, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Executes method on object queued with performer
//! \~russian Выполняет метод на объекте в очереди с исполнителем
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) { static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVector<PIVariantSimple> & vl) {
return o->executeQueued(performer, method, vl); return o->executeQueued(performer, method, vl);
} }
//! \~english Executes method on object without arguments queued with performer
//! \~russian Выполняет метод на объекте без аргументов в очереди с исполнителем
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) { static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>()); return executeQueued(o, performer, method, PIVector<PIVariantSimple>());
} }
//! \~english Executes method on object with one argument queued with performer
//! \~russian Выполняет метод на объекте с одним аргументом в очереди с исполнителем
static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0) { static bool executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0); return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0);
} }
//! \~english Executes method on object with two arguments queued with performer
//! \~russian Выполняет метод на объекте с двумя аргументами в очереди с исполнителем
static bool static bool
executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) { executeQueued(PIObject * o, PIObject * performer, const PIString & method, const PIVariantSimple & v0, const PIVariantSimple & v1) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1); return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1);
} }
//! \~english Executes method on object with three arguments queued with performer
//! \~russian Выполняет метод на объекте с тремя аргументами в очереди с исполнителем
static bool executeQueued(PIObject * o, static bool executeQueued(PIObject * o,
PIObject * performer, PIObject * performer,
const PIString & method, const PIString & method,
@@ -262,6 +314,8 @@ public:
const PIVariantSimple & v2) { const PIVariantSimple & v2) {
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2); return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2);
} }
//! \~english Executes method on object with four arguments queued with performer
//! \~russian Выполняет метод на объекте с четырьмя аргументами в очереди с исполнителем
static bool executeQueued(PIObject * o, static bool executeQueued(PIObject * o,
PIObject * performer, PIObject * performer,
const PIString & method, const PIString & method,
@@ -272,6 +326,8 @@ public:
return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3); return executeQueued(o, performer, method, PIVector<PIVariantSimple>() << v0 << v1 << v2 << v3);
} }
//! \~english Dumps object information
//! \~russian Выводит информацию об объекте
void dump(const PIString & line_prefix = PIString()) const; void dump(const PIString & line_prefix = PIString()) const;
@@ -279,10 +335,20 @@ public:
//! \~russian Возвращает цепочку наследования объекта (вместе с классом самого объекта) //! \~russian Возвращает цепочку наследования объекта (вместе с классом самого объекта)
PIStringList scopeList() const; PIStringList scopeList() const;
//! \~english Returns list of all event-handler methods
//! \~russian Возвращает список всех методов-обработчиков событий
PIStringList methodsEH() const; PIStringList methodsEH() const;
//! \~english Returns if method "name" is event-handler
//! \~russian Возвращает является ли метод "name" обработчиком событий
bool isMethodEHContains(const PIString & name) const; bool isMethodEHContains(const PIString & name) const;
//! \~english Returns arguments of event-handler method "name"
//! \~russian Возвращает аргументы метода-обработчика событий "name"
PIString methodEHArguments(const PIString & name) const; PIString methodEHArguments(const PIString & name) const;
//! \~english Returns full format of event-handler method "name"
//! \~russian Возвращает полный формат метода-обработчика событий "name"
PIString methodEHFullFormat(const PIString & name) const; PIString methodEHFullFormat(const PIString & name) const;
//! \~english Returns event-handler method name from address "addr"
//! \~russian Возвращает имя метода-обработчика событий по адресу "addr"
PIString methodEHFromAddr(const void * addr) const; PIString methodEHFromAddr(const void * addr) const;
// / Direct connect // / Direct connect
@@ -542,6 +608,8 @@ public:
//! \~english Returns if "o" is valid %PIObject (check signature) //! \~english Returns if "o" is valid %PIObject (check signature)
//! \~russian Возвращает действительный ли "o" %PIObject (проверяет подпись) //! \~russian Возвращает действительный ли "o" %PIObject (проверяет подпись)
static bool isPIObject(const PIObject * o); static bool isPIObject(const PIObject * o);
//! \~english Returns if "o" is valid %PIObject (check signature)
//! \~russian Возвращает действительный ли "o" %PIObject (проверяет подпись)
static bool isPIObject(const void * o) { return isPIObject((PIObject *)o); } static bool isPIObject(const void * o) { return isPIObject((PIObject *)o); }
//! \~english Returns if "o" is valid %PIObject subclass "T" (check signature and classname) //! \~english Returns if "o" is valid %PIObject subclass "T" (check signature and classname)
@@ -554,6 +622,8 @@ public:
static bool isTypeOf(const void * o) { static bool isTypeOf(const void * o) {
return isTypeOf<T>((PIObject *)o); return isTypeOf<T>((PIObject *)o);
} }
//! \~english Simplifies type name "a" to readable format
//! \~russian Упрощает имя типа "a" в читаемый формат
static PIString simplifyType(const char * a, bool readable = true); static PIString simplifyType(const char * a, bool readable = true);
struct PIP_EXPORT __MetaFunc { struct PIP_EXPORT __MetaFunc {

View File

@@ -1,8 +1,12 @@
/*! \file piauth.h /*! \file piauth.h
* \ingroup Crypt * \addtogroup Crypt
* \~\brief * \{
* \~english Authentication API * \brief Authentication API
* \~russian API аутентификации * \~english Authentication API for client-server key exchange and authentication
* \~russian API аутентификации для обмена ключами и аутентификации клиент-сервер
* \details
* \~english Provides classes for secure client-server authentication with digital signatures, password verification, and key exchange
* \~russian Предоставляет классы для безопасной клиент-серверной аутентификации с цифровыми подписями, проверкой пароля и обменом ключами
*/ */
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
@@ -31,70 +35,106 @@
#include "pip_crypt_export.h" #include "pip_crypt_export.h"
//! \~english Authentication and key exchange class
//! \~russian Класс аутентификации и обмена ключами
class PIP_CRYPT_EXPORT PIAuth: public PIObject { class PIP_CRYPT_EXPORT PIAuth: public PIObject {
PIOBJECT(PIAuth) PIOBJECT(PIAuth)
public: public:
//! \~english Authentication state
//! \~russian Состояние аутентификации
enum State { enum State {
NotConnected, NotConnected, //!< \~english Not connected \~russian Не подключен
AuthProbe, AuthProbe, //!< \~english Authentication probe \~russian Зондирование аутентификации
PassRequest, PassRequest, //!< \~english Password request \~russian Запрос пароля
AuthReply, AuthReply, //!< \~english Authentication reply \~russian Ответ аутентификации
KeyExchange, KeyExchange, //!< \~english Key exchange \~russian Обмен ключами
Connected Connected //!< \~english Connected, authenticated \~russian Подключено, аутентифицировано
}; };
//! Create PIAuth with your digital sign //! \~english Create PIAuth with your digital sign
//! \~russian Создать PIAuth с вашей цифровой подписью
//! \param sign \~english Digital sign private key \~russian Приватный ключ цифровой подписи
PIAuth(const PIByteArray & sign); PIAuth(const PIByteArray & sign);
//! Set server info data for client authorize event //! \~english Set server info data for client authorize event
//! \~russian Установить информационные данные сервера для события авторизации клиента
//! \param info \~english Info data \~russian Информационные данные
void setInfoData(const PIByteArray & info) { custom_info = info; } void setInfoData(const PIByteArray & info) { custom_info = info; }
//! Set server password for check //! \~english Set server password for check
//! \~russian Установить пароль сервера для проверки
//! \param ps \~english Server password \~russian Пароль сервера
void setServerPassword(const PIString & ps); void setServerPassword(const PIString & ps);
//! Set list of trusted clients/servers public digital sign keys //! \~english Set list of trusted clients/servers public digital sign keys
//! \~russian Установить список доверенных публичных ключей цифровой подписи клиентов/серверов
//! \param pkeys \~english List of public keys \~russian Список публичных ключей
void setAuthorizedPublicKeys(const PIVector<PIByteArray> & pkeys) { auth_pkeys = pkeys; } void setAuthorizedPublicKeys(const PIVector<PIByteArray> & pkeys) { auth_pkeys = pkeys; }
//! Get list of trusted clients/servers public digital sign keys //! \~english Get list of trusted clients/servers public digital sign keys
//! \~russian Получить список доверенных публичных ключей цифровой подписи клиентов/серверов
//! \return \~english List of public keys \~russian Список публичных ключей
PIVector<PIByteArray> getAuthorizedPublicKeys() { return auth_pkeys; } PIVector<PIByteArray> getAuthorizedPublicKeys() { return auth_pkeys; }
//! Get your digital sign public key //! \~english Get your digital sign public key
//! \~russian Получить ваш публичный ключ цифровой подписи
//! \return Public sign key \~english Публичный ключ подписи
PIByteArray getSignPublicKey() { return sign_pk; } PIByteArray getSignPublicKey() { return sign_pk; }
//! Stop authorization //! \~english Stop authorization
//! \~russian Остановить авторизацию
void stop(); void stop();
//! Start authorization as client //! \~english Start authorization as client
//! \~russian Начать авторизацию как клиент
void startClient(); void startClient();
//! Start authorization as server, return first server message for client //! \~english Start authorization as server, return first server message for client
//! \~russian Начать авторизацию как сервер, вернуть первое сообщение сервера для клиента
//! \return \~english First server message \~russian Первое сообщение сервера
PIByteArray startServer(); PIByteArray startServer();
//! Process reseived message both for client and server, return current state and new message writed in "ba" //! \~english Process received message both for client and server, return current state and new message written in "ba"
//! \~russian Обработать полученное сообщение как для клиента, так и для сервера, вернуть текущее состояние и новое сообщение в "ba"
//! \param ba \~english Message to process, output message \~russian Сообщение для обработки, выходное сообщение
//! \return \~english Current authentication state \~russian Текущее состояние аутентификации
State receive(PIByteArray & ba); State receive(PIByteArray & ba);
//! Get session secret key, return key only when Connected state //! \~english Get session secret key, return key only when Connected state
//! \~russian Получить секретный ключ сессии, вернуть ключ только в состоянии Connected
//! \return \~english Session secret key \~russian Секретный ключ сессии
//! \note
//! \~english Returns empty array if not connected
//! \~russian Возвращает пустой массив если не подключен
PIByteArray getSecretKey(); PIByteArray getSecretKey();
//! Generate digital sign from seed //! \~english Generate digital sign from seed
//! \~russian Сгенерировать цифровую подпись из зерна
//! \param seed \~english Seed for key generation \~russian Зерно для генерации ключа
//! \return \~english Generated digital sign key \~russian Сгенерированный ключ цифровой подписи
static PIByteArray generateSign(const PIByteArray & seed); static PIByteArray generateSign(const PIByteArray & seed);
//! Disconneted event //! \~english Disconnected event
//! \~russian Событие отключения
EVENT1(disconnected, PIString, reason); EVENT1(disconnected, PIString, reason);
//! Conneted event //! \~english Connected event
//! \~russian Событие подключения
EVENT1(connected, PIString, info); EVENT1(connected, PIString, info);
//! Client event for authorize new server //! \~english Client event for authorize new server
//! \~russian Событие клиента для авторизации нового сервера
EVENT2(authorize, PIByteArray, info, bool *, ok); EVENT2(authorize, PIByteArray, info, bool *, ok);
//! Client event for input server password //! \~english Client event for input server password
//! \~russian Событие клиента для ввода пароля сервера
EVENT1(passwordRequest, PIString *, pass); EVENT1(passwordRequest, PIString *, pass);
//! Server event on check client password //! \~english Server event on check client password
//! \~russian Событие сервера при проверке пароля клиента
EVENT1(passwordCheck, bool, result); EVENT1(passwordCheck, bool, result);
private: private:

View File

@@ -40,6 +40,9 @@ public:
//! \~russian Конструктор, генерирующий случайный ключ //! \~russian Конструктор, генерирующий случайный ключ
PICrypt(); PICrypt();
//! \~\brief
//! \~english Destructor
//! \~russian Деструктор
~PICrypt(); ~PICrypt();
//! \~\brief //! \~\brief

View File

@@ -25,6 +25,7 @@
#include "pidigest_md5_p.h" #include "pidigest_md5_p.h"
#include "pidigest_sha1_p.h" #include "pidigest_sha1_p.h"
#include "pidigest_sha2_p.h" #include "pidigest_sha2_p.h"
#include "pidigest_siphash_p.h"
int PIDigest::hashLength(Type type) { int PIDigest::hashLength(Type type) {
@@ -49,6 +50,10 @@ int PIDigest::hashLength(Type type) {
case Type::BLAKE2b_256: return 32; case Type::BLAKE2b_256: return 32;
case Type::BLAKE2b_384: return 48; case Type::BLAKE2b_384: return 48;
case Type::BLAKE2b_512: return 64; case Type::BLAKE2b_512: return 64;
case Type::SipHash_2_4_64: return 8;
case Type::SipHash_2_4_128: return 16;
case Type::HalfSipHash_2_4_32: return 4;
case Type::HalfSipHash_2_4_64: return 8;
default: break; default: break;
} }
return 0; return 0;
@@ -77,6 +82,10 @@ int PIDigest::blockLength(Type type) {
case Type::BLAKE2b_256: case Type::BLAKE2b_256:
case Type::BLAKE2b_384: case Type::BLAKE2b_384:
case Type::BLAKE2b_512: return 128; case Type::BLAKE2b_512: return 128;
case Type::SipHash_2_4_64: return 8;
case Type::SipHash_2_4_128: return 16;
case Type::HalfSipHash_2_4_32: return 4;
case Type::HalfSipHash_2_4_64: return 8;
default: break; default: break;
} }
return 0; return 0;
@@ -105,6 +114,10 @@ PIConstChars PIDigest::typeName(Type type) {
case Type::BLAKE2b_256: return "BLAKE2b_256"; case Type::BLAKE2b_256: return "BLAKE2b_256";
case Type::BLAKE2b_384: return "BLAKE2b_384"; case Type::BLAKE2b_384: return "BLAKE2b_384";
case Type::BLAKE2b_512: return "BLAKE2b_512"; case Type::BLAKE2b_512: return "BLAKE2b_512";
case Type::SipHash_2_4_64: return "SipHash_2_4_64";
case Type::SipHash_2_4_128: return "SipHash_2_4_128";
case Type::HalfSipHash_2_4_32: return "HalfSipHash_2_4_32";
case Type::HalfSipHash_2_4_64: return "HalfSipHash_2_4_64";
default: break; default: break;
} }
return "Unknown"; return "Unknown";
@@ -123,16 +136,42 @@ PIByteArray PIDigest::calculate(const PIByteArray & msg, Type type) {
case Type::SHA2_512: return SHA2::sha5xx(msg, SHA2::initial_512, 64); case Type::SHA2_512: return SHA2::sha5xx(msg, SHA2::initial_512, 64);
case Type::SHA2_512_224: return SHA2::sha5xx(msg, SHA2::initial_512_224, 28); case Type::SHA2_512_224: return SHA2::sha5xx(msg, SHA2::initial_512_224, 28);
case Type::SHA2_512_256: return SHA2::sha5xx(msg, SHA2::initial_512_256, 32); case Type::SHA2_512_256: return SHA2::sha5xx(msg, SHA2::initial_512_256, 32);
case Type::BLAKE2s_128: return BLAKE2::blake2s(msg, 16); case Type::BLAKE2s_128: return BLAKE2::blake2s(msg, {}, 16);
case Type::BLAKE2s_160: return BLAKE2::blake2s(msg, 20); case Type::BLAKE2s_160: return BLAKE2::blake2s(msg, {}, 20);
case Type::BLAKE2s_224: return BLAKE2::blake2s(msg, 28); case Type::BLAKE2s_224: return BLAKE2::blake2s(msg, {}, 28);
case Type::BLAKE2s_256: return BLAKE2::blake2s(msg, 32); case Type::BLAKE2s_256: return BLAKE2::blake2s(msg, {}, 32);
case Type::BLAKE2b_128: return BLAKE2::blake2b(msg, 16); case Type::BLAKE2b_128: return BLAKE2::blake2b(msg, {}, 16);
case Type::BLAKE2b_160: return BLAKE2::blake2b(msg, 20); case Type::BLAKE2b_160: return BLAKE2::blake2b(msg, {}, 20);
case Type::BLAKE2b_224: return BLAKE2::blake2b(msg, 28); case Type::BLAKE2b_224: return BLAKE2::blake2b(msg, {}, 28);
case Type::BLAKE2b_256: return BLAKE2::blake2b(msg, 32); case Type::BLAKE2b_256: return BLAKE2::blake2b(msg, {}, 32);
case Type::BLAKE2b_384: return BLAKE2::blake2b(msg, 48); case Type::BLAKE2b_384: return BLAKE2::blake2b(msg, {}, 48);
case Type::BLAKE2b_512: return BLAKE2::blake2b(msg, 64); case Type::BLAKE2b_512: return BLAKE2::blake2b(msg, {}, 64);
case Type::SipHash_2_4_64: return SipHash::siphash(msg, {}, 8);
case Type::SipHash_2_4_128: return SipHash::siphash(msg, {}, 16);
case Type::HalfSipHash_2_4_32: return SipHash::halfsiphash(msg, {}, 4);
case Type::HalfSipHash_2_4_64: return SipHash::halfsiphash(msg, {}, 8);
default: break;
}
return {};
}
PIByteArray PIDigest::calculateWithKey(const PIByteArray & msg, const PIByteArray & key, Type type) {
switch (type) {
case Type::BLAKE2s_128: return BLAKE2::blake2s(msg, key, 16);
case Type::BLAKE2s_160: return BLAKE2::blake2s(msg, key, 20);
case Type::BLAKE2s_224: return BLAKE2::blake2s(msg, key, 28);
case Type::BLAKE2s_256: return BLAKE2::blake2s(msg, key, 32);
case Type::BLAKE2b_128: return BLAKE2::blake2b(msg, key, 16);
case Type::BLAKE2b_160: return BLAKE2::blake2b(msg, key, 20);
case Type::BLAKE2b_224: return BLAKE2::blake2b(msg, key, 28);
case Type::BLAKE2b_256: return BLAKE2::blake2b(msg, key, 32);
case Type::BLAKE2b_384: return BLAKE2::blake2b(msg, key, 48);
case Type::BLAKE2b_512: return BLAKE2::blake2b(msg, key, 64);
case Type::SipHash_2_4_64: return SipHash::siphash(msg, key, 8);
case Type::SipHash_2_4_128: return SipHash::siphash(msg, key, 16);
case Type::HalfSipHash_2_4_32: return SipHash::halfsiphash(msg, key, 4);
case Type::HalfSipHash_2_4_64: return SipHash::halfsiphash(msg, key, 8);
default: break; default: break;
} }
return {}; return {};

View File

@@ -1,15 +1,16 @@
/*! \file pidigest.h //! \addtogroup Core
* \ingroup Core //! \{
* \~\brief //! \file pidigest.h
* \~english Digest algorithms //! \brief
* \~russian Алгоритмы хэш-сумм //! \~english Digest algorithms
* //! \~russian Алгоритмы хэш-сумм
* \~\details //!
* \~english //! \details
* This file implements several common-usage hash algorithms //! \~english
* \~russian //! This file implements several common-usage hash algorithms
* Этот файл реализует несколько распространенных алгоритмов хэширования //! \~russian
*/ //! Этот файл реализует несколько распространенных алгоритмов хэширования
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Digest algorithms Digest algorithms
@@ -37,17 +38,29 @@
class PIP_EXPORT PIDigest { class PIP_EXPORT PIDigest {
public: public:
//! \~english Hash algorithm type
//! \~russian Тип алгоритма хэширования
//! \details
//! \~english
//! Supported algorithms: SHA1, SHA2 family (224, 256, 384, 512, 512_224, 512_256),
//! MD2, MD4, MD5, BLAKE2s, BLAKE2b, SipHash
//! \~russian
//! Поддерживаемые алгоритмы: SHA1, семейство SHA2 (224, 256, 384, 512, 512_224, 512_256),
//! MD2, MD4, MD5, BLAKE2s, BLAKE2b, SipHash
enum class Type { enum class Type {
SHA1, SHA1,
SHA2_224, SHA2_224,
SHA2_256, SHA2_256,
SHA2_384, SHA2_384,
SHA2_512, SHA2_512,
SHA2_512_224, SHA2_512_224,
SHA2_512_256, SHA2_512_256,
MD2, MD2,
MD4, MD4,
MD5, MD5,
BLAKE2s_128, BLAKE2s_128,
BLAKE2s_160, BLAKE2s_160,
BLAKE2s_224, BLAKE2s_224,
@@ -58,15 +71,54 @@ public:
BLAKE2b_256, BLAKE2b_256,
BLAKE2b_384, BLAKE2b_384,
BLAKE2b_512, BLAKE2b_512,
SipHash_2_4_64,
SipHash_2_4_128,
HalfSipHash_2_4_32,
HalfSipHash_2_4_64,
Count, Count,
}; };
//! \~english Get hash output length in bytes
//! \~russian Получить длину хэша в байтах
static int hashLength(Type type); static int hashLength(Type type);
//! \~english Get hash block length in bytes
//! \~russian Получить длину блока хэширования в байтах
static int blockLength(Type type); static int blockLength(Type type);
//! \~english Get algorithm name as string
//! \~russian Получить название алгоритма в виде строки
//! \return Algorithm name
//! \sa Type
static PIConstChars typeName(Type type); static PIConstChars typeName(Type type);
//! \~english Calculate hash of message
//! \~russian Вычислить хэш сообщения
//! \param msg Input message
//! \param type Hash algorithm type
//! \return Hash bytes
//! \sa calculateWithKey, HMAC
static PIByteArray calculate(const PIByteArray & msg, Type type); static PIByteArray calculate(const PIByteArray & msg, Type type);
//! \~english Calculate keyed hash of message
//! \~russian Вычислить ключевой хэш сообщения
//! \param msg Input message
//! \param key Secret key
//! \param type Hash algorithm type (SipHash or BLAKE2)
//! \return Hash bytes
//! \note Only SipHash and BLAKE2 algorithms support keyed hashing
//! \sa calculate, HMAC
static PIByteArray calculateWithKey(const PIByteArray & msg, const PIByteArray & key, Type type);
//! \~english Calculate HMAC (Keyed-Hash Message Authentication Code)
//! \~russian Вычислить HMAC (код аутентификации сообщений на основе ключа)
//! \param msg Input message
//! \param key Secret key
//! \param type Hash algorithm type
//! \return HMAC bytes
//! \note Supports SHA1, SHA2 and MD5 algorithms
//! \sa calculate, calculateWithKey
static PIByteArray HMAC(const PIByteArray & msg, const PIByteArray & key, PIDigest::Type type); static PIByteArray HMAC(const PIByteArray & msg, const PIByteArray & key, PIDigest::Type type);
}; };
//! \}
#endif #endif

View File

@@ -21,44 +21,18 @@
#include "3rd/BLAKE2/blake2.h" #include "3rd/BLAKE2/blake2.h"
#define IMPLEMENT(func, key_len) \
PIByteArray BLAKE2::func(const PIByteArray & in, const PIByteArray & key, int out_bytes) { \
PIByteArray ret(out_bytes); \
::func(ret.data(), ret.size(), in.data(), in.size(), key.isEmpty() ? nullptr : key.data(), piMini(key.size(), key_len)); \
return ret; \
}
PIByteArray BLAKE2::blake2s(const PIByteArray & in, int out_bytes) { IMPLEMENT(blake2s, BLAKE2S_KEYBYTES)
PIByteArray ret(out_bytes); IMPLEMENT(blake2b, BLAKE2B_KEYBYTES)
::blake2s(ret.data(), ret.size(), in.data(), in.size(), nullptr, 0); IMPLEMENT(blake2sp, BLAKE2S_KEYBYTES)
return ret; IMPLEMENT(blake2bp, BLAKE2B_KEYBYTES)
} IMPLEMENT(blake2xs, BLAKE2S_KEYBYTES)
IMPLEMENT(blake2xb, BLAKE2B_KEYBYTES)
#undef IMPLEMENT
PIByteArray BLAKE2::blake2b(const PIByteArray & in, int out_bytes) {
PIByteArray ret(out_bytes);
::blake2b(ret.data(), ret.size(), in.data(), in.size(), nullptr, 0);
return ret;
}
PIByteArray BLAKE2::blake2sp(const PIByteArray & in, int out_bytes) {
PIByteArray ret(out_bytes);
::blake2sp(ret.data(), ret.size(), in.data(), in.size(), nullptr, 0);
return ret;
}
PIByteArray BLAKE2::blake2bp(const PIByteArray & in, int out_bytes) {
PIByteArray ret(out_bytes);
::blake2bp(ret.data(), ret.size(), in.data(), in.size(), nullptr, 0);
return ret;
}
PIByteArray BLAKE2::blake2xs(const PIByteArray & in, int out_bytes) {
PIByteArray ret(out_bytes);
::blake2xs(ret.data(), ret.size(), in.data(), in.size(), nullptr, 0);
return ret;
}
PIByteArray BLAKE2::blake2xb(const PIByteArray & in, int out_bytes) {
PIByteArray ret(out_bytes);
::blake2xb(ret.data(), ret.size(), in.data(), in.size(), nullptr, 0);
return ret;
}

View File

@@ -24,12 +24,12 @@
class BLAKE2 { class BLAKE2 {
public: public:
static PIByteArray blake2s(const PIByteArray & in, int out_bytes); static PIByteArray blake2s(const PIByteArray & in, const PIByteArray & key, int out_bytes);
static PIByteArray blake2b(const PIByteArray & in, int out_bytes); static PIByteArray blake2b(const PIByteArray & in, const PIByteArray & key, int out_bytes);
static PIByteArray blake2sp(const PIByteArray & in, int out_bytes); static PIByteArray blake2sp(const PIByteArray & in, const PIByteArray & key, int out_bytes);
static PIByteArray blake2bp(const PIByteArray & in, int out_bytes); static PIByteArray blake2bp(const PIByteArray & in, const PIByteArray & key, int out_bytes);
static PIByteArray blake2xs(const PIByteArray & in, int out_bytes); static PIByteArray blake2xs(const PIByteArray & in, const PIByteArray & key, int out_bytes);
static PIByteArray blake2xb(const PIByteArray & in, int out_bytes); static PIByteArray blake2xb(const PIByteArray & in, const PIByteArray & key, int out_bytes);
}; };
#endif #endif

View File

@@ -70,7 +70,7 @@ PIByteArray SHA2::sha2xx(const PIByteArray & in, const uint32_t * initial, int o
constexpr int part_size = 64; constexpr int part_size = 64;
constexpr int rounds = 64; constexpr int rounds = 64;
static constexpr uint32_t k[part_size] = { static constexpr uint32_t k[rounds] = {
0x428A2F98u, 0x71374491u, 0xB5C0FBCFu, 0xE9B5DBA5u, 0x3956C25Bu, 0x59F111F1u, 0x923F82A4u, 0xAB1C5ED5u, 0xD807AA98u, 0x12835B01u, 0x428A2F98u, 0x71374491u, 0xB5C0FBCFu, 0xE9B5DBA5u, 0x3956C25Bu, 0x59F111F1u, 0x923F82A4u, 0xAB1C5ED5u, 0xD807AA98u, 0x12835B01u,
0x243185BEu, 0x550C7DC3u, 0x72BE5D74u, 0x80DEB1FEu, 0x9BDC06A7u, 0xC19BF174u, 0xE49B69C1u, 0xEFBE4786u, 0x0FC19DC6u, 0x240CA1CCu, 0x243185BEu, 0x550C7DC3u, 0x72BE5D74u, 0x80DEB1FEu, 0x9BDC06A7u, 0xC19BF174u, 0xE49B69C1u, 0xEFBE4786u, 0x0FC19DC6u, 0x240CA1CCu,
0x2DE92C6Fu, 0x4A7484AAu, 0x5CB0A9DCu, 0x76F988DAu, 0x983E5152u, 0xA831C66Du, 0xB00327C8u, 0xBF597FC7u, 0xC6E00BF3u, 0xD5A79147u, 0x2DE92C6Fu, 0x4A7484AAu, 0x5CB0A9DCu, 0x76F988DAu, 0x983E5152u, 0xA831C66Du, 0xB00327C8u, 0xBF597FC7u, 0xC6E00BF3u, 0xD5A79147u,
@@ -153,7 +153,7 @@ PIByteArray SHA2::sha5xx(const PIByteArray & in, const uint64_t * initial, int o
constexpr int part_size = 128; constexpr int part_size = 128;
constexpr int rounds = 80; constexpr int rounds = 80;
static constexpr uint64_t k[80] = { static constexpr uint64_t k[rounds] = {
0X428A2F98D728AE22U, 0X7137449123EF65CDU, 0XB5C0FBCFEC4D3B2FU, 0XE9B5DBA58189DBBCU, 0X3956C25BF348B538U, 0X59F111F1B605D019U, 0X428A2F98D728AE22U, 0X7137449123EF65CDU, 0XB5C0FBCFEC4D3B2FU, 0XE9B5DBA58189DBBCU, 0X3956C25BF348B538U, 0X59F111F1B605D019U,
0X923F82A4AF194F9BU, 0XAB1C5ED5DA6D8118U, 0XD807AA98A3030242U, 0X12835B0145706FBEU, 0X243185BE4EE4B28CU, 0X550C7DC3D5FFB4E2U, 0X923F82A4AF194F9BU, 0XAB1C5ED5DA6D8118U, 0XD807AA98A3030242U, 0X12835B0145706FBEU, 0X243185BE4EE4B28CU, 0X550C7DC3D5FFB4E2U,
0X72BE5D74F27B896FU, 0X80DEB1FE3B1696B1U, 0X9BDC06A725C71235U, 0XC19BF174CF692694U, 0XE49B69C19EF14AD2U, 0XEFBE4786384F25E3U, 0X72BE5D74F27B896FU, 0X80DEB1FE3B1696B1U, 0X9BDC06A725C71235U, 0XC19BF174CF692694U, 0XE49B69C19EF14AD2U, 0XEFBE4786384F25E3U,

View File

@@ -0,0 +1,58 @@
/*
PIP - Platform Independent Primitives
Digest algorithms
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pidigest_siphash_p.h"
#include "3rd/SipHash/halfsiphash.h"
#include "3rd/SipHash/siphash.h"
#include "3rd/SipHash/vectors.h"
PIByteArray SipHash::siphash(const PIByteArray & in, const PIByteArray & key, int out_bytes) {
PIByteArray ret(out_bytes);
static PIByteArray empty_key(16, 0);
if (key.isEmpty())
::siphash(in.data(), in.size(), empty_key.data(), ret.data(), ret.size());
else {
if (key.size() >= 16)
::siphash(in.data(), in.size(), key.data(), ret.data(), ret.size());
else {
auto skey = key.resized(16);
::siphash(in.data(), in.size(), skey.data(), ret.data(), ret.size());
}
}
return ret;
}
PIByteArray SipHash::halfsiphash(const PIByteArray & in, const PIByteArray & key, int out_bytes) {
PIByteArray ret(out_bytes);
static PIByteArray empty_key(8, 0);
if (key.isEmpty())
::halfsiphash(in.data(), in.size(), empty_key.data(), ret.data(), ret.size());
else {
if (key.size() >= 8)
::halfsiphash(in.data(), in.size(), key.data(), ret.data(), ret.size());
else {
auto skey = key.resized(8);
::halfsiphash(in.data(), in.size(), skey.data(), ret.data(), ret.size());
}
}
return ret;
}

View File

@@ -0,0 +1,31 @@
/*
PIP - Platform Independent Primitives
Digest algorithms
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef pidigest_siphash_h
#define pidigest_siphash_h
#include "pibytearray.h"
class SipHash {
public:
static PIByteArray siphash(const PIByteArray & in, const PIByteArray & key, int out_bytes);
static PIByteArray halfsiphash(const PIByteArray & in, const PIByteArray & key, int out_bytes);
};
#endif

View File

@@ -29,21 +29,53 @@
#include "pimathbase.h" #include "pimathbase.h"
//! \~english Geographical ellipsoid Earth model
//! \~russian Географическая эллипсоидная модель Земли
class PIP_EXPORT PIEllipsoidModel { class PIP_EXPORT PIEllipsoidModel {
public: public:
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
PIEllipsoidModel(); PIEllipsoidModel();
double eccSquared() const { return eccentricity * eccentricity; } // eccentricity squared
//! \~english Get eccentricity squared
//! \~russian Получить квадрат эксцентриситета
double eccSquared() const { return eccentricity * eccentricity; }
//! \~english Get semi-minor axis (b)
//! \~russian Получить малую полуось (b)
double b() const { return a * sqrt(1 - eccSquared()); } double b() const { return a * sqrt(1 - eccSquared()); }
//! \~english WGS84 ellipsoid model
//! \~russian Эллипсоид WGS84
static PIEllipsoidModel WGS84Ellipsoid(); static PIEllipsoidModel WGS84Ellipsoid();
//! \~english PZ90 ellipsoid model
//! \~russian Эллипсоид ПЗ-90
static PIEllipsoidModel PZ90Ellipsoid(); static PIEllipsoidModel PZ90Ellipsoid();
//! \~english GPS ellipsoid (same as WGS84)
//! \~russian Эллипсоид GPS (то же что WGS84)
static PIEllipsoidModel GPSEllipsoid(); static PIEllipsoidModel GPSEllipsoid();
//! \~english Krasovskiy ellipsoid model
//! \~russian Эллипсоид Красовского
static PIEllipsoidModel KrasovskiyEllipsoid(); static PIEllipsoidModel KrasovskiyEllipsoid();
double a; /// Major axis of Earth in meters //! \~english Major semi-axis (meters)
double flattening; /// Flattening (ellipsoid parameter) //! \~russian Большая полуось (метры)
double eccentricity; /// Eccentricity (ellipsoid parameter) double a;
double angVelocity; /// Angular velocity of Earth in radians/sec
//! \~english Flattening (f = (a-b)/a)
//! \~russian Сплюснутость (f = (a-b)/a)
double flattening;
//! \~english First eccentricity
//! \~russian Первый эксцентриситет
double eccentricity;
//! \~english Angular velocity (rad/sec)
//! \~russian Угловая скорость (рад/сек)
double angVelocity;
}; };

View File

@@ -29,147 +29,338 @@
#include "piellipsoidmodel.h" #include "piellipsoidmodel.h"
#include "pimathvector.h" #include "pimathvector.h"
//! \~english Geographical position class
//! \~russian Класс географической позиции
class PIP_EXPORT PIGeoPosition: public PIMathVectorT3d { class PIP_EXPORT PIGeoPosition: public PIMathVectorT3d {
public: public:
//! \~english Coordinate system types
//! \~russian Типы систем координат
enum CoordinateSystem { enum CoordinateSystem {
Unknown = 0, /// Unknown coordinate system Unknown = 0, //!< Unknown coordinate system
Geodetic, /// Geodetic latitude, longitude, and height above ellipsoid Geodetic, //!< Geodetic latitude, longitude, and height above ellipsoid
Geocentric, /// Geocentric (regular spherical coordinates) Geocentric, //!< Geocentric (regular spherical coordinates)
Cartesian, /// Cartesian (Earth-centered, Earth-fixed) Cartesian, //!< Cartesian (Earth-centered, Earth-fixed)
Spherical /// Spherical coordinates (theta,phi,radius) Spherical //!< Spherical coordinates (theta,phi,radius)
}; };
static const double one_cm_tolerance; /// One centimeter tolerance. //! \~english One centimeter tolerance
static const double one_mm_tolerance; /// One millimeter tolerance. //! \~russian Допуск один сантиметр
static const double one_um_tolerance; /// One micron tolerance. static const double one_cm_tolerance;
static double position_tolerance; /// Default tolerance (default 1mm)
//! \~english One millimeter tolerance
//! \~russian Допуск один миллиметр
static const double one_mm_tolerance;
//! \~english One micron tolerance
//! \~russian Допуск один микрон
static const double one_um_tolerance;
//! \~english Default position tolerance (default 1mm)
//! \~russian Допуск позиции по умолчанию (по умолчанию 1мм)
static double position_tolerance;
//! \~english Set position tolerance
//! \~russian Установить допуск позиции
//! \param tol New tolerance value
//! \return Previous tolerance value
static double setPositionTolerance(const double tol) { static double setPositionTolerance(const double tol) {
position_tolerance = tol; position_tolerance = tol;
return position_tolerance; return position_tolerance;
} }
//! \~english Get position tolerance
//! \~russian Получить допуск позиции
static double getPositionTolerance() { return position_tolerance; } static double getPositionTolerance() { return position_tolerance; }
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
PIGeoPosition(); PIGeoPosition();
//! \~english Constructor with coordinates
//! \~russian Конструктор с координатами
//! \param a First coordinate
//! \param b Second coordinate
//! \param c Third coordinate
//! \param s Coordinate system
//! \param ell Ellipsoid model
PIGeoPosition(double a, double b, double c, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIGeoPosition(double a, double b, double c, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Constructor from vector
//! \~russian Конструктор из вектора
//! \param v Vector with coordinates
//! \param s Coordinate system
//! \param ell Ellipsoid model
PIGeoPosition(PIMathVectorT3d v, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIGeoPosition(PIMathVectorT3d v, CoordinateSystem s = Cartesian, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Transform to specified coordinate system
//! \~russian Преобразовать в указанную систему координат
//! \param sys Target coordinate system
//! \return Reference to this position
PIGeoPosition & transformTo(CoordinateSystem sys); PIGeoPosition & transformTo(CoordinateSystem sys);
//! \~english Convert to geodetic coordinates
//! \~russian Преобразовать в геодезические координаты
PIGeoPosition & asGeodetic() { PIGeoPosition & asGeodetic() {
transformTo(Geodetic); transformTo(Geodetic);
return *this; return *this;
} /// Convert to geodetic coordinate }
//! \~english Convert to geodetic coordinates using specified ellipsoid
//! \~russian Преобразовать в геодезические координаты с указанным эллипсоидом
//! \param ell Ellipsoid model to use
//! \return Reference to this position
PIGeoPosition & asGeodetic(const PIEllipsoidModel & ell) { PIGeoPosition & asGeodetic(const PIEllipsoidModel & ell) {
setEllipsoidModel(ell); setEllipsoidModel(ell);
transformTo(Geodetic); transformTo(Geodetic);
return *this; return *this;
} /// Convert to another ell, then to geodetic coordinates }
//! \~english Convert to ECEF (cartesian) coordinates
//! \~russian Преобразовать в координаты ECEF (декартовы)
PIGeoPosition & asECEF() { PIGeoPosition & asECEF() {
transformTo(Cartesian); transformTo(Cartesian);
return *this; return *this;
} /// Convert to cartesian coordinates }
//! \~english Get X coordinate (or first coordinate in Cartesian)
//! \~russian Получить координату X (или первую координату в Декартовой)
double x() const; double x() const;
//! \~english Get Y coordinate (or second coordinate in Cartesian)
//! \~russian Получить координату Y (или вторую координату в Декартовой)
double y() const; double y() const;
//! \~english Get Z coordinate (or third coordinate in Cartesian)
//! \~russian Получить координату Z (или третью координату в Декартовой)
double z() const; double z() const;
//! \~english Get geodetic latitude in degrees
//! \~russian Получить геодезическую широту в градусах
double latitudeGeodetic() const; double latitudeGeodetic() const;
//! \~english Get geocentric latitude in degrees
//! \~russian Получить геоцентрическую широту в градусах
double latitudeGeocentric() const; double latitudeGeocentric() const;
//! \~english Get longitude in degrees
//! \~russian Получить долготу в градусах
double longitude() const; double longitude() const;
//! \~english Get theta (angle from Z axis) in degrees
//! \~russian Получить тета (угол от оси Z) в градусах
double theta() const; double theta() const;
//! \~english Get phi (angle in XY plane from X axis) in degrees
//! \~russian Получить фи (угол в плоскости XY от оси X) в градусах
double phi() const; double phi() const;
//! \~english Get radius (distance from Earth center)
//! \~russian Получить радиус (расстояние от центра Земли)
double radius() const; double radius() const;
//! \~english Get height above ellipsoid
//! \~russian Получить высоту над эллипсоидом
double height() const; double height() const;
/// Set the ellipsoid values for this PIGeoPosition given a ellipsoid. //! \~english Set ellipsoid model for this position
//! \~russian Установить модель эллипсоида для этой позиции
//! \param ell Ellipsoid model
void setEllipsoidModel(const PIEllipsoidModel & ell) { el = ell; } void setEllipsoidModel(const PIEllipsoidModel & ell) { el = ell; }
/// Set the \a PIGeoPosition given geodetic coordinates in degrees. \a CoordinateSystem is set to \a Geodetic. //! \~english Set position from geodetic coordinates
//! \~russian Установить позицию из геодезических координат
//! \param lat Latitude in degrees
//! \param lon Longitude in degrees
//! \param ht Height above ellipsoid
//! \param ell Ellipsoid model (default WGS84)
//! \return Reference to this position
PIGeoPosition & setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIGeoPosition & setGeodetic(double lat, double lon, double ht, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Set the \a PIGeoPosition given geocentric coordinates in degrees. \a CoordinateSystem is set to \a Geocentric //! \~english Set position from geocentric coordinates
//! \~russian Установить позицию из геоцентрических координат
//! \param lat Latitude in degrees
//! \param lon Longitude in degrees
//! \param rad Radius
//! \return Reference to this position
PIGeoPosition & setGeocentric(double lat, double lon, double rad); PIGeoPosition & setGeocentric(double lat, double lon, double rad);
/// Set the \a PIGeoPosition given spherical coordinates in degrees. \a CoordinateSystem is set to \a Spherical //! \~english Set position from spherical coordinates
//! \~russian Установить позицию из сферических координат
//! \param theta Angle from Z axis in degrees
//! \param phi Angle in XY plane from X axis in degrees
//! \param rad Radius
//! \return Reference to this position
PIGeoPosition & setSpherical(double theta, double phi, double rad); PIGeoPosition & setSpherical(double theta, double phi, double rad);
/// Set the \a PIGeoPosition given ECEF coordinates in meeters. \a CoordinateSystem is set to \a Cartesian. //! \~english Set position from ECEF coordinates
//! \~russian Установить позицию из координат ECEF
//! \param x X coordinate in meters
//! \param y Y coordinate in meters
//! \param z Z coordinate in meters
//! \return Reference to this position
PIGeoPosition & setECEF(double x, double y, double z); PIGeoPosition & setECEF(double x, double y, double z);
/// Fundamental conversion from spherical to cartesian coordinates. //! \~english Convert spherical to Cartesian coordinates
//! \~russian Преобразовать сферические в декартовы координаты
//! \param tpr Input spherical (theta, phi, radius)
//! \param xyz Output Cartesian (x, y, z)
static void convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz); static void convertSphericalToCartesian(const PIMathVectorT3d & tpr, PIMathVectorT3d & xyz);
/// Fundamental routine to convert cartesian to spherical coordinates. //! \~english Convert Cartesian to spherical coordinates
//! \~russian Преобразовать декартовы в сферические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param tpr Output spherical (theta, phi, radius)
static void convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr); static void convertCartesianToSpherical(const PIMathVectorT3d & xyz, PIMathVectorT3d & tpr);
/// Fundamental routine to convert ECEF (cartesian) to geodetic coordinates, //! \~english Convert Cartesian (ECEF) to geodetic coordinates
//! \~russian Преобразовать декартовы (ECEF) в геодезические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param llh Output geodetic (latitude, longitude, height)
//! \param ell Ellipsoid model (default WGS84)
static void convertCartesianToGeodetic(const PIMathVectorT3d & xyz, static void convertCartesianToGeodetic(const PIMathVectorT3d & xyz,
PIMathVectorT3d & llh, PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert geodetic to ECEF (cartesian) coordinates, //! \~english Convert geodetic to Cartesian (ECEF) coordinates
//! \~russian Преобразовать геодезические в декартовы (ECEF) координаты
//! \param llh Input geodetic (latitude, longitude, height)
//! \param xyz Output Cartesian (x, y, z)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeodeticToCartesian(const PIMathVectorT3d & llh, static void convertGeodeticToCartesian(const PIMathVectorT3d & llh,
PIMathVectorT3d & xyz, PIMathVectorT3d & xyz,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert cartesian (ECEF) to geocentric //! \~english Convert Cartesian (ECEF) to geocentric coordinates
//! \~russian Преобразовать декартовы (ECEF) в геоцентрические координаты
//! \param xyz Input Cartesian (x, y, z)
//! \param llr Output geocentric (latitude, longitude, radius)
static void convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr); static void convertCartesianToGeocentric(const PIMathVectorT3d & xyz, PIMathVectorT3d & llr);
/// Fundamental routine to convert geocentric to cartesian (ECEF) //! \~english Convert geocentric to Cartesian (ECEF)
//! \~russian Преобразовать геоцентрические в декартовы (ECEF)
//! \param llr Input geocentric (latitude, longitude, radius)
//! \param xyz Output Cartesian (x, y, z)
static void convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz); static void convertGeocentricToCartesian(const PIMathVectorT3d & llr, PIMathVectorT3d & xyz);
/// Fundamental routine to convert geocentric to geodetic //! \~english Convert geocentric to geodetic
//! \~russian Преобразовать геоцентрические в геодезические
//! \param llr Input geocentric (latitude, longitude, radius)
//! \param llh Output geodetic (latitude, longitude, height)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeocentricToGeodetic(const PIMathVectorT3d & llr, static void convertGeocentricToGeodetic(const PIMathVectorT3d & llr,
PIMathVectorT3d & llh, PIMathVectorT3d & llh,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Fundamental routine to convert geodetic to geocentric //! \~english Convert geodetic to geocentric
//! \~russian Преобразовать геодезические в геоцентрические
//! \param llh Input geodetic (latitude, longitude, height)
//! \param llr Output geocentric (latitude, longitude, radius)
//! \param ell Ellipsoid model (default WGS84)
static void convertGeodeticToGeocentric(const PIMathVectorT3d & llh, static void convertGeodeticToGeocentric(const PIMathVectorT3d & llh,
PIMathVectorT3d & llr, PIMathVectorT3d & llr,
PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
/// Compute the radius of the ellipsoidal Earth, given the geodetic latitude. //! \~english Compute radius of ellipsoid at given latitude
//! \~russian Вычислить радиус эллипсоида на заданной широте
//! \param geolat Geodetic latitude in degrees
//! \param ell Ellipsoid model (default WGS84)
//! \return Radius in meters
static double radiusEarth(double geolat, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid()); static double radiusEarth(double geolat, PIEllipsoidModel ell = PIEllipsoidModel::WGS84Ellipsoid());
//! \~english Compute radius of ellipsoid at current position
//! \~russian Вычислить радиус эллипсоида в текущей позиции
double radiusEarth() const { double radiusEarth() const {
PIGeoPosition p(*this); PIGeoPosition p(*this);
p.transformTo(PIGeoPosition::Geodetic); p.transformTo(PIGeoPosition::Geodetic);
return PIGeoPosition::radiusEarth((*this)[0], p.el); return PIGeoPosition::radiusEarth((*this)[0], p.el);
} }
/// Compute the range in meters between two PIGeoPositions. //! \~english Compute range between two positions
//! \~russian Вычислить расстояние между двумя позициями
//! \param a First position
//! \param b Second position
//! \return Range in meters
static double range(const PIGeoPosition & a, const PIGeoPosition & b); static double range(const PIGeoPosition & a, const PIGeoPosition & b);
//! \~english Compute range from this position to another
//! \~russian Вычислить расстояние от этой позиции до другой
//! \param p Target position
//! \return Range in meters
double range(const PIGeoPosition & p) const { return range((*this), p); } double range(const PIGeoPosition & p) const { return range((*this), p); }
/// Computes the elevation of the input (p) position as seen from this PIGeoPosition. //! \~english Compute elevation angle to target position
//! \~russian Вычислить угол возвышения до целевой позиции
//! \param p Target position
//! \return Elevation angle in degrees
double elevation(const PIGeoPosition & p) const; double elevation(const PIGeoPosition & p) const;
/// Computes the elevation of the input (p) position as seen from this PIGeoPosition, using a Geodetic (ellipsoidal) system. //! \~english Compute geodetic elevation angle to target position
//! \~russian Вычислить геодезический угол возвышения до целевой позиции
//! \param p Target position
//! \return Elevation angle in degrees
double elevationGeodetic(const PIGeoPosition & p) const; double elevationGeodetic(const PIGeoPosition & p) const;
/// Computes the azimuth of the input (p) position as seen from this PIGeoPosition. //! \~english Compute azimuth angle to target position
//! \~russian Вычислить азимут до целевой позиции
//! \param p Target position
//! \return Azimuth angle in degrees
double azimuth(const PIGeoPosition & p) const; double azimuth(const PIGeoPosition & p) const;
/// Computes the azimuth of the input (p) position as seen from this PIGeoPosition, using a Geodetic (ellipsoidal) system. //! \~english Compute geodetic azimuth angle to target position
//! \~russian Вычислить геодезический азимут до целевой позиции
//! \param p Target position
//! \return Azimuth angle in degrees
double azimuthGeodetic(const PIGeoPosition & p) const; double azimuthGeodetic(const PIGeoPosition & p) const;
/// Computes the radius of curvature of the meridian (Rm) corresponding to this PIGeoPosition. //! \~english Get radius of curvature of the meridian
//! \~russian Получить радиус кривизны меридиана
//! \return Radius in meters
double getCurvMeridian() const; double getCurvMeridian() const;
/// Computes the radius of curvature in the prime vertical (Rn) corresponding to this PIGeoPosition. //! \~english Get radius of curvature in the prime vertical
//! \~russian Получить радиус кривизны в вертикале
//! \return Radius in meters
double getCurvPrimeVertical() const; double getCurvPrimeVertical() const;
/// Returns as PIMathVectorT3d //! \~english Get as PIMathVectorT3d
//! \~russian Получить как PIMathVectorT3d
//! \return Reference to underlying vector
const PIMathVectorT3d & vector() const { return *this; } const PIMathVectorT3d & vector() const { return *this; }
//! \~english Assignment from vector
//! \~russian Присваивание из вектора
PIGeoPosition & operator=(const PIMathVectorT3d & v); PIGeoPosition & operator=(const PIMathVectorT3d & v);
//! \~english Subtraction
//! \~russian Вычитание
PIGeoPosition & operator-=(const PIGeoPosition & right); PIGeoPosition & operator-=(const PIGeoPosition & right);
//! \~english Addition
//! \~russian Сложение
PIGeoPosition & operator+=(const PIGeoPosition & right); PIGeoPosition & operator+=(const PIGeoPosition & right);
//! \~english Subtraction
//! \~russian Вычитание
friend PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right); friend PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right);
//! \~english Addition
//! \~russian Сложение
friend PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right); friend PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right);
//! \~english Scalar multiplication
//! \~russian Умножение на скаляр
friend PIGeoPosition operator*(const double & scale, const PIGeoPosition & right); friend PIGeoPosition operator*(const double & scale, const PIGeoPosition & right);
friend PIGeoPosition operator*(const PIGeoPosition & left, const double & scale); friend PIGeoPosition operator*(const PIGeoPosition & left, const double & scale);
friend PIGeoPosition operator*(const int & scale, const PIGeoPosition & right); friend PIGeoPosition operator*(const int & scale, const PIGeoPosition & right);
friend PIGeoPosition operator*(const PIGeoPosition & left, const int & scale); friend PIGeoPosition operator*(const PIGeoPosition & left, const int & scale);
//! \~english Equality comparison
//! \~russian Сравнение на равенство
bool operator==(const PIGeoPosition & right) const; bool operator==(const PIGeoPosition & right) const;
//! \~english Inequality comparison
//! \~russian Сравнение на неравенство
bool operator!=(const PIGeoPosition & right) const { return !(operator==(right)); } bool operator!=(const PIGeoPosition & right) const { return !(operator==(right)); }
@@ -181,6 +372,8 @@ private:
}; };
//! \~english Subtraction
//! \~russian Вычитание
inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right) { inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition & right) {
PIGeoPosition l(left), r(right); PIGeoPosition l(left), r(right);
l.transformTo(PIGeoPosition::Cartesian); l.transformTo(PIGeoPosition::Cartesian);
@@ -188,6 +381,8 @@ inline PIGeoPosition operator-(const PIGeoPosition & left, const PIGeoPosition &
l -= r; l -= r;
return l; return l;
} }
//! \~english Addition
//! \~russian Сложение
inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right) { inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition & right) {
PIGeoPosition l(left), r(right); PIGeoPosition l(left), r(right);
l.transformTo(PIGeoPosition::Cartesian); l.transformTo(PIGeoPosition::Cartesian);
@@ -195,17 +390,25 @@ inline PIGeoPosition operator+(const PIGeoPosition & left, const PIGeoPosition &
l += r; l += r;
return l; return l;
} }
//! \~english Scalar multiplication (double)
//! \~russian Умножение на скаляр (double)
inline PIGeoPosition operator*(const double & scale, const PIGeoPosition & right) { inline PIGeoPosition operator*(const double & scale, const PIGeoPosition & right) {
PIMathVectorT3d tmp(right); PIMathVectorT3d tmp(right);
tmp *= scale; tmp *= scale;
return PIGeoPosition(tmp); return PIGeoPosition(tmp);
} }
//! \~english Scalar multiplication (double)
//! \~russian Умножение на скаляр (double)
inline PIGeoPosition operator*(const PIGeoPosition & left, const double & scale) { inline PIGeoPosition operator*(const PIGeoPosition & left, const double & scale) {
return operator*(scale, left); return operator*(scale, left);
} }
//! \~english Scalar multiplication (int)
//! \~russian Умножение на скаляр (int)
inline PIGeoPosition operator*(const int & scale, const PIGeoPosition & right) { inline PIGeoPosition operator*(const int & scale, const PIGeoPosition & right) {
return operator*(double(scale), right); return operator*(double(scale), right);
} }
//! \~english Scalar multiplication (int)
//! \~russian Умножение на скаляр (int)
inline PIGeoPosition operator*(const PIGeoPosition & left, const int & scale) { inline PIGeoPosition operator*(const PIGeoPosition & left, const int & scale) {
return operator*(double(scale), left); return operator*(double(scale), left);
} }

View File

@@ -1,3 +1,14 @@
//! \addtogroup HTTP
//! \{
//! \file pihttpclient.h
//! \brief HTTP client implementation
//! \~english HTTP client for performing asynchronous HTTP requests with callbacks
//! \~russian HTTP клиент для выполнения асинхронных HTTP запросов с колбэками
//! \details
//! \~english Provides async HTTP client functionality using libcurl
//! \~russian Обеспечивает функциональность асинхронного HTTP клиента с использованием libcurl
//! \}
#ifndef pihttpclient_h #ifndef pihttpclient_h
#define pihttpclient_h #define pihttpclient_h
@@ -6,6 +17,8 @@
#include "pistringlist.h" #include "pistringlist.h"
//! \~english Base class for HTTP client internal functionality
//! \~russian Базовый класс для внутренней функциональности HTTP клиента
class PIHTTPClientBase { class PIHTTPClientBase {
public: public:
int __infoFunc(ssize_t dltotal, ssize_t dlnow, ssize_t ultotal, ssize_t ulnow); int __infoFunc(ssize_t dltotal, ssize_t dlnow, ssize_t ultotal, ssize_t ulnow);
@@ -13,51 +26,51 @@ public:
}; };
//! ~english Main HTTP client class for performing requests with event callbacks. //! \~english Main HTTP client class for performing requests with event callbacks.
//! ~russian Основной класс HTTP-клиента для выполнения запросов с callback-ми событий. //! \~russian Основной класс HTTP-клиента для выполнения запросов с callback-ми событий.
class PIP_HTTP_CLIENT_EXPORT PIHTTPClient: private PIHTTPClientBase { class PIP_HTTP_CLIENT_EXPORT PIHTTPClient: private PIHTTPClientBase {
friend class PIHTTPClientBase; friend class PIHTTPClientBase;
friend class CurlThreadPool; friend class CurlThreadPool;
public: public:
//! ~english Creates a new HTTP request instance with the specified URL, method and message. //! \~english Creates a new HTTP request instance with the specified URL, method and message.
//! ~russian Создает новый экземпляр HTTP-запроса с указанным URL, методом и сообщением. //! \~russian Создает новый экземпляр HTTP-запроса с указанным URL, методом и сообщением.
static PIHTTPClient * create(const PIString & url, PIHTTP::Method method = PIHTTP::Method::Get, const PIHTTP::MessageConst & req = {}); static PIHTTPClient * create(const PIString & url, PIHTTP::Method method = PIHTTP::Method::Get, const PIHTTP::MessageConst & req = {});
//! ~english Sets a callback for successful request completion (no parameters). //! \~english Sets a callback for successful request completion (no parameters).
//! ~russian Устанавливает callback для успешного завершения запроса (без параметров). //! \~russian Устанавливает callback для успешного завершения запроса (без параметров).
PIHTTPClient * onFinish(std::function<void()> f); PIHTTPClient * onFinish(std::function<void()> f);
//! ~english Sets a callback for successful request completion (with response). //! \~english Sets a callback for successful request completion (with response).
//! ~russian Устанавливает callback для успешного завершения запроса (с ответом). //! \~russian Устанавливает callback для успешного завершения запроса (с ответом).
PIHTTPClient * onFinish(std::function<void(const PIHTTP::MessageConst &)> f); PIHTTPClient * onFinish(std::function<void(const PIHTTP::MessageConst &)> f);
//! ~english Sets a callback for request errors (no parameters). //! \~english Sets a callback for request errors (no parameters).
//! ~russian Устанавливает callback для ошибок запроса (без параметров). //! \~russian Устанавливает callback для ошибок запроса (без параметров).
PIHTTPClient * onError(std::function<void()> f); PIHTTPClient * onError(std::function<void()> f);
//! ~english Sets a callback for request errors (with error response). //! \~english Sets a callback for request errors (with error response).
//! ~russian Устанавливает callback для ошибок запроса (с ответом об ошибке). //! \~russian Устанавливает callback для ошибок запроса (с ответом об ошибке).
PIHTTPClient * onError(std::function<void(const PIHTTP::MessageConst &)> f); PIHTTPClient * onError(std::function<void(const PIHTTP::MessageConst &)> f);
//! ~english Sets a callback for request abortion (no parameters). //! \~english Sets a callback for request abortion (no parameters).
//! ~russian Устанавливает callback для прерывания запроса (без параметров). //! \~russian Устанавливает callback для прерывания запроса (без параметров).
PIHTTPClient * onAbort(std::function<void()> f); PIHTTPClient * onAbort(std::function<void()> f);
//! ~english Sets a callback for request abortion (with abort response). //! \~english Sets a callback for request abortion (with abort response).
//! ~russian Устанавливает callback для прерывания запроса (с ответом о прерывании). //! \~russian Устанавливает callback для прерывания запроса (с ответом о прерывании).
PIHTTPClient * onAbort(std::function<void(const PIHTTP::MessageConst &)> f); PIHTTPClient * onAbort(std::function<void(const PIHTTP::MessageConst &)> f);
//! ~english Starts the HTTP request execution. //! \~english Starts the HTTP request execution.
//! ~russian Начинает выполнение HTTP-запроса. //! \~russian Начинает выполнение HTTP-запроса.
void start(); void start();
//! ~english Aborts the current HTTP request. //! \~english Aborts the current HTTP request.
//! ~russian Прерывает текущий HTTP-запрос. //! \~russian Прерывает текущий HTTP-запрос.
void abort(); void abort();
//! ~english Returns the last error message. //! \~english Returns the last error message.
//! ~russian Возвращает последнее сообщение об ошибке. //! \~russian Возвращает последнее сообщение об ошибке.
PIString lastError() const { return last_error; } PIString lastError() const { return last_error; }
private: private:

View File

@@ -1,9 +1,23 @@
//! \addtogroup HTTP
//! \{
//! \file pihttpconstants.h
//! \brief HTTP constants and enumerations
//! \~english Definitions for HTTP methods, status codes and header names
//! \~russian Определения HTTP методов, кодов состояния и имен заголовков
//! \details
//! \~english Provides enum classes for HTTP methods and status codes, and a namespace with HTTP header name constants
//! \~russian Предоставляет классы перечислений для HTTP методов и кодов состояния, а также пространство имён с константами имён HTTP
//! заголовков
//! \}
#ifndef pihttpconstants_h #ifndef pihttpconstants_h
#define pihttpconstants_h #define pihttpconstants_h
namespace PIHTTP { namespace PIHTTP {
//! \~english HTTP request methods
//! \~russian HTTP методы запросов
enum class Method { enum class Method {
Unknown, Unknown,
Get, Get,
@@ -17,6 +31,8 @@ enum class Method {
Patch Patch
}; };
//! \~english HTTP response status codes
//! \~russian Коды состояния HTTP ответа
enum class Code { enum class Code {
Unknown = -1, Unknown = -1,
Continue = 100, Continue = 100,
@@ -90,6 +106,8 @@ enum class Code {
NetworkAuthenticationRequired = 511, NetworkAuthenticationRequired = 511,
}; };
//! \~english HTTP header field names
//! \~russian Имена полей заголовков HTTP
namespace Header { namespace Header {
constexpr static char Accept[] = "Accept"; constexpr static char Accept[] = "Accept";
constexpr static char AcceptCharset[] = "Accept-Charset"; constexpr static char AcceptCharset[] = "Accept-Charset";

View File

@@ -1,3 +1,14 @@
//! \addtogroup HTTP
//! \{
//! \file pihttptypes.h
//! \brief HTTP types and message classes
//! \~english HTTP message types and containers for requests and responses
//! \~russian Типы HTTP и классы сообщений для запросов и ответов
//! \details
//! \~english Provides MessageConst and MessageMutable classes for HTTP communication
//! \~russian Предоставляет классы MessageConst и MessageMutable для HTTP коммуникации
//! \}
#ifndef pihttptypes_h #ifndef pihttptypes_h
#define pihttptypes_h #define pihttptypes_h
@@ -9,68 +20,68 @@
namespace PIHTTP { namespace PIHTTP {
//! ~english Immutable HTTP message container with accessors for message components //! \~english Immutable HTTP message container with accessors for message components
//! ~russian Контейнер для неизменяемого HTTP-сообщения с методами доступа к компонентам //! \~russian Контейнер для неизменяемого HTTP-сообщения с методами доступа к компонентам
class PIP_EXPORT MessageConst { class PIP_EXPORT MessageConst {
public: public:
//! ~english Gets the HTTP method used in the message //! \~english Gets the HTTP method used in the message
//! ~russian Возвращает HTTP-метод, использованный в сообщении //! \~russian Возвращает HTTP-метод, использованный в сообщении
PIHTTP::Method method() const { return m_method; } PIHTTP::Method method() const { return m_method; }
//! ~english Gets the HTTP status code //! \~english Gets the HTTP status code
//! ~russian Возвращает HTTP-статус код //! \~russian Возвращает HTTP-статус код
PIHTTP::Code code() const { return m_code; } PIHTTP::Code code() const { return m_code; }
//! ~english Checks if status code is informational (1xx) //! \~english Checks if status code is informational (1xx)
//! ~russian Проверяет, является ли статус код информационным (1xx) //! \~russian Проверяет, является ли статус код информационным (1xx)
bool isCodeInformational() const; bool isCodeInformational() const;
//! ~english Checks if status code indicates success (2xx) //! \~english Checks if status code indicates success (2xx)
//! ~russian Проверяет, указывает ли статус код на успех (2xx) //! \~russian Проверяет, указывает ли статус код на успех (2xx)
bool isCodeSuccess() const; bool isCodeSuccess() const;
//! ~english Checks if status code indicates redirection (3xx) //! \~english Checks if status code indicates redirection (3xx)
//! ~russian Проверяет, указывает ли статус код на перенаправление (3xx) //! \~russian Проверяет, указывает ли статус код на перенаправление (3xx)
bool isCodeRedirection() const; bool isCodeRedirection() const;
//! ~english Checks if status code indicates client error (4xx) //! \~english Checks if status code indicates client error (4xx)
//! ~russian Проверяет, указывает ли статус код на ошибку клиента (4xx) //! \~russian Проверяет, указывает ли статус код на ошибку клиента (4xx)
bool isCodeClientError() const; bool isCodeClientError() const;
//! ~english Checks if status code indicates server error (5xx) //! \~english Checks if status code indicates server error (5xx)
//! ~russian Проверяет, указывает ли статус код на ошибку сервера (5xx) //! \~russian Проверяет, указывает ли статус код на ошибку сервера (5xx)
bool isCodeServerError() const; bool isCodeServerError() const;
//! ~english Checks if status code indicates any error (4xx or 5xx) //! \~english Checks if status code indicates any error (4xx or 5xx)
//! ~russian Проверяет, указывает ли статус код на любую ошибку (4xx или 5xx) //! \~russian Проверяет, указывает ли статус код на любую ошибку (4xx или 5xx)
bool isCodeError() const { return isCodeClientError() || isCodeServerError(); } bool isCodeError() const { return isCodeClientError() || isCodeServerError(); }
//! ~english Gets the request/response path //! \~english Gets the request/response path
//! ~russian Возвращает путь запроса/ответа //! \~russian Возвращает путь запроса/ответа
const PIString & path() const { return m_path; } const PIString & path() const { return m_path; }
//! ~english Gets path components as list //! \~english Gets path components as list
//! ~russian Возвращает компоненты пути в виде списка //! \~russian Возвращает компоненты пути в виде списка
PIStringList pathList() const { return m_path.split('/').removeAll({}); } PIStringList pathList() const { return m_path.split('/').removeAll({}); }
//! ~english Gets the message body //! \~english Gets the message body
//! ~russian Возвращает тело сообщения //! \~russian Возвращает тело сообщения
const PIByteArray & body() const { return m_body; } const PIByteArray & body() const { return m_body; }
//! ~english Gets all message headers //! \~english Gets all message headers
//! ~russian Возвращает все заголовки сообщения //! \~russian Возвращает все заголовки сообщения
const PIMap<PIString, PIString> & headers() const { return m_headers; } const PIMap<PIString, PIString> & headers() const { return m_headers; }
//! ~english Gets URL query arguments //! \~english Gets URL query arguments
//! ~russian Возвращает URL query аргументы //! \~russian Возвращает URL query аргументы
const PIMap<PIString, PIString> & queryArguments() const { return m_query_arguments; } const PIMap<PIString, PIString> & queryArguments() const { return m_query_arguments; }
//! ~english Gets URL path arguments //! \~english Gets URL path arguments
//! ~russian Возвращает URL path аргументы //! \~russian Возвращает URL path аргументы
const PIMap<PIString, PIString> & pathArguments() const { return m_path_arguments; } const PIMap<PIString, PIString> & pathArguments() const { return m_path_arguments; }
//! ~english Gets all message arguments (query + path) //! \~english Gets all message arguments (query + path)
//! ~russian Возвращает все аргументы сообщения (query + path) //! \~russian Возвращает все аргументы сообщения (query + path)
const PIMap<PIString, PIString> & arguments() const { return m_arguments; } const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
protected: protected:
@@ -83,24 +94,24 @@ protected:
}; };
//! ~english Mutable HTTP message container with modifiers for message components //! \~english Mutable HTTP message container with modifiers for message components
//! ~russian Контейнер для изменяемого HTTP-сообщения с методами модификации //! \~russian Контейнер для изменяемого HTTP-сообщения с методами модификации
class PIP_EXPORT MessageMutable: public MessageConst { class PIP_EXPORT MessageMutable: public MessageConst {
public: public:
//! ~english Sets the HTTP method //! \~english Sets the HTTP method
//! ~russian Устанавливает HTTP-метод //! \~russian Устанавливает HTTP-метод
MessageMutable & setMethod(PIHTTP::Method m); MessageMutable & setMethod(PIHTTP::Method m);
//! ~english Sets the HTTP status code //! \~english Sets the HTTP status code
//! ~russian Устанавливает HTTP-статус код //! \~russian Устанавливает HTTP-статус код
MessageMutable & setCode(PIHTTP::Code c); MessageMutable & setCode(PIHTTP::Code c);
//! ~english Sets the request/response path //! \~english Sets the request/response path
//! ~russian Устанавливает путь запроса/ответа //! \~russian Устанавливает путь запроса/ответа
MessageMutable & setPath(PIString p); MessageMutable & setPath(PIString p);
//! ~english Sets the message body //! \~english Sets the message body
//! ~russian Устанавливает тело сообщения //! \~russian Устанавливает тело сообщения
MessageMutable & setBody(PIByteArray b); MessageMutable & setBody(PIByteArray b);
const PIMap<PIString, PIString> & headers() const { return m_headers; } const PIMap<PIString, PIString> & headers() const { return m_headers; }
@@ -111,50 +122,50 @@ public:
PIMap<PIString, PIString> & headers() { return m_headers; } PIMap<PIString, PIString> & headers() { return m_headers; }
//! ~english Adds a header to the message //! \~english Adds a header to the message
//! ~russian Добавляет заголовок к сообщению //! \~russian Добавляет заголовок к сообщению
MessageMutable & addHeader(const PIString & header, const PIString & value); MessageMutable & addHeader(const PIString & header, const PIString & value);
//! ~english Removes a header from the message //! \~english Removes a header from the message
//! ~russian Удаляет заголовок из сообщения //! \~russian Удаляет заголовок из сообщения
MessageMutable & removeHeader(const PIString & header); MessageMutable & removeHeader(const PIString & header);
//! ~english Gets reference to URL query arguments //! \~english Gets reference to URL query arguments
//! ~russian Возвращает ссылку на URL query аргументы //! \~russian Возвращает ссылку на URL query аргументы
PIMap<PIString, PIString> & queryArguments() { return m_query_arguments; } PIMap<PIString, PIString> & queryArguments() { return m_query_arguments; }
//! ~english Adds an URL query argument to the message //! \~english Adds an URL query argument to the message
//! ~russian Добавляет URL query аргумент к сообщению //! \~russian Добавляет URL query аргумент к сообщению
MessageMutable & addQueryArgument(const PIString & arg, const PIString & value); MessageMutable & addQueryArgument(const PIString & arg, const PIString & value);
//! ~english Removes an URL query argument from the message //! \~english Removes an URL query argument from the message
//! ~russian Удаляет URL query аргумент из сообщения //! \~russian Удаляет URL query аргумент из сообщения
MessageMutable & removeQueryArgument(const PIString & arg); MessageMutable & removeQueryArgument(const PIString & arg);
//! ~english Gets reference to URL path arguments //! \~english Gets reference to URL path arguments
//! ~russian Возвращает ссылку на URL path аргументы //! \~russian Возвращает ссылку на URL path аргументы
PIMap<PIString, PIString> & pathArguments() { return m_path_arguments; } PIMap<PIString, PIString> & pathArguments() { return m_path_arguments; }
//! ~english Adds an URL path argument to the message //! \~english Adds an URL path argument to the message
//! ~russian Добавляет URL path аргумент к сообщению //! \~russian Добавляет URL path аргумент к сообщению
MessageMutable & addPathArgument(const PIString & arg, const PIString & value); MessageMutable & addPathArgument(const PIString & arg, const PIString & value);
//! ~english Removes an URL path argument from the message //! \~english Removes an URL path argument from the message
//! ~russian Удаляет URL query path из сообщения //! \~russian Удаляет URL query path из сообщения
MessageMutable & removePathArgument(const PIString & arg); MessageMutable & removePathArgument(const PIString & arg);
//! ~english Creates message from HTTP status code //! \~english Creates message from HTTP status code
//! ~russian Создает сообщение из HTTP-статус кода //! \~russian Создает сообщение из HTTP-статус кода
static MessageMutable fromCode(PIHTTP::Code c); static MessageMutable fromCode(PIHTTP::Code c);
//! ~english Creates message from HTTP method //! \~english Creates message from HTTP method
//! ~russian Создает сообщение из HTTP-метода //! \~russian Создает сообщение из HTTP-метода
static MessageMutable fromMethod(PIHTTP::Method m); static MessageMutable fromMethod(PIHTTP::Method m);
}; };
//! ~english Gets string representation of HTTP method //! \~english Gets string representation of HTTP method
//! ~russian Возвращает строковое представление HTTP-метода //! \~russian Возвращает строковое представление HTTP-метода
PIP_EXPORT const char * methodName(Method m); PIP_EXPORT const char * methodName(Method m);

View File

@@ -1,3 +1,14 @@
//! \addtogroup HTTP
//! \{
//! \file microhttpd_server.h
//! \brief Base HTTP server class
//! \~english Base HTTP server class using libmicrohttpd
//! \~russian Базовый класс HTTP сервера с использованием libmicrohttpd
//! \details
//! \~english Provides core HTTP server functionality with connection handling
//! \~russian Обеспечивает базовую функциональность HTTP сервера с обработкой соединений
//! \}
#ifndef MICROHTTPD_SERVER_P_H #ifndef MICROHTTPD_SERVER_P_H
#define MICROHTTPD_SERVER_P_H #define MICROHTTPD_SERVER_P_H
@@ -7,85 +18,89 @@
struct MicrohttpdServerConnection; struct MicrohttpdServerConnection;
//! ~english Base HTTP server class implementing core functionality //! \~english Base HTTP server class implementing core functionality
//! ~runnan Базовый класс HTTP сервера, реализующий основную функциональность //! \~russian Базовый класс HTTP сервера, реализующий основную функциональность
class PIP_HTTP_SERVER_EXPORT MicrohttpdServer: public PIObject { class PIP_HTTP_SERVER_EXPORT MicrohttpdServer: public PIObject {
PIOBJECT(MicrohttpdServer) PIOBJECT(MicrohttpdServer)
friend struct MicrohttpdServerConnection; friend struct MicrohttpdServerConnection;
public: public:
//! \~english Constructs a new MicroHTTP server
//! \~russian Создает новый MicroHTTP сервер
MicrohttpdServer(); MicrohttpdServer();
//! \~english Destroys the MicroHTTP server
//! \~russian Уничтожает MicroHTTP сервер
virtual ~MicrohttpdServer(); virtual ~MicrohttpdServer();
//! ~english Server configuration options //! \~english Server configuration options
//! ~russian Опции конфигурации сервера //! \~russian Опции конфигурации сервера
enum class Option { enum class Option {
ConnectionLimit, //!< ~english Maximum concurrent connections ConnectionLimit, //!< \~english Maximum concurrent connections
//!< ~russian Максимальное количество соединений //!< \~russian Максимальное количество соединений
ConnectionTimeout, //!< ~english Connection timeout in seconds ConnectionTimeout, //!< \~english Connection timeout in seconds
//!< ~russian Таймаут соединения в секундах //!< \~russian Таймаут соединения в секундах
HTTPSEnabled, //!< ~english Enable HTTPS support HTTPSEnabled, //!< \~english Enable HTTPS support
//!< ~russian Включить поддержку HTTPS //!< \~russian Включить поддержку HTTPS
HTTPSMemKey, //!< ~english SSL key in memory (PIByteArray) HTTPSMemKey, //!< \~english SSL key in memory (PIByteArray)
//!< ~russian SSL ключ в памяти (PIByteArray) //!< \~russian SSL ключ в памяти (PIByteArray)
HTTPSMemCert, //!< ~english SSL certificate in memory (PIByteArray) HTTPSMemCert, //!< \~english SSL certificate in memory (PIByteArray)
//!< ~russian SSL сертификат в памяти (PIByteArray) //!< \~russian SSL сертификат в памяти (PIByteArray)
HTTPSKeyPassword //!< ~english SSL key password (PIByteArray) HTTPSKeyPassword //!< \~english SSL key password (PIByteArray)
//!< ~russian Пароль SSL ключа (PIByteArray) //!< \~russian Пароль SSL ключа (PIByteArray)
}; };
//! ~english Sets server option //! \~english Sets server option
//! ~russian Устанавливает опцию сервера //! \~russian Устанавливает опцию сервера
void setOption(Option o, PIVariant v); void setOption(Option o, PIVariant v);
//! ~english Sets server favicon //! \~english Sets server favicon
//! ~russian Устанавливает фавикон сервера //! \~russian Устанавливает фавикон сервера
void setFavicon(const PIByteArray & im); void setFavicon(const PIByteArray & im);
//! ~english Starts server on specified address //! \~english Starts server on specified address
//! ~russian Запускает сервер на указанном адресе //! \~russian Запускает сервер на указанном адресе
bool listen(PINetworkAddress addr); bool listen(PINetworkAddress addr);
//! ~english Starts server on all interfaces //! \~english Starts server on all interfaces
//! ~russian Запускает сервер на всех интерфейсах //! \~russian Запускает сервер на всех интерфейсах
bool listenAll(ushort port) { return listen({0, port}); } bool listenAll(ushort port) { return listen({0, port}); }
//! ~english Checks if server is running //! \~english Checks if server is running
//! ~russian Проверяет, работает ли сервер //! \~russian Проверяет, работает ли сервер
bool isListen() const; bool isListen() const;
//! ~english Stops the server //! \~english Stops the server
//! ~russian Останавливает сервер //! \~russian Останавливает сервер
void stop(); void stop();
//! ~english Enables basic authentication //! \~english Enables basic authentication
//! ~russian Включает базовую аутентификацию //! \~russian Включает базовую аутентификацию
void enableBasicAuth() { setBasicAuthEnabled(true); } void enableBasicAuth() { setBasicAuthEnabled(true); }
//! ~english Disables basic authentication //! \~english Disables basic authentication
//! ~russian Выключает базовую аутентификацию //! \~russian Выключает базовую аутентификацию
void disableBasicAuth() { setBasicAuthEnabled(false); } void disableBasicAuth() { setBasicAuthEnabled(false); }
//! ~english Set basic authentication enabled to "yes" //! \~english Set basic authentication enabled to "yes"
//! ~russian Устанавливает базовую аутентификацию в "yes" //! \~russian Устанавливает базовую аутентификацию в "yes"
void setBasicAuthEnabled(bool yes) { use_basic_auth = yes; } void setBasicAuthEnabled(bool yes) { use_basic_auth = yes; }
//! ~english Return if basic authentication enabled //! \~english Return if basic authentication enabled
//! ~russian Возвращает включена ли базовая аутентификация //! \~russian Возвращает включена ли базовая аутентификация
bool isBasicAuthEnabled() const { return use_basic_auth; } bool isBasicAuthEnabled() const { return use_basic_auth; }
//! ~english Sets basic authentication realm //! \~english Sets basic authentication realm
//! ~russian Устанавливает область аутентификации //! \~russian Устанавливает область аутентификации
void setBasicAuthRealm(const PIString & r) { realm = r; } void setBasicAuthRealm(const PIString & r) { realm = r; }
//! ~english Sets request processing callback //! \~english Sets request processing callback
//! ~russian Устанавливает callback для обработки запросов //! \~russian Устанавливает callback для обработки запросов
void setRequestCallback(std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)> c) { callback = c; } void setRequestCallback(std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)> c) { callback = c; }
//! ~english Sets basic authentication callback //! \~english Sets basic authentication callback
//! ~russian Устанавливает callback для базовой аутентификации //! \~russian Устанавливает callback для базовой аутентификации
void setBasicAuthCallback(std::function<bool(const PIString &, const PIString &)> c) { callback_auth = c; } void setBasicAuthCallback(std::function<bool(const PIString &, const PIString &)> c) { callback_auth = c; }
private: private:

View File

@@ -1,26 +1,41 @@
//! \addtogroup HTTP
//! \{
//! \file pihttpserver.h
//! \brief High-level HTTP server implementation
//! \~english High-level HTTP server with path-based routing and handler registration
//! \~russian Высокоуровневый HTTP сервер с маршрутизацией по путям и регистрацией обработчиков
//! \details
//! \~english Provides path-based request routing and handler management
//! \~russian Обеспечивает маршрутизацию запросов по путям и управление обработчиками
//! \}
#ifndef PIHTTPSERVER_H #ifndef PIHTTPSERVER_H
#define PIHTTPSERVER_H #define PIHTTPSERVER_H
#include "microhttpd_server.h" #include "microhttpd_server.h"
//! ~english HTTP server //! \~english HTTP server
//! ~russian HTTP сервер //! \~russian HTTP сервер
class PIP_HTTP_SERVER_EXPORT PIHTTPServer: public MicrohttpdServer { class PIP_HTTP_SERVER_EXPORT PIHTTPServer: public MicrohttpdServer {
PIOBJECT_SUBCLASS(PIHTTPServer, MicrohttpdServer) PIOBJECT_SUBCLASS(PIHTTPServer, MicrohttpdServer)
public: public:
//! \~english Constructs a new HTTP server
//! \~russian Создает новый HTTP сервер
PIHTTPServer(); PIHTTPServer();
//! \~english Destroys the HTTP server
//! \~russian Уничтожает HTTP сервер
virtual ~PIHTTPServer(); virtual ~PIHTTPServer();
using RequestFunction = std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)>; using RequestFunction = std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)>;
//! ~english Registers handler for specific path and HTTP method //! \~english Registers handler for specific path and HTTP method
//! ~russian Регистрирует обработчик для указанного пути и HTTP метода //! \~russian Регистрирует обработчик для указанного пути и HTTP метода
bool registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor); bool registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor);
//! ~english Registers handler for specific path and HTTP method //! \~english Registers handler for specific path and HTTP method
//! ~russian Регистрирует обработчик для указанного пути и HTTP метода //! \~russian Регистрирует обработчик для указанного пути и HTTP метода
template<typename T> template<typename T>
bool bool
registerPath(const PIString & path, PIHTTP::Method method, T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) { registerPath(const PIString & path, PIHTTP::Method method, T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) {
@@ -28,36 +43,36 @@ public:
} }
//! ~english Registers handler for unregistered pathes //! \~english Registers handler for unregistered pathes
//! ~russian Регистрирует обработчик для незарегистрированных путей //! \~russian Регистрирует обработчик для незарегистрированных путей
void registerUnhandled(RequestFunction functor); void registerUnhandled(RequestFunction functor);
//! ~english Registers handler for unregistered pathes //! \~english Registers handler for unregistered pathes
//! ~russian Регистрирует обработчик для незарегистрированных путей //! \~russian Регистрирует обработчик для незарегистрированных путей
template<typename T> template<typename T>
void registerUnhandled(T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) { void registerUnhandled(T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) {
registerUnhandled([o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); }); registerUnhandled([o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); });
} }
//! ~english Unregisters handler for specific path and method //! \~english Unregisters handler for specific path and method
//! ~russian Удаляет обработчик для указанного пути и метода //! \~russian Удаляет обработчик для указанного пути и метода
void unregisterPath(const PIString & path, PIHTTP::Method method); void unregisterPath(const PIString & path, PIHTTP::Method method);
//! ~english Unregisters all handlers for specific path //! \~english Unregisters all handlers for specific path
//! ~russian Удаляет все обработчики для указанного пути //! \~russian Удаляет все обработчики для указанного пути
void unregisterPath(const PIString & path); void unregisterPath(const PIString & path);
//! ~english Adds header to all server responses //! \~english Adds header to all server responses
//! ~russian Добавляет заголовок ко всем ответам сервера //! \~russian Добавляет заголовок ко всем ответам сервера
void addReplyHeader(const PIString & name, const PIString & value) { reply_headers[name] = value; } void addReplyHeader(const PIString & name, const PIString & value) { reply_headers[name] = value; }
//! ~english Removes header from server responses //! \~english Removes header from server responses
//! ~russian Удаляет заголовок из ответов сервера //! \~russian Удаляет заголовок из ответов сервера
void removeReplyHeader(const PIString & name) { reply_headers.remove(name); } void removeReplyHeader(const PIString & name) { reply_headers.remove(name); }
//! ~english Clears all custom response headers //! \~english Clears all custom response headers
//! ~russian Очищает все пользовательские заголовки ответов //! \~russian Очищает все пользовательские заголовки ответов
void clearReplyHeaders() { reply_headers.clear(); } void clearReplyHeaders() { reply_headers.clear(); }
private: private:

View File

@@ -61,8 +61,13 @@ class PIIntrospection;
class PIIntrospectionServer; class PIIntrospectionServer;
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) #if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
//! \~english Declare singleton interface for introspection module T
//! \~russian Объявить интерфейс-синглтон для интроспекции модуля T
# define __PIINTROSPECTION_SINGLETON_H__(T) static PIIntrospection##T##Interface * instance(); # define __PIINTROSPECTION_SINGLETON_H__(T) static PIIntrospection##T##Interface * instance();
//! \~english Implement singleton interface for introspection module T
//! \~russian Реализовать интерфейс-синглтон для интроспекции модуля T
# define __PIINTROSPECTION_SINGLETON_CPP__(T) \ # define __PIINTROSPECTION_SINGLETON_CPP__(T) \
PIIntrospection##T##Interface * PIIntrospection##T##Interface::instance() { \ PIIntrospection##T##Interface * PIIntrospection##T##Interface::instance() { \
static PIIntrospection##T##Interface ret; \ static PIIntrospection##T##Interface ret; \

View File

@@ -16,31 +16,54 @@
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
//! \addtogroup Introspection
//! \{
//! \file piintrospection_containers.h
//! \brief Container introspection
//! \~english Interface for container introspection and memory tracking
//! \~russian Интерфейс для интроспекции контейнеров и отслеживания памяти
//! \details
//! \~english Provides interface for tracking container memory allocations and usage
//! \~russian Предоставляет интерфейс для отслеживания выделения и использования памяти контейнерами
#ifndef PIINTROSPECTION_CONTAINERS_H #ifndef PIINTROSPECTION_CONTAINERS_H
#define PIINTROSPECTION_CONTAINERS_H # define PIINTROSPECTION_CONTAINERS_H
#include "pibase.h" # include "pibase.h"
//! \~english Container type information structure
//! \~russian Структура информации о типе контейнера
struct PIP_EXPORT PIIntrospectionContainersType { struct PIP_EXPORT PIIntrospectionContainersType {
~PIIntrospectionContainersType(); ~PIIntrospectionContainersType();
void finish(); void finish();
//! \~english Type identifier
//! \~russian Идентификатор типа
uint id = 0; uint id = 0;
//! \~english Type name
//! \~russian Имя типа
const char * name = nullptr; const char * name = nullptr;
//! \~english Demangled type name
//! \~russian Демангл-имя типа
const char * demangled = "?"; const char * demangled = "?";
//! \~english Initialization flag
//! \~russian Флаг инициализации
bool inited = false; bool inited = false;
//! \~english Has demangled name flag
//! \~russian Флаг наличия demangled имени
bool has_demangled = false; bool has_demangled = false;
}; };
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) # if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
# include "piintrospection_base.h" # include "piintrospection_base.h"
class PIIntrospectionContainers; //! \~english Container type information template
//! \~russian Шаблон информации о типе контейнера
template<typename T> template<typename T>
class PIIntrospectionContainersTypeInfo { class PIIntrospectionContainersTypeInfo {
public: public:
//! \~english Get container type information
//! \~russian Получить информацию о типе контейнера
static const PIIntrospectionContainersType & get() { static const PIIntrospectionContainersType & get() {
static PIIntrospectionContainersType ret = create(); static PIIntrospectionContainersType ret = create();
return ret; return ret;
@@ -67,6 +90,8 @@ private:
// clang-format on // clang-format on
//! \~english Container introspection interface
//! \~russian Интерфейс интроспекции контейнеров
class PIP_EXPORT PIIntrospectionContainersInterface { class PIP_EXPORT PIIntrospectionContainersInterface {
friend class PIIntrospection; friend class PIIntrospection;
friend class PIIntrospectionServer; friend class PIIntrospectionServer;
@@ -75,11 +100,23 @@ public:
__PIINTROSPECTION_SINGLETON_H__(Containers) __PIINTROSPECTION_SINGLETON_H__(Containers)
// clang-format off // clang-format off
//! \~english Notify about new container allocation
//! \~russian Уведомить о новом выделении контейнера
void containerNew (const PIIntrospectionContainersType & ti, uint isz); void containerNew (const PIIntrospectionContainersType & ti, uint isz);
//! \~english Notify about container deletion
//! \~russian Уведомить об удалении контейнера
void containerDelete(const PIIntrospectionContainersType & ti); void containerDelete(const PIIntrospectionContainersType & ti);
//! \~english Notify about container memory allocation
//! \~russian Уведомить о выделении памяти контейнером
void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt); void containerAlloc (const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Notify about container memory freeing
//! \~russian Уведомить об освобождении памяти контейнером
void containerFree (const PIIntrospectionContainersType & ti, ullong cnt); void containerFree (const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Notify about container memory usage
//! \~russian Уведомить об использовании памяти контейнером
void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt); void containerUsed (const PIIntrospectionContainersType & ti, ullong cnt);
//! \~english Notify about container unused memory
//! \~russian Уведомить о неиспользуемой памяти контейнера
void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt); void containerUnused(const PIIntrospectionContainersType & ti, ullong cnt);
// clang-format on // clang-format on
@@ -91,14 +128,15 @@ private:
}; };
#else # else
# define PIINTROSPECTION_CONTAINER_NEW(t, isz) # define PIINTROSPECTION_CONTAINER_NEW(t, isz)
# define PIINTROSPECTION_CONTAINER_DELETE(t) # define PIINTROSPECTION_CONTAINER_DELETE(t)
# define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt) # define PIINTROSPECTION_CONTAINER_ALLOC(t, cnt)
# define PIINTROSPECTION_CONTAINER_FREE(t, cnt) # define PIINTROSPECTION_CONTAINER_FREE(t, cnt)
# define PIINTROSPECTION_CONTAINER_USED(t, cnt) # define PIINTROSPECTION_CONTAINER_USED(t, cnt)
# define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt) # define PIINTROSPECTION_CONTAINER_UNUSED(t, cnt)
#endif # endif // defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
#endif // PIINTROSPECTION_CONTAINERS_H #endif // PIINTROSPECTION_CONTAINERS_H
//! \}

View File

@@ -51,13 +51,23 @@ class PISystemMonitor;
# define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name); # define PIINTROSPECTION_START(name) PIINTROSPECTION_SERVER->start(#name);
# define PIINTROSPECTION_STOP PIINTROSPECTION_SERVER->stop(); # define PIINTROSPECTION_STOP PIINTROSPECTION_SERVER->stop();
//! \~english Introspection server class for collecting and broadcasting PIP internal statistics
//! \~russian Класс сервера интроспекции для сбора и распространения внутренних статистик PIP
class PIP_EXPORT PIIntrospectionServer: public PIPeer { class PIP_EXPORT PIIntrospectionServer: public PIPeer {
PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer); PIOBJECT_SUBCLASS(PIIntrospectionServer, PIPeer);
public: public:
//! \~english Get singleton instance of introspection server
//! \~russian Получить синглтон-экземпляр сервера интроспекции
static PIIntrospectionServer * instance(); static PIIntrospectionServer * instance();
//! \~english Start introspection server with specified name
//! \~russian Запустить сервер интроспекции с указанным именем
//! \param server_name \~english Name of the server to start \~russian Имя сервера для запуска
void start(const PIString & server_name); void start(const PIString & server_name);
//! \~english Stop introspection server
//! \~russian Остановить сервер интроспекции
void stop(); void stop();
private: private:

View File

@@ -17,10 +17,22 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef PIINTROSPECTION_THREADS_H //! \addtogroup Introspection
#define PIINTROSPECTION_THREADS_H //! \{
//! \file piintrospection_threads.h
//! \brief Thread introspection interface
//! \~english Interface for thread introspection and monitoring
//! \~russian Интерфейс для интроспекции и мониторинга потоков
//! \details
//! \~english Provides callbacks for thread lifecycle events such as creation, deletion, start, run, wait, stop and completion
//! \~russian Предоставляет обратные вызовы для событий жизненного цикла потоков: создание, удаление, запуск, выполнение, ожидание,
//! остановка и завершение
//! \}
#if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION) #ifndef PIINTROSPECTION_THREADS_H
# define PIINTROSPECTION_THREADS_H
# if defined(PIP_INTROSPECTION) && !defined(PIP_FORCE_NO_PIINTROSPECTION)
# include "piintrospection_base.h" # include "piintrospection_base.h"
@@ -36,6 +48,8 @@ class PIIntrospectionThreads;
# define PIINTROSPECTION_THREAD_STOP(t) PIINTROSPECTION_THREADS->threadStop(t); # define PIINTROSPECTION_THREAD_STOP(t) PIINTROSPECTION_THREADS->threadStop(t);
# define PIINTROSPECTION_THREAD_RUN_DONE(t, us) PIINTROSPECTION_THREADS->threadRunDone(t, us); # define PIINTROSPECTION_THREAD_RUN_DONE(t, us) PIINTROSPECTION_THREADS->threadRunDone(t, us);
//! \~english Thread introspection interface class
//! \~russian Класс интерфейса интроспекции потоков
class PIP_EXPORT PIIntrospectionThreadsInterface { class PIP_EXPORT PIIntrospectionThreadsInterface {
friend class PIIntrospection; friend class PIIntrospection;
@@ -43,12 +57,26 @@ public:
__PIINTROSPECTION_SINGLETON_H__(Threads) __PIINTROSPECTION_SINGLETON_H__(Threads)
// clang-format off // clang-format off
//! \~english Called when new thread is created
//! \~russian Вызывается при создании нового потока
void threadNew (PIThread * t); void threadNew (PIThread * t);
//! \~english Called when thread is deleted
//! \~russian Вызывается при удалении потока
void threadDelete (PIThread * t); void threadDelete (PIThread * t);
//! \~english Called when thread is starting
//! \~russian Вызывается при запуске потока
void threadStart (PIThread * t); void threadStart (PIThread * t);
//! \~english Called when thread starts execution
//! \~russian Вызывается при начале выполнения потока
void threadRun (PIThread * t); void threadRun (PIThread * t);
//! \~english Called when thread is waiting
//! \~russian Вызывается при ожидании потока
void threadWait (PIThread * t); void threadWait (PIThread * t);
//! \~english Called when thread is stopped
//! \~russian Вызывается при остановке потока
void threadStop (PIThread * t); void threadStop (PIThread * t);
//! \~english Called when thread execution is done
//! \~russian Вызывается при завершении выполнения потока
void threadRunDone(PIThread * t, ullong us); void threadRunDone(PIThread * t, ullong us);
// clang-format on // clang-format on
@@ -59,7 +87,7 @@ private:
PIIntrospectionThreads * p; PIIntrospectionThreads * p;
}; };
#else # else
# define PIINTROSPECTION_THREAD_NEW(t) # define PIINTROSPECTION_THREAD_NEW(t)
# define PIINTROSPECTION_THREAD_DELETE(t) # define PIINTROSPECTION_THREAD_DELETE(t)
# define PIINTROSPECTION_THREAD_START(t) # define PIINTROSPECTION_THREAD_START(t)
@@ -67,6 +95,7 @@ private:
# define PIINTROSPECTION_THREAD_WAIT(t) # define PIINTROSPECTION_THREAD_WAIT(t)
# define PIINTROSPECTION_THREAD_STOP(t) # define PIINTROSPECTION_THREAD_STOP(t)
# define PIINTROSPECTION_THREAD_RUN_DONE(t, us) # define PIINTROSPECTION_THREAD_RUN_DONE(t, us)
#endif # endif
#endif // PIINTROSPECTION_THREADS_H #endif // PIINTROSPECTION_THREADS_H
//! \}

View File

@@ -938,7 +938,7 @@ PIString PIBinaryLog::constructFullPathDevice() const {
void PIBinaryLog::configureFromFullPathDevice(const PIString & full_path) { void PIBinaryLog::configureFromFullPathDevice(const PIString & full_path) {
const PIStringList pl = full_path.split(":"); const PIStringList pl = full_path.split(":");
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {
const PIString p(pl[i]); const PIString p(pl[i].trimmed());
switch (i) { switch (i) {
case 0: setLogDir(p); break; case 0: setLogDir(p); break;
case 1: setFilePrefix(p); break; case 1: setFilePrefix(p); break;

View File

@@ -1,9 +1,13 @@
/*! \file pibinarylog.h //! \addtogroup IO
* \ingroup IO //! \{
* \~\brief //! \file pibinarylog.h
* \~english Binary log //! \brief
* \~russian Бинарный лог //! \~english Binary log
*/ //! \~russian Бинарный лог
//! \details
//! \~english Class for writing and reading binary data to/from log files, with support for playback in different modes
//! \~russian Класс для записи и чтения бинарных данных в/из файлов логов с поддержкой воспроизведения в различных режимах
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Class for write binary data to logfile, and read or playback this data Class for write binary data to logfile, and read or playback this data
@@ -29,10 +33,8 @@
#include "pichunkstream.h" #include "pichunkstream.h"
#include "pifile.h" #include "pifile.h"
//! \ingroup IO //! \~english Class for writing and reading binary data to/from log files, with support for playback in different modes
//! \~\brief //! \~russian Класс для записи и чтения бинарных данных в/из файлов логов с поддержкой воспроизведения в различных режимах
//! \~english Binary log
//! \~russian Бинарный лог
class PIP_EXPORT PIBinaryLog: public PIIODevice { class PIP_EXPORT PIBinaryLog: public PIIODevice {
PIIODEVICE(PIBinaryLog, "binlog"); PIIODEVICE(PIBinaryLog, "binlog");
@@ -40,93 +42,146 @@ public:
explicit PIBinaryLog(); explicit PIBinaryLog();
virtual ~PIBinaryLog(); virtual ~PIBinaryLog();
//! \brief Play modes for \a PIBinaryLog //! \~english Play modes for \a PIBinaryLog
//! \~russian Режимы воспроизведения для \a PIBinaryLog
enum PlayMode { enum PlayMode {
PlayRealTime /*! Play in system realtime, default mode */, PlayRealTime /*! \~english Play in system realtime, default mode \~russian В системном реальном времени, режим по умолчанию */,
PlayVariableSpeed /*! Play in software realtime with speed, set by \a setSpeed */, PlayVariableSpeed /*! \~english Play in software realtime with speed, set by \a setSpeed \~russian В программном реальном времени со скоростью, задаваемой через \a setSpeed */,
PlayStaticDelay /*! Play with custom static delay, ignoring timestamp */ PlayStaticDelay /*! \~english Play with custom static delay, ignoring timestamp \~russian С пользовательской статической задержкой, игнорируя метку времени */
}; };
//! \brief Different split modes for writing \a PIBinaryLog, which can separate files by size, by time or by records count //! \~english Different split modes for writing \a PIBinaryLog, which can separate files by size, by time or by records count
//! \~russian Различные режимы разделения для записи \a PIBinaryLog, позволяющие разделять файлы по размеру, времени или количеству записей
enum SplitMode { enum SplitMode {
SplitNone /*! Without separate, default mode */, SplitNone /*! \~english Without separate, default mode \~russian Без разделения, режим по умолчанию */,
SplitTime /*! Separate files by record time */, SplitTime /*! \~english Separate files by record time \~russian Разделение файлов по времени записи */,
SplitSize /*! Separate files by size */, SplitSize /*! \~english Separate files by size \~russian Разделение файлов по размеру */,
SplitCount /*! Separate files by records count */ SplitCount /*! \~english Separate files by records count \~russian Разделение файлов по количеству записей */
}; };
#pragma pack(push, 8) #pragma pack(push, 8)
//! \brief Struct contains information about all records with same ID //! \~english Struct contains information about all records with same ID
//! \~russian Структура содержит информацию обо всех записях с одинаковым ID
struct PIP_EXPORT BinLogRecordInfo { struct PIP_EXPORT BinLogRecordInfo {
//! \~english Constructor, initializes all fields to zero
//! \~russian Конструктор, инициализирует все поля нулями
BinLogRecordInfo() { BinLogRecordInfo() {
id = count = 0; id = count = 0;
minimum_size = maximum_size = 0; minimum_size = maximum_size = 0;
} }
//! \~english Record ID
//! \~russian ID записи
int id; int id;
//! \~english Records count
//! \~russian Количество записей
int count; int count;
//! \~english Minimum record size
//! \~russian Минимальный размер записи
int minimum_size; int minimum_size;
//! \~english Maximum record size
//! \~russian Максимальный размер записи
int maximum_size; int maximum_size;
//! \~english Start time of records
//! \~russian Время начала записей
PISystemTime start_time; PISystemTime start_time;
//! \~english End time of records
//! \~russian Время окончания записей
PISystemTime end_time; PISystemTime end_time;
}; };
//! \brief Struct contains position, ID and timestamp of record in file //! \~english Struct contains position, ID and timestamp of record in file
//! \~russian Структура содержит позицию, ID и метку времени записи в файле
struct PIP_EXPORT BinLogIndex { struct PIP_EXPORT BinLogIndex {
//! \~english Record ID
//! \~russian ID записи
int id; int id;
//! \~english Data size
//! \~russian Размер данных
int data_size; int data_size;
//! \~english Position in file
//! \~russian Позиция в файле
llong pos; llong pos;
//! \~english Timestamp
//! \~russian Метка времени
PISystemTime timestamp; PISystemTime timestamp;
}; };
#pragma pack(pop) #pragma pack(pop)
//! \brief Struct contains full information about Binary Log file and about all Records using map of \a BinLogRecordInfo //! \~english Struct contains full information about Binary Log file and about all Records using map of \a BinLogRecordInfo
//! \~russian Структура содержит полную информацию о файле бинарного лога и обо всех записях с использованием карты \a BinLogRecordInfo
struct PIP_EXPORT BinLogInfo { struct PIP_EXPORT BinLogInfo {
//! \~english Path to the log file
//! \~russian Путь к файлу лога
PIString path; PIString path;
//! \~english Total records count
//! \~russian Общее количество записей
int records_count = 0; int records_count = 0;
//! \~english Log file size
//! \~russian Размер файла лога
llong log_size = 0L; llong log_size = 0L;
//! \~english Start time of logging
//! \~russian Время начала логирования
PISystemTime start_time; PISystemTime start_time;
//! \~english End time of logging
//! \~russian Время окончания логирования
PISystemTime end_time; PISystemTime end_time;
//! \~english Map of record information by ID
//! \~russian Карта информации о записях по ID
PIMap<int, BinLogRecordInfo> records; PIMap<int, BinLogRecordInfo> records;
//! \~english User-defined header data
//! \~russian Пользовательские данные заголовка
PIByteArray user_header; PIByteArray user_header;
}; };
//! Current \a PlayMode //! \~english Returns current \a PlayMode
//! \~russian Возвращает текущий \a PlayMode
PlayMode playMode() const { return play_mode; } PlayMode playMode() const { return play_mode; }
//! Current \a SplitMode //! \~english Returns current \a SplitMode
//! \~russian Возвращает текущий \a SplitMode
SplitMode splitMode() const { return split_mode; } SplitMode splitMode() const { return split_mode; }
//! Current directory where billogs wiil be saved //! \~english Returns current directory where binlogs will be saved
//! \~russian Возвращает текущий каталог, куда будут сохраняться бинарные логи
PIString logDir() const { return property("logDir").toString(); } PIString logDir() const { return property("logDir").toString(); }
//! Returns current file prefix //! \~english Returns current file prefix
//! \~russian Возвращает текущий префикс файла
PIString filePrefix() const { return property("filePrefix").toString(); } PIString filePrefix() const { return property("filePrefix").toString(); }
//! Default ID, used in \a write function //! \~english Returns default ID, used in \a write function
//! \~russian Возвращает ID по умолчанию, используемый в функции \a write
int defaultID() const { return default_id; } int defaultID() const { return default_id; }
//! Returns current play speed //! \~english Returns current play speed
//! \~russian Возвращает текущую скорость воспроизведения
double playSpeed() const { return play_speed > 0 ? 1. / play_speed : 0.; } double playSpeed() const { return play_speed > 0 ? 1. / play_speed : 0.; }
//! Returns current play delay //! \~english Returns current play delay
//! \~russian Возвращает текущую задержку воспроизведения
PISystemTime playDelay() const { return play_delay; } PISystemTime playDelay() const { return play_delay; }
//! Returns current binlog file split time //! \~english Returns current binlog file split time
//! \~russian Возвращает текущее время разделения файла бинарного лога
PISystemTime splitTime() const { return split_time; } PISystemTime splitTime() const { return split_time; }
//! Returns current binlog file split size //! \~english Returns current binlog file split size
//! \~russian Возвращает текущий размер разделения файла бинарного лога
llong splitFileSize() const { return split_size; } llong splitFileSize() const { return split_size; }
//! Returns current binlog file split records count //! \~english Returns current binlog file split records count
//! \~russian Возвращает текущее количество записей для разделения файла бинарного лога
int splitRecordCount() const { return split_count; } int splitRecordCount() const { return split_count; }
//! Returns if rapid start enabled //! \~english Returns if rapid start enabled
//! \~russian Возвращает, включено ли быстрое начало
bool rapidStart() const { return rapid_start; } bool rapidStart() const { return rapid_start; }
//! Returns if index creates while writing //! \~english Returns if index creates while writing
//! \~russian Возвращает, создается ли индекс во время записи
bool createIndexOnFly() const { return create_index_on_fly; } bool createIndexOnFly() const { return create_index_on_fly; }
//! Create binlog file with Filename = path //! Create binlog file with Filename = path

View File

@@ -181,7 +181,7 @@ void PICAN::configureFromFullPathDevice(const PIString & full_path) {
PIString p(pl[i]); PIString p(pl[i]);
switch (i) { switch (i) {
case 0: setPath(p); break; case 0: setPath(p); break;
case 1: setCANID(p.toInt(16)); break; case 1: setCANID(p.trimmed().toInt(16)); break;
default: break; default: break;
} }
} }

View File

@@ -29,16 +29,36 @@
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english CAN device.
//! \~russian Устройство CAN.
class PIP_EXPORT PICAN: public PIIODevice { class PIP_EXPORT PICAN: public PIIODevice {
PIIODEVICE(PICAN, "can"); PIIODEVICE(PICAN, "can");
public: public:
//! \~english Constructs %PICAN with empty path and ReadWrite mode
//! \~russian Создаёт %PICAN с пустым путём и режимом ReadWrite
explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PICAN(const PIString & path = PIString(), PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Destructor
//! \~russian Деструктор
virtual ~PICAN(); virtual ~PICAN();
//! \~english Set CAN ID for filtering received messages
//! \~russian Устанавливает CAN ID для фильтрации принимаемых сообщений
void setCANID(int id); void setCANID(int id);
//! \~english Returns current CAN ID
//! \~russian Возвращает текущий CAN ID
int CANID() const; int CANID() const;
//! \~english Returns CAN ID of last readed message
//! \~russian Возвращает CAN ID последнего прочитанного сообщения
int readedCANID() const; int readedCANID() const;
//! \~english Interrupt blocking operation
//! \~russian Прерывает блокирующую операцию
void interrupt() override; void interrupt() override;
protected: protected:

View File

@@ -1,9 +1,13 @@
/*! \file piconfig.h //! \addtogroup IO
* \ingroup IO //! \{
* \~\brief //! \file piconfig.h
* \~english Configuration files parser and writer //! \brief Configuration files parser and writer
* \~russian Разбор и запись конфигурационных файлов //! \~english Parser and writer for configuration files with tree structure support
*/ //! \~russian Разбор и запись конфигурационных файлов с поддержкой древовидной структуры
//! \details
//! \~english PIConfig provides functionality to read, write and manipulate configuration files in a tree-like structure.
//! \~russian PIConfig предоставляет функциональность для чтения, записи и управления конфигурационными файлами в древовидной структуре.
//! \}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Configuration parser and writer Configuration parser and writer
@@ -58,6 +62,8 @@
Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);} Entry & getValue(const PIString & vname, const double def, bool * exists = 0) const {return getValue(vname, PIString::fromNumber(def), exists);}
// clang-format on // clang-format on
//! \~english Main configuration parser and writer class
//! \~russian Главный класс для разбора и записи конфигурационных файлов
class PIP_EXPORT PIConfig { class PIP_EXPORT PIConfig {
friend class Entry; friend class Entry;
friend class Branch; friend class Branch;
@@ -79,6 +85,8 @@ public:
class Entry; class Entry;
//! \~english Branch class - container for Entry objects
//! \~russian Класс Branch - контейнер для объектов Entry
class PIP_EXPORT Branch: public PIVector<Entry *> { class PIP_EXPORT Branch: public PIVector<Entry *> {
friend class PIConfig; friend class PIConfig;
friend class Entry; friend class Entry;
@@ -90,22 +98,44 @@ public:
public: public:
Branch() { ; } Branch() { ; }
//! \~english Get value from branch by name with default value
//! \~russian Получить значение из ветки по имени со значением по умолчанию
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0);
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const { Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {
return const_cast<Branch *>(this)->getValue(vname, def, exists); return const_cast<Branch *>(this)->getValue(vname, def, exists);
} }
PICONFIG_GET_VALUE PICONFIG_GET_VALUE
//! \~english Get all leaf entries from the entire tree
//! \~russian Получить все листовые записи из всего дерева
Branch allLeaves(); Branch allLeaves();
//! \~english Get all entries with name containing specified substring
//! \~russian Получить все записи с именем, содержащим указанную подстроку
Branch getValues(const PIString & name); Branch getValues(const PIString & name);
//! \~english Get all leaf entries (entries without children)
//! \~russian Получить все листовые записи (записи без детей)
Branch getLeaves(); Branch getLeaves();
//! \~english Get all branch entries (entries with children)
//! \~russian Получить все ветвящиеся записи (записи с детьми)
Branch getBranches(); Branch getBranches();
//! \~english Filter branch by filter string
//! \~russian Фильтровать ветку по строке фильтра
Branch & filter(const PIString & f); Branch & filter(const PIString & f);
//! \~english Check if entry with specified name exists
//! \~russian Проверить, существует ли запись с указанным именем
bool isEntryExists(const PIString & name) const { bool isEntryExists(const PIString & name) const {
for (const auto * i: *this) for (const auto * i: *this)
if (entryExists(i, name)) return true; if (entryExists(i, name)) return true;
return false; return false;
} }
//! \~english Get index of entry in branch
//! \~russian Получить индекс записи в ветке
int indexOf(const Entry * e) { int indexOf(const Entry * e) {
for (int i = 0; i < size_s(); ++i) for (int i = 0; i < size_s(); ++i)
if (at(i) == e) return i; if (at(i) == e) return i;
@@ -138,6 +168,8 @@ public:
}; };
//! \~english Entry class - represents a single configuration entry
//! \~russian Класс Entry - представляет отдельную запись конфигурации
class PIP_EXPORT Entry { class PIP_EXPORT Entry {
friend class PIConfig; friend class PIConfig;
friend class Branch; friend class Branch;
@@ -446,18 +478,24 @@ public:
}; };
//! Read configuration from file at path "path" in mode "mode" //! \~english Open configuration from file at path in specified mode
//! \~russian Открыть конфигурацию из файла по указанному пути в указанном режиме
bool open(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(const PIString & path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Read configuration from string "string" in mode "mode" //! \~english Open configuration from string in specified mode
//! \~russian Открыть конфигурацию из строки в указанном режиме
bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(PIString * string, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! Read configuration from custom device "device" in mode "mode" //! \~english Open configuration from custom I/O device in specified mode
//! \~russian Открыть конфигурацию из пользовательского устройства ввода-вывода в указанном режиме
bool open(PIIODevice * device, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); bool open(PIIODevice * device, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Check if configuration is opened
//! \~russian Проверить, открыта ли конфигурация
bool isOpened() const; bool isOpened() const;
//! Returns top-level entry with name "vname", if doesn`t exists return entry with value "def" and set *exist to false //! \~english Get top-level entry by name with default value
//! \~russian Получить запись верхнего уровня по имени со значением по умолчанию
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0); Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0);
Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const { Entry & getValue(const PIString & vname, const PIString & def = PIString(), bool * exists = 0) const {
return const_cast<PIConfig *>(this)->getValue(vname, def, exists); return const_cast<PIConfig *>(this)->getValue(vname, def, exists);
@@ -504,13 +542,16 @@ public:
//! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0) //! \fn Entry & getValue(const PIString & vname, const double def, bool * exists = 0)
//! \brief Returns top-level entry with name "vname" and default value "def" //! \brief Returns top-level entry with name "vname" and default value "def"
//! \~english Get all top-level entries with name containing substring
//! Returns top-level entries with names with substrings "vname" //! \~russian Получить все записи верхнего уровня с именем, содержащим подстроку
Branch getValues(const PIString & vname); Branch getValues(const PIString & vname);
//! Set top-level entry with name "name" value to "value", type to "type" and if "write" immediate write to file. Add new entry if there //! \~english Set value for top-level entry with name
//! is no suitable exists //! \~russian Установить значение для записи верхнего уровня с именем
//! \details
//! \~english Set top-level entry with name "name" value to "value", type to "type" and if "write" immediate write to file.
//! Add new entry if there is no suitable exists
void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); void setValue(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true);
//! Set top-level entry with name "name" value to "value", type to "l" and if "write" immediate write to file. Add new entry if there is //! Set top-level entry with name "name" value to "value", type to "l" and if "write" immediate write to file. Add new entry if there is
@@ -561,16 +602,20 @@ public:
//! no suitable exists //! no suitable exists
void setValue(const PIString & name, const double value, bool write = true) { setValue(name, PIString::fromNumber(value), "f", write); } void setValue(const PIString & name, const double value, bool write = true) { setValue(name, PIString::fromNumber(value), "f", write); }
//! Returns root entry //! \~english Get root entry of configuration tree
//! \~russian Получить корневую запись дерева конфигурации
Entry & rootEntry() { return root; } Entry & rootEntry() { return root; }
//! Returns top-level entries count //! \~english Get count of top-level entries
//! \~russian Получить количество записей верхнего уровня
int entriesCount() const { return childCount(&root); } int entriesCount() const { return childCount(&root); }
//! Returns if top-level entry with name "name" exists //! \~english Check if top-level entry with name exists
//! \~russian Проверить, существует ли запись верхнего уровня с указанным именем
bool isEntryExists(const PIString & name) const { return entryExists(&root, name); } bool isEntryExists(const PIString & name) const { return entryExists(&root, name); }
//! Returns all top-level entries //! \~english Get all top-level entries
//! \~russian Получить все записи верхнего уровня
Branch allTree() { Branch allTree() {
Branch b; Branch b;
for (auto * i: root._children) for (auto * i: root._children)
@@ -579,7 +624,8 @@ public:
return b; return b;
} }
//! Returns all entries without children //! \~english Get all entries without children (leaves)
//! \~russian Получить все записи без детей (листья)
Branch allLeaves() { Branch allLeaves() {
Branch b; Branch b;
allLeaves(b, &root); allLeaves(b, &root);
@@ -588,35 +634,71 @@ public:
return b; return b;
} }
//! \~english Get index of entry by name
//! \~russian Получить индекс записи по имени
int entryIndex(const PIString & name); int entryIndex(const PIString & name);
//! \~english Get entry name by index
//! \~russian Получить имя записи по индексу
PIString getName(uint number) { return entryByIndex(number)._name; } PIString getName(uint number) { return entryByIndex(number)._name; }
//! \~english Get entry value by index
//! \~russian Получить значение записи по индексу
PIString getValueByIndex(uint number) { return entryByIndex(number)._value; } PIString getValueByIndex(uint number) { return entryByIndex(number)._value; }
//! \~english Get entry type by index
//! \~russian Получить тип записи по индексу
PIChar getType(uint number) { return entryByIndex(number)._type[0]; } PIChar getType(uint number) { return entryByIndex(number)._type[0]; }
//! \~english Get entry comment by index
//! \~russian Получить комментарий записи по индексу
PIString getComment(uint number) { return entryByIndex(number)._comment; } PIString getComment(uint number) { return entryByIndex(number)._comment; }
//! \~english Add new entry with name, value and type
//! \~russian Добавить новую запись с именем, значением и типом
void addEntry(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true); void addEntry(const PIString & name, const PIString & value, const PIString & type = "s", bool write = true);
//! \~english Set name of entry by index
//! \~russian Установить имя записи по индексу
void setName(uint number, const PIString & name, bool write = true); void setName(uint number, const PIString & name, bool write = true);
//! \~english Set value of entry by index
//! \~russian Установить значение записи по индексу
void setValue(uint number, const PIString & value, bool write = true); void setValue(uint number, const PIString & value, bool write = true);
//! \~english Set type of entry by index
//! \~russian Установить тип записи по индексу
void setType(uint number, const PIString & type, bool write = true); void setType(uint number, const PIString & type, bool write = true);
//! \~english Set comment of entry by index
//! \~russian Установить комментарий записи по индексу
void setComment(uint number, const PIString & comment, bool write = true); void setComment(uint number, const PIString & comment, bool write = true);
//! \~english Remove entry by name
//! \~russian Удалить запись по имени
void removeEntry(const PIString & name, bool write = true); void removeEntry(const PIString & name, bool write = true);
//! \~english Remove entry by index
//! \~russian Удалить запись по индексу
void removeEntry(uint number, bool write = true); void removeEntry(uint number, bool write = true);
//! Remove all tree and device content //! Remove all tree and device content
void clear(); void clear();
//! Parse device and build internal tree //! \~english Parse device and build internal tree
//! \~russian Прочитать устройство и построить внутреннее дерево
void readAll(); void readAll();
//! Write all internal tree to device //! \~english Write all internal tree to device
//! \~russian Записать всё внутреннее дерево в устройство
void writeAll(); void writeAll();
//! Returns current tree delimiter, default "." //! \~english Get current tree delimiter
//! \~russian Получить текущий разделитель дерева
const PIString & delimiter() const { return delim; } const PIString & delimiter() const { return delim; }
//! Set current tree delimiter //! \~english Set tree delimiter
//! \~russian Установить разделитель дерева
void setDelimiter(const PIString & d) { void setDelimiter(const PIString & d) {
delim = d; delim = d;
setEntryDelim(&root, d); setEntryDelim(&root, d);
@@ -708,14 +790,18 @@ inline PICout operator<<(PICout s, const PIConfig::Entry & v) {
} }
/** \relatesalso PIConfig \relatesalso PIIODevice //! \~english Service function for reading device settings from configuration
* \brief Service function. useful for configuring devices //! \~russian Сервисная функция для чтения настроек устройства из конфигурации
* \details Function takes entry name "name", default value "def" and two //! \note
* \a PIConfig::Entry sections: "em" and their parent "ep". If there is no //! \~english Useful for implementing PIIODevice::configureDevice()
* parent ep = 0. If "ep" is not null and entry "name" exists in "ep" function //! \~russian Полезно для реализации PIIODevice::configureDevice()
* returns this value. Else returns value of entry "name" in section "em" or //! \~\details Function takes entry name "name", default value "def" and two
* "def" if entry doesn`t exists. \n This function useful to read settings //! \a PIConfig::Entry sections: "em" and their parent "ep". If there is no
* from configuration file in implementation \a PIIODevice::configureDevice() function */ //! parent ep = 0. If "ep" is not null and entry "name" exists in "ep" function
//! returns this value. Else returns value of entry "name" in section "em" or
//! "def" if entry doesn`t exists. \n This function useful to read settings
//! from configuration file in implementation \a PIIODevice::configureDevice() function
//! \relatesalso PIConfig \relatesalso PIIODevice
template<typename T> template<typename T>
T readDeviceSetting(const PIString & name, const T & def, const PIConfig::Entry * em, const PIConfig::Entry * ep) { T readDeviceSetting(const PIString & name, const T & def, const PIConfig::Entry * em, const PIConfig::Entry * ep) {
PIVariant v = PIVariant::fromValue<T>(def); PIVariant v = PIVariant::fromValue<T>(def);

View File

@@ -1047,7 +1047,7 @@ void PIEthernet::configureFromFullPathDevice(const PIString & full_path) {
PIStringList pl = full_path.split(":"); PIStringList pl = full_path.split(":");
bool mcast = false; bool mcast = false;
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {
PIString p(pl[i]); PIString p(pl[i].trimmed());
switch (i) { switch (i) {
case 0: case 0:
p = p.toLowerCase(); p = p.toLowerCase();

View File

@@ -76,30 +76,40 @@ public:
//! Set read address //! Set read address
//! \~english Set read address
//! \~russian Устанавливает адрес для чтения
void setReadAddress(const PIString & ip, int port) { void setReadAddress(const PIString & ip, int port) {
addr_r.set(ip, port); addr_r.set(ip, port);
setPath(addr_r.toString()); setPath(addr_r.toString());
} }
//! Set read address in format "i.i.i.i:p" //! Set read address in format "i.i.i.i:p"
//! \~english Set read address in format "i.i.i.i:p"
//! \~russian Устанавливает адрес для чтения в формате "i.i.i.i:p"
void setReadAddress(const PIString & ip_port) { void setReadAddress(const PIString & ip_port) {
addr_r.set(ip_port); addr_r.set(ip_port);
setPath(addr_r.toString()); setPath(addr_r.toString());
} }
//! Set read address //! Set read address
//! \~english Set read address
//! \~russian Устанавливает адрес для чтения
void setReadAddress(const PINetworkAddress & addr) { void setReadAddress(const PINetworkAddress & addr) {
addr_r = addr; addr_r = addr;
setPath(addr_r.toString()); setPath(addr_r.toString());
} }
//! Set read IP //! Set read IP
//! \~english Set read IP
//! \~russian Устанавливает IP для чтения
void setReadIP(const PIString & ip) { void setReadIP(const PIString & ip) {
addr_r.setIP(ip); addr_r.setIP(ip);
setPath(addr_r.toString()); setPath(addr_r.toString());
} }
//! Set read port //! Set read port
//! \~english Set read port
//! \~russian Устанавливает порт для чтения
void setReadPort(int port) { void setReadPort(int port) {
addr_r.setPort(port); addr_r.setPort(port);
setPath(addr_r.toString()); setPath(addr_r.toString());
@@ -153,12 +163,16 @@ public:
//! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them //! Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
//! \~english Set parameters to "parameters_". You should to reopen %PIEthernet to apply them
//! \~russian Устанавливает параметры "parameters_". Необходимо переоткрыть %PIEthernet для применения
void setParameters(PIFlags<PIEthernet::Parameters> parameters_) { void setParameters(PIFlags<PIEthernet::Parameters> parameters_) {
params = parameters_; params = parameters_;
applyParameters(); applyParameters();
} }
//! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this //! Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this
//! \~english Set parameter "parameter" to state "on". You should to reopen %PIEthernet to apply this
//! \~russian Устанавливает параметр "parameter" в состояние "on". Необходимо переоткрыть %PIEthernet для применения
void setParameter(PIEthernet::Parameters parameter, bool on = true) { void setParameter(PIEthernet::Parameters parameter, bool on = true) {
params.setFlag(parameter, on); params.setFlag(parameter, on);
applyParameters(); applyParameters();
@@ -222,18 +236,24 @@ public:
bool connect(bool threaded = true); bool connect(bool threaded = true);
//! Connect to TCP server with address "ip":"port". Use only for TCP_Client //! Connect to TCP server with address "ip":"port". Use only for TCP_Client
//! \~english Connect to TCP server with address "ip":"port". Use only for TCP_Client
//! \~russian Подключается к TCP серверу по адресу "ip":"port". Только для TCP_Client
bool connect(const PIString & ip, int port, bool threaded = true) { bool connect(const PIString & ip, int port, bool threaded = true) {
setPath(ip + PIStringAscii(":") + PIString::fromNumber(port)); setPath(ip + PIStringAscii(":") + PIString::fromNumber(port));
return connect(threaded); return connect(threaded);
} }
//! Connect to TCP server with address "ip_port". Use only for TCP_Client //! Connect to TCP server with address "ip_port". Use only for TCP_Client
//! \~english Connect to TCP server with address "ip_port". Use only for TCP_Client
//! \~russian Подключается к TCP серверу по адресу "ip_port". Только для TCP_Client
bool connect(const PIString & ip_port, bool threaded = true) { bool connect(const PIString & ip_port, bool threaded = true) {
setPath(ip_port); setPath(ip_port);
return connect(threaded); return connect(threaded);
} }
//! Connect to TCP server with address "addr". Use only for TCP_Client //! Connect to TCP server with address "addr". Use only for TCP_Client
//! \~english Connect to TCP server with address "addr". Use only for TCP_Client
//! \~russian Подключается к TCP серверу по адресу "addr". Только для TCP_Client
bool connect(const PINetworkAddress & addr, bool threaded = true) { bool connect(const PINetworkAddress & addr, bool threaded = true) {
setPath(addr.toString()); setPath(addr.toString());
return connect(threaded); return connect(threaded);
@@ -269,11 +289,15 @@ public:
bool send(const void * data, int size, bool threaded = false); bool send(const void * data, int size, bool threaded = false);
//! Send data "data" with size "size" to address "ip":"port" //! Send data "data" with size "size" to address "ip":"port"
//! \~english Send data "data" with size "size" to address "ip":"port"
//! \~russian Отправляет данные "data" размером "size" на адрес "ip":"port"
bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) { bool send(const PIString & ip, int port, const void * data, int size, bool threaded = false) {
return send(PINetworkAddress(ip, port), data, size, threaded); return send(PINetworkAddress(ip, port), data, size, threaded);
} }
//! Send data "data" with size "size" to address "ip_port" //! Send data "data" with size "size" to address "ip_port"
//! \~english Send data "data" with size "size" to address "ip_port"
//! \~russian Отправляет данные "data" размером "size" на адрес "ip_port"
bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) { bool send(const PIString & ip_port, const void * data, int size, bool threaded = false) {
return send(PINetworkAddress(ip_port), data, size, threaded); return send(PINetworkAddress(ip_port), data, size, threaded);
} }
@@ -285,11 +309,15 @@ public:
bool send(const PIByteArray & data, bool threaded = false); bool send(const PIByteArray & data, bool threaded = false);
//! Send data "data" to address "ip":"port" for UDP //! Send data "data" to address "ip":"port" for UDP
//! \~english Send data "data" to address "ip":"port" for UDP
//! \~russian Отправляет данные "data" на адрес "ip":"port" для UDP
bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) { bool send(const PIString & ip, int port, const PIByteArray & data, bool threaded = false) {
return send(PINetworkAddress(ip, port), data, threaded); return send(PINetworkAddress(ip, port), data, threaded);
} }
//! Send data "data" to address "ip_port" for UDP //! Send data "data" to address "ip_port" for UDP
//! \~english Send data "data" to address "ip_port" for UDP
//! \~russian Отправляет данные "data" на адрес "ip_port" для UDP
bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) { bool send(const PIString & ip_port, const PIByteArray & data, bool threaded = false) {
return send(PINetworkAddress(ip_port), data, threaded); return send(PINetworkAddress(ip_port), data, threaded);
} }

View File

@@ -390,7 +390,7 @@ void PIIODevice::read_func() {
ssize_t readed_ = read(buffer_tr.data(), buffer_tr.size_s()); ssize_t readed_ = read(buffer_tr.data(), buffer_tr.size_s());
if (read_thread.isStopping()) return; if (read_thread.isStopping()) return;
if (readed_ <= 0) { if (readed_ <= 0) {
piMSleep(10); piMSleep(threaded_read_timeout_ms);
// cout << readed_ << ", " << errno << ", " << errorString() << endl; // cout << readed_ << ", " << errno << ", " << errorString() << endl;
return; return;
} }

View File

@@ -63,19 +63,13 @@ typedef std::function<bool(const uchar *, int, void *)> ReadRetFunc;
# define PIIODEVICE(name, prefix) \ # define PIIODEVICE(name, prefix) \
PIOBJECT_SUBCLASS(name, PIIODevice) \ PIOBJECT_SUBCLASS(name, PIIODevice) \
PIIODevice * copy() const override { \ PIIODevice * copy() const override { return new name(); } \
return new name(); \
} \
\ \
public: \ public: \
PIConstChars fullPathPrefix() const override { \ PIConstChars fullPathPrefix() const override { return prefix; } \
return prefix; \ static PIConstChars fullPathPrefixS() { return prefix; } \
} \
static PIConstChars fullPathPrefixS() { \
return prefix; \
} \
\ \
private: private:
#endif #endif
@@ -271,6 +265,10 @@ public:
bool waitThreadedReadFinished(PISystemTime timeout = {}); bool waitThreadedReadFinished(PISystemTime timeout = {});
uint threadedReadTimeout() const { return threaded_read_timeout_ms; }
void setThreadedReadTimeout(uint ms) { threaded_read_timeout_ms = ms; }
//! \~english Returns if threaded write is started //! \~english Returns if threaded write is started
//! \~russian Возвращает запущен ли поток записи //! \~russian Возвращает запущен ли поток записи
bool isThreadedWrite() const; bool isThreadedWrite() const;
@@ -591,7 +589,7 @@ private:
PIQueue<PIPair<PIByteArray, ullong>> write_queue; PIQueue<PIPair<PIByteArray, ullong>> write_queue;
PISystemTime reopen_timeout; PISystemTime reopen_timeout;
ullong tri = 0; ullong tri = 0;
uint threaded_read_buffer_size; uint threaded_read_buffer_size, threaded_read_timeout_ms = 10;
bool reopen_enabled = true, destroying = false; bool reopen_enabled = true, destroying = false;
static PIMutex nfp_mutex; static PIMutex nfp_mutex;

View File

@@ -49,11 +49,15 @@ public:
resetReadError(); resetReadError();
} }
//! \~english Append data to stream
//! \~russian Добавляет данные в поток
bool binaryStreamAppendImp(const void * d, size_t s) { bool binaryStreamAppendImp(const void * d, size_t s) {
if (!dev) return false; if (!dev) return false;
return (dev->write(d, s) == (int)s); return (dev->write(d, s) == (int)s);
} }
//! \~english Take data from stream
//! \~russian Извлекает данные из потока
bool binaryStreamTakeImp(void * d, size_t s) { bool binaryStreamTakeImp(void * d, size_t s) {
if (!dev) return false; if (!dev) return false;
return (dev->read(d, s) == (int)s); return (dev->read(d, s) == (int)s);
@@ -90,6 +94,8 @@ public:
if (io_string) delete io_string; if (io_string) delete io_string;
} }
//! \~english Assign "device" device
//! \~russian Назначает устройство "device"
void setDevice(PIIODevice * device) { void setDevice(PIIODevice * device) {
bin_stream = PIIOBinaryStream(device); bin_stream = PIIOBinaryStream(device);
setStream(&bin_stream); setStream(&bin_stream);

View File

@@ -1067,7 +1067,7 @@ PIString PIPeer::constructFullPathDevice() const {
void PIPeer::configureFromFullPathDevice(const PIString & full_path) { void PIPeer::configureFromFullPathDevice(const PIString & full_path) {
PIStringList pl = full_path.split(":"); PIStringList pl = full_path.split(":");
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {
PIString p(pl[i]); PIString p(pl[i].trimmed());
switch (i) { switch (i) {
case 0: changeName(p); break; case 0: changeName(p); break;
case 1: setTrustPeerName(p); break; case 1: setTrustPeerName(p); break;

View File

@@ -29,6 +29,10 @@
#include "pidiagnostics.h" #include "pidiagnostics.h"
#include "piethernet.h" #include "piethernet.h"
//! \ingroup IO
//! \~\brief
//! \~english Peering net node.
//! \~russian Элемент пиринговой сети.
class PIP_EXPORT PIPeer: public PIIODevice { class PIP_EXPORT PIPeer: public PIIODevice {
PIIODEVICE(PIPeer, "peer"); PIIODEVICE(PIPeer, "peer");
@@ -36,9 +40,16 @@ private:
class PeerData; class PeerData;
public: public:
//! \~english Constructs %PIPeer with name "name"
//! \~russian Создаёт %PIPeer с именем "name"
explicit PIPeer(const PIString & name = PIString()); explicit PIPeer(const PIString & name = PIString());
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIPeer(); virtual ~PIPeer();
//! \~english Peer information structure
//! \~russian Структура информации о пире
class PIP_EXPORT PeerInfo { class PIP_EXPORT PeerInfo {
friend class PIPeer; friend class PIPeer;
BINARY_STREAM_FRIEND(PIPeer::PeerInfo); BINARY_STREAM_FRIEND(PIPeer::PeerInfo);
@@ -87,38 +98,89 @@ public:
BINARY_STREAM_FRIEND(PIPeer::PeerInfo); BINARY_STREAM_FRIEND(PIPeer::PeerInfo);
//! \~english Send data to peer with name "to"
//! \~russian Отправляет данные пиру с именем "to"
bool send(const PIString & to, const PIByteArray & data) { return send(to, data.data(), data.size_s()); } bool send(const PIString & to, const PIByteArray & data) { return send(to, data.data(), data.size_s()); }
//! \~english Send string to peer with name "to"
//! \~russian Отправляет строку пиру с именем "to"
bool send(const PIString & to, const PIString & data) { return send(to, data.data(), data.size_s()); } bool send(const PIString & to, const PIString & data) { return send(to, data.data(), data.size_s()); }
bool send(const PIString & to, const void * data, int size); bool send(const PIString & to, const void * data, int size);
//! \~english Send data to peer "to"
//! \~russian Отправляет данные пиру "to"
bool send(const PeerInfo & to, const PIByteArray & data) { return send(to.name, data.data(), data.size_s()); } bool send(const PeerInfo & to, const PIByteArray & data) { return send(to.name, data.data(), data.size_s()); }
bool send(const PeerInfo & to, const PIString & data) { return send(to.name, data.data(), data.size_s()); } bool send(const PeerInfo & to, const PIString & data) { return send(to.name, data.data(), data.size_s()); }
bool send(const PeerInfo & to, const void * data, int size) { return send(to.name, data, size); } bool send(const PeerInfo & to, const void * data, int size) { return send(to.name, data, size); }
bool send(const PeerInfo * to, const PIByteArray & data); bool send(const PeerInfo * to, const PIByteArray & data);
bool send(const PeerInfo * to, const PIString & data); bool send(const PeerInfo * to, const PIString & data);
bool send(const PeerInfo * to, const void * data, int size); bool send(const PeerInfo * to, const void * data, int size);
//! \~english Send data to all peers
//! \~russian Отправляет данные всем пирам
void sendToAll(const PIByteArray & data); void sendToAll(const PIByteArray & data);
void sendToAll(const PIString & data); void sendToAll(const PIString & data);
void sendToAll(const void * data, int size); void sendToAll(const void * data, int size);
//! \~english Returns if receiving multicast packets is enabled
//! \~russian Возвращает включён ли приём мультикаст пакетов
bool isMulticastReceive() const { return !eths_mcast.isEmpty(); } bool isMulticastReceive() const { return !eths_mcast.isEmpty(); }
//! \~english Returns if receiving broadcast packets is enabled
//! \~russian Возвращает включён ли приём широковещательных пакетов
bool isBroadcastReceive() const { return !eths_bcast.isEmpty(); } bool isBroadcastReceive() const { return !eths_bcast.isEmpty(); }
//! \~english Returns diagnostic service
//! \~russian Возвращает диагностический сервис
PIDiagnostics & diagnosticService() { return diag_s; } PIDiagnostics & diagnosticService() { return diag_s; }
//! \~english Returns diagnostic data
//! \~russian Возвращает диагностические данные
PIDiagnostics & diagnosticData() { return diag_d; } PIDiagnostics & diagnosticData() { return diag_d; }
//! \~english Returns all known peers
//! \~russian Возвращает всех известных пиров
const PIVector<PIPeer::PeerInfo> & allPeers() const { return peers; } const PIVector<PIPeer::PeerInfo> & allPeers() const { return peers; }
//! \~english Returns if peer with name "name" exists
//! \~russian Возвращает существует ли пир с именем "name"
bool isPeerExists(const PIString & name) const { return getPeerByName(name) != 0; } bool isPeerExists(const PIString & name) const { return getPeerByName(name) != 0; }
//! \~english Returns peer info by name, or nullptr if not found
//! \~russian Возвращает информацию о пире по имени, или nullptr если не найден
const PeerInfo * getPeerByName(const PIString & name) const { return peers_map.value(name, 0); } const PeerInfo * getPeerByName(const PIString & name) const { return peers_map.value(name, 0); }
//! \~english Returns self info
//! \~russian Возвращает информацию о себе
const PeerInfo & selfInfo() const { return self_info; } const PeerInfo & selfInfo() const { return self_info; }
const PIMap<PIString, PIVector<PeerInfo *>> & _peerMap() const { return addresses_map; } const PIMap<PIString, PIVector<PeerInfo *>> & _peerMap() const { return addresses_map; }
//! \~english Reinitialize peer network
//! \~russian Переинициализирует пиринговую сеть
void reinit(); void reinit();
//! \~english Lock peers list
//! \~russian Блокирует список пиров
void lock() { peers_mutex.lock(); } void lock() { peers_mutex.lock(); }
//! \~english Unlock peers list
//! \~russian Разблокирует список пиров
void unlock() { peers_mutex.unlock(); } void unlock() { peers_mutex.unlock(); }
//! \~english Change peer name to "new_name"
//! \~russian Изменяет имя пира на "new_name"
void changeName(const PIString & new_name); void changeName(const PIString & new_name);
//! \~english Returns trusted peer name
//! \~russian Возвращает имя доверенного пира
const PIString & trustPeerName() const { return trust_peer; } const PIString & trustPeerName() const { return trust_peer; }
//! \~english Set trusted peer name
//! \~russian Устанавливает имя доверенного пира
void setTrustPeerName(const PIString & peer_name) { trust_peer = peer_name; } void setTrustPeerName(const PIString & peer_name) { trust_peer = peer_name; }
//! \~english Set TCP server IP address
//! \~russian Устанавливает IP адрес TCP сервера
void setTcpServerIP(const PIString & ip); void setTcpServerIP(const PIString & ip);
ssize_t bytesAvailable() const override; ssize_t bytesAvailable() const override;

View File

@@ -983,7 +983,7 @@ void PISerial::configureFromFullPathDevice(const PIString & full_path) {
} }
} }
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {
PIString p(pl[i]); PIString p(pl[i].trimmed());
switch (i) { switch (i) {
case 0: setProperty("path", p); break; case 0: setProperty("path", p); break;
case 1: case 1:

View File

@@ -216,6 +216,8 @@ public:
//! \~russian Переключает состояние передачи в break //! \~russian Переключает состояние передачи в break
bool setBreak(bool enabled); bool setBreak(bool enabled);
//! \~english Set VTime parameter
//! \~russian Устанавливает параметр VTime
void setVTime(int t) { void setVTime(int t) {
vtime = t; vtime = t;
applySettings(); applySettings();

View File

@@ -182,7 +182,7 @@ void PISharedMemory::configureFromFullPathDevice(const PIString & full_path) {
initPrivate(); initPrivate();
PIStringList pl = full_path.split(":"); PIStringList pl = full_path.split(":");
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {
PIString p(pl[i]); PIString p(pl[i].trimmed());
switch (i) { switch (i) {
case 0: setPath(p); break; case 0: setPath(p); break;
case 1: dsize = p.toInt(); break; case 1: dsize = p.toInt(); break;

View File

@@ -187,7 +187,7 @@ PIString PISPI::constructFullPathDevice() const {
void PISPI::configureFromFullPathDevice(const PIString & full_path) { void PISPI::configureFromFullPathDevice(const PIString & full_path) {
PIStringList pl = full_path.split(":"); PIStringList pl = full_path.split(":");
for (int i = 0; i < pl.size_s(); ++i) { for (int i = 0; i < pl.size_s(); ++i) {
PIString p(pl[i]); PIString p(pl[i].trimmed());
switch (i) { switch (i) {
case 0: setPath(p); break; case 0: setPath(p); break;
case 1: setSpeed(p.toInt()); break; case 1: setSpeed(p.toInt()); break;

View File

@@ -29,35 +29,59 @@
#include "piiodevice.h" #include "piiodevice.h"
//! \ingroup IO
//! \~\brief
//! \~english SPI device.
//! \~russian Устройство SPI.
class PIP_EXPORT PISPI: public PIIODevice { class PIP_EXPORT PISPI: public PIIODevice {
PIIODEVICE(PISPI, "spi"); PIIODEVICE(PISPI, "spi");
public: public:
//! \~english Constructs %PISPI with path "path", speed "speed_hz" and mode "mode"
//! \~russian Создаёт %PISPI с путём "path", скоростью "speed_hz" и режимом "mode"
explicit PISPI(const PIString & path = PIString(), uint speed_hz = 1000000, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite); explicit PISPI(const PIString & path = PIString(), uint speed_hz = 1000000, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite);
//! \~english Destructor
//! \~russian Деструктор
virtual ~PISPI(); virtual ~PISPI();
//! \brief Parameters of PISPI //! \~english Parameters of PISPI
//! \~russian Параметры PISPI
enum Parameters { enum Parameters {
ClockInverse /*! SPI clk polarity control*/ = 0x1, ClockInverse /*! \~english SPI clk polarity control \~russian Управление полярностью SPI clk */ = 0x1,
ClockPhaseShift /*! SPI clk phase control */ = 0x2, ClockPhaseShift /*! \~english SPI clk phase control \~russian Управление фазой SPI clk */ = 0x2,
}; };
//! \~english Set SPI speed in Hz
//! \~russian Устанавливает скорость SPI в Гц
void setSpeed(uint speed_hz); void setSpeed(uint speed_hz);
//! \~english Returns current SPI speed in Hz
//! \~russian Возвращает текущую скорость SPI в Гц
uint speed() const { return spi_speed; } uint speed() const { return spi_speed; }
//! \~english Set number of bits per word, default is 8
//! \~russian Устанавливает количество бит на слово, по умолчанию 8
void setBits(uchar bits = 8); void setBits(uchar bits = 8);
//! \~english Returns number of bits per word
//! \~russian Возвращает количество бит на слово
uchar bits() const { return spi_bits; } uchar bits() const { return spi_bits; }
//! Set parameters to "parameters_" //! \~english Set parameters to "parameters_"
//! \~russian Устанавливает параметры в "parameters_"
void setParameters(PIFlags<PISPI::Parameters> parameters_) { spi_mode = (int)parameters_; } void setParameters(PIFlags<PISPI::Parameters> parameters_) { spi_mode = (int)parameters_; }
//! Set parameter "parameter" to "on" state //! \~english Set parameter "parameter" to "on" state
//! \~russian Устанавливает параметр "parameter" в состояние "on"
void setParameter(PISPI::Parameters parameter, bool on = true); void setParameter(PISPI::Parameters parameter, bool on = true);
//! Returns if parameter "parameter" is set //! \~english Returns if parameter "parameter" is set
//! \~russian Возвращает установлен ли параметр "parameter"
bool isParameterSet(PISPI::Parameters parameter) const; bool isParameterSet(PISPI::Parameters parameter) const;
//! Returns parameters //! \~english Returns parameters
//! \~russian Возвращает параметры
PIFlags<PISPI::Parameters> parameters() const { return spi_mode; } PIFlags<PISPI::Parameters> parameters() const { return spi_mode; }
ssize_t bytesAvailable() const override; ssize_t bytesAvailable() const override;

View File

@@ -62,13 +62,24 @@
struct usb_dev_handle; struct usb_dev_handle;
//! \ingroup IO
//! \~\brief
//! \~english USB device.
//! \~russian Устройство USB.
class PIP_USB_EXPORT PIUSB: public PIIODevice { class PIP_USB_EXPORT PIUSB: public PIIODevice {
PIIODEVICE(PIUSB, "usb"); PIIODEVICE(PIUSB, "usb");
public: public:
//! \~english Constructs %PIUSB with vendor ID "vid" and product ID "pid"
//! \~russian Создаёт %PIUSB с идентификатором поставщика "vid" и идентификатором продукта "pid"
explicit PIUSB(ushort vid = 0, ushort pid = 0); explicit PIUSB(ushort vid = 0, ushort pid = 0);
//! \~english Destructor
//! \~russian Деструктор
virtual ~PIUSB(); virtual ~PIUSB();
//! \~english USB endpoint structure
//! \~russian Структура USB endpoint
struct PIP_USB_EXPORT Endpoint { struct PIP_USB_EXPORT Endpoint {
Endpoint(uchar a = 0, uchar at = 0, ushort mps = 0) { Endpoint(uchar a = 0, uchar at = 0, ushort mps = 0) {
address = a; address = a;
@@ -111,6 +122,8 @@ public:
UsageType usage_type = DataEndpoint; UsageType usage_type = DataEndpoint;
}; };
//! \~english USB interface structure
//! \~russian Структура USB интерфейса
struct PIP_USB_EXPORT Interface { struct PIP_USB_EXPORT Interface {
uchar index = 0; uchar index = 0;
uchar value_to_select = 0; uchar value_to_select = 0;
@@ -120,6 +133,8 @@ public:
PIVector<PIUSB::Endpoint> endpoints; PIVector<PIUSB::Endpoint> endpoints;
}; };
//! \~english USB configuration structure
//! \~russian Структура USB конфигурации
struct PIP_USB_EXPORT Configuration { struct PIP_USB_EXPORT Configuration {
uchar index = 0; uchar index = 0;
uchar value_to_select = 0; uchar value_to_select = 0;
@@ -130,6 +145,8 @@ public:
PIVector<PIUSB::Interface> interfaces; PIVector<PIUSB::Interface> interfaces;
}; };
//! \~english USB device descriptor structure
//! \~russian Структура дескриптора USB устройства
struct PIP_USB_EXPORT Descriptor { struct PIP_USB_EXPORT Descriptor {
ushort usb_spec_number = 0; ushort usb_spec_number = 0;
uchar device_class = 0; uchar device_class = 0;
@@ -145,36 +162,100 @@ public:
PIVector<PIUSB::Configuration> configurations; PIVector<PIUSB::Configuration> configurations;
}; };
//! \~english Returns current device descriptor
//! \~russian Возвращает текущий дескриптор устройства
const PIUSB::Descriptor & currentDescriptor() const { return desc_; } const PIUSB::Descriptor & currentDescriptor() const { return desc_; }
//! \~english Returns current configuration
//! \~russian Возвращает текущую конфигурацию
const PIUSB::Configuration & currentConfiguration() const { return conf_; } const PIUSB::Configuration & currentConfiguration() const { return conf_; }
//! \~english Returns current interface
//! \~russian Возвращает текущий интерфейс
const PIUSB::Interface & currentInterface() const { return iface_; } const PIUSB::Interface & currentInterface() const { return iface_; }
//! \~english Returns vendor ID
//! \~russian Возвращает ID поставщика
ushort vendorID() const { return vid_; } ushort vendorID() const { return vid_; }
//! \~english Returns product ID
//! \~russian Возвращает ID продукта
ushort productID() const { return pid_; } ushort productID() const { return pid_; }
//! \~english Returns device number
//! \~russian Возвращает номер устройства
int deviceNumber() const { return property("deviceNumber").toInt(); } int deviceNumber() const { return property("deviceNumber").toInt(); }
//! \~english Returns read timeout in milliseconds
//! \~russian Возвращает таймаут чтения в миллисекундах
int timeoutRead() const { return property("timeoutRead").toInt(); } int timeoutRead() const { return property("timeoutRead").toInt(); }
//! \~english Returns write timeout in milliseconds
//! \~russian Возвращает таймаут записи в миллисекундах
int timeoutWrite() const { return property("timeoutWrite").toInt(); } int timeoutWrite() const { return property("timeoutWrite").toInt(); }
//! \~english Returns read endpoint
//! \~russian Возвращает endpoint для чтения
const PIUSB::Endpoint & endpointRead() const { return ep_read; } const PIUSB::Endpoint & endpointRead() const { return ep_read; }
//! \~english Returns write endpoint
//! \~russian Возвращает endpoint для записи
const PIUSB::Endpoint & endpointWrite() const { return ep_write; } const PIUSB::Endpoint & endpointWrite() const { return ep_write; }
//! \~english Returns all endpoints
//! \~russian Возвращает все endpoints
const PIVector<PIUSB::Endpoint> & endpoints() const { return eps; } const PIVector<PIUSB::Endpoint> & endpoints() const { return eps; }
//! \~english Returns read endpoints
//! \~russian Возвращает endpoints для чтения
PIVector<PIUSB::Endpoint> endpointsRead(); PIVector<PIUSB::Endpoint> endpointsRead();
//! \~english Returns write endpoints
//! \~russian Возвращает endpoints для записи
PIVector<PIUSB::Endpoint> endpointsWrite(); PIVector<PIUSB::Endpoint> endpointsWrite();
//! \~english Returns endpoint by address
//! \~russian Возвращает endpoint по адресу
PIUSB::Endpoint getEndpointByAddress(uchar address); PIUSB::Endpoint getEndpointByAddress(uchar address);
//! \~english Set vendor ID to "vid"
//! \~russian Устанавливает ID поставщика в "vid"
void setVendorID(ushort vid); void setVendorID(ushort vid);
//! \~english Set product ID to "pid"
//! \~russian Устанавливает ID продукта в "pid"
void setProductID(ushort pid); void setProductID(ushort pid);
//! \~english Set configuration by value
//! \~russian Устанавливает конфигурацию по значению
bool setConfiguration(uchar value); bool setConfiguration(uchar value);
//! \~english Set interface by value
//! \~russian Устанавливает интерфейс по значению
bool setInterface(uchar value); bool setInterface(uchar value);
//! \~english Set read endpoint
//! \~russian Устанавливает endpoint для чтения
void setEndpointRead(const PIUSB::Endpoint & ep) { ep_read = ep; } void setEndpointRead(const PIUSB::Endpoint & ep) { ep_read = ep; }
//! \~english Set write endpoint
//! \~russian Устанавливает endpoint для записи
void setEndpointWrite(const PIUSB::Endpoint & ep) { ep_write = ep; } void setEndpointWrite(const PIUSB::Endpoint & ep) { ep_write = ep; }
//! \~english Set device number
//! \~russian Устанавливает номер устройства
void setDeviceNumber(int dn) { setProperty("deviceNumber", dn); } void setDeviceNumber(int dn) { setProperty("deviceNumber", dn); }
//! \~english Set read timeout in milliseconds
//! \~russian Устанавливает таймаут чтения в миллисекундах
void setTimeoutRead(int t) { setProperty("timeoutRead", t); } void setTimeoutRead(int t) { setProperty("timeoutRead", t); }
//! \~english Set write timeout in milliseconds
//! \~russian Устанавливает таймаут записи в миллисекундах
void setTimeoutWrite(int t) { setProperty("timeoutWrite", t); } void setTimeoutWrite(int t) { setProperty("timeoutWrite", t); }
//! \~english Control write to device
//! \~russian Управляющая запись в устройство
int controlWrite(const void * data, int max_size); int controlWrite(const void * data, int max_size);
virtual void flush() override; virtual void flush() override;

View File

@@ -29,24 +29,39 @@
#include "picrc.h" #include "picrc.h"
#include "pidiagnostics.h" #include "pidiagnostics.h"
//! \~english Base class for reliable send and receive data in fixed packets with error correction, pause and resume
//! \~russian Базовый класс для надежного обмена данными с помощью фиксированных пакетов с коррекцией ошибок и паузой
class PIP_EXPORT PIBaseTransfer: public PIObject { class PIP_EXPORT PIBaseTransfer: public PIObject {
PIOBJECT_SUBCLASS(PIBaseTransfer, PIObject); PIOBJECT_SUBCLASS(PIBaseTransfer, PIObject);
public: public:
//! \~english Constructs empty transfer
//! \~russian Создает пустой transfer
PIBaseTransfer(); PIBaseTransfer();
//! \~english Destructor
//! \~russian Деструктор
~PIBaseTransfer(); ~PIBaseTransfer();
#pragma pack(push, 1) #pragma pack(push, 1)
//! \~english Packet header structure
//! \~russian Структура заголовка пакета
struct PIP_EXPORT PacketHeader { struct PIP_EXPORT PacketHeader {
uint sig; uint sig;
int type; // PacketType int type; // PacketType
int session_id; int session_id;
uint id; uint id;
uint crc; uint crc;
//! \~english Check if signature is valid
//! \~russian Проверка валидности подписи
bool check_sig() { return (sig == signature); } bool check_sig() { return (sig == signature); }
}; };
//! \~english Part information structure
//! \~russian Структура информации о части
struct PIP_EXPORT Part { struct PIP_EXPORT Part {
//! \~english Constructor
//! \~russian Конструктор
Part(uint id_ = 0, ullong size_ = 0, ullong start_ = 0): id(id_), size(size_), start(start_) {} Part(uint id_ = 0, ullong size_ = 0, ullong start_ = 0): id(id_), size(size_), start(start_) {}
uint id; uint id;
ullong size; ullong size;
@@ -54,29 +69,76 @@ public:
}; };
#pragma pack(pop) #pragma pack(pop)
//! \~english Stop sending data
//! \~russian Остановить отправку данных
void stopSend(); void stopSend();
//! \~english Stop receiving data
//! \~russian Остановить прием данных
void stopReceive(); void stopReceive();
//! \~english Check if currently sending
//! \~russian Проверка, идет ли отправка
bool isSending() const { return is_sending; } bool isSending() const { return is_sending; }
//! \~english Check if currently receiving
//! \~russian Проверка, идет ли прием
bool isReceiving() const { return is_receiving; } bool isReceiving() const { return is_receiving; }
//! \~english Check if paused
//! \~russian Проверка, на паузе ли
bool isPause() const { return is_pause; } bool isPause() const { return is_pause; }
//! \~english Set pause state
//! \~russian Установить состояние паузы
void setPause(bool pause_); void setPause(bool pause_);
//! \~english Set packet size
//! \~russian Установить размер пакета
void setPacketSize(int size) { packet_size = size; } void setPacketSize(int size) { packet_size = size; }
//! \~english Get packet size
//! \~russian Получить размер пакета
int packetSize() const { return packet_size; } int packetSize() const { return packet_size; }
//! \~english Set timeout in seconds
//! \~russian Установить таймаут в секундах
void setTimeout(double sec); void setTimeout(double sec);
//! \~english Get timeout in seconds
//! \~russian Получить таймаут в секундах
double timeout() const { return timeout_; } double timeout() const { return timeout_; }
//! \~english Enable/disable CRC check
//! \~russian Включить/выключить проверку CRC
void setCRCEnabled(bool en = true) { crc_enabled = en; } void setCRCEnabled(bool en = true) { crc_enabled = en; }
//! \~english Check if CRC is enabled
//! \~russian Проверка, включен ли CRC
bool isCRCEnabled() const { return crc_enabled; } bool isCRCEnabled() const { return crc_enabled; }
//! \~english Get state as string
//! \~russian Получить состояние в виде строки
PIString stateString() const { return state_string; } PIString stateString() const { return state_string; }
//! \~english Get packet map as string
//! \~russian Получить карту пакетов в виде строки
PIString packetMap() const { return pm_string; } PIString packetMap() const { return pm_string; }
//! \~english Get total bytes count
//! \~russian Получить общее количество байт
llong bytesAll() const { return bytes_all; } llong bytesAll() const { return bytes_all; }
//! \~english Get current bytes count
//! \~russian Получить текущее количество байт
llong bytesCur() const { return bytes_cur; } llong bytesCur() const { return bytes_cur; }
//! \~english Get diagnostics object
//! \~russian Получить объект диагностики
const PIDiagnostics & diagnostic() { return diag; } const PIDiagnostics & diagnostic() { return diag; }
//! \~english Get packet signature
//! \~russian Получить подпись пакета
static uint packetSignature() { return signature; } static uint packetSignature() { return signature; }
EVENT_HANDLER1(void, received, PIByteArray, data); EVENT_HANDLER1(void, received, PIByteArray, data);

View File

@@ -31,13 +31,16 @@
#include "pip_io_utils_export.h" #include "pip_io_utils_export.h"
//! \~english Broadcast for all interfaces, including loopback
//! \~russian Широкое вещание на все интерфейсы, включая loopback
class PIP_IO_UTILS_EXPORT PIBroadcast class PIP_IO_UTILS_EXPORT PIBroadcast
: public PIThread : public PIThread
, public PIEthUtilBase { , public PIEthUtilBase {
PIOBJECT_SUBCLASS(PIBroadcast, PIThread); PIOBJECT_SUBCLASS(PIBroadcast, PIThread);
public: public:
//! %PIBroadcast channels, can be used independently //! \~english %PIBroadcast channels, can be used independently
//! \~russian Каналы %PIBroadcast, могут использоваться независимо
enum Channel { enum Channel {
Multicast /** Use multicast addresses */ = 0x01, Multicast /** Use multicast addresses */ = 0x01,
Broadcast /** Use broadcast addresses */ = 0x02, Broadcast /** Use broadcast addresses */ = 0x02,
@@ -45,75 +48,97 @@ public:
All /** Use all channels */ = 0xFFFF, All /** Use all channels */ = 0xFFFF,
}; };
//! \~english Channels flags type
//! \~russian Тип флагов каналов
typedef PIFlags<Channel> Channels; typedef PIFlags<Channel> Channels;
/** Contructs %PIBroadcast, if \"send_only\" not set //! \~english Constructs %PIBroadcast. If "send_only" not set, all PIEthernets will be binded to receive data
* all PIEthernets will be binded to receive data //! \~russian Создает %PIBroadcast. Если "send_only" не установлен, все PIEthernets будут привязаны для приема данных
* */
PIBroadcast(bool send_only = false); PIBroadcast(bool send_only = false);
//! \~english Destructor
//! \~russian Деструктор
~PIBroadcast(); ~PIBroadcast();
//! Set channels to \"ch\" and queue to reinit //! \~english Set channels to "ch" and queue to reinit
//! \~russian Установить каналы в "ch" и очередь на реинициализацию
void setChannels(Channels ch); void setChannels(Channels ch);
//! Returns channels //! \~english Returns channels
//! \~russian Возвращает каналы
Channels channels() const { return _channels; } Channels channels() const { return _channels; }
//! Returns if is send_only //! \~english Returns if is send_only
//! \~russian Возвращает, является ли отправка только
bool isSendOnly() const { return _send_only; } bool isSendOnly() const { return _send_only; }
//! Set multicast IP to \"mg\" and queue to reinit //! \~english Set multicast IP to "mg" and queue to reinit
//! \~russian Установить multicast IP в "mg" и очередь на реинициализацию
void setMulticastGroup(const PIString & mg); void setMulticastGroup(const PIString & mg);
//! Returns multicast IP //! \~english Returns multicast IP
//! \~russian Возвращает multicast IP
PIString multicastGroup() const { return mcast_address.ipString(); } PIString multicastGroup() const { return mcast_address.ipString(); }
//! Set multicast port to \"port\" and queue to reinit //! \~english Set multicast port to "port" and queue to reinit
//! \~russian Установить multicast порт в "port" и очередь на реинициализацию
void setMulticastPort(ushort port); void setMulticastPort(ushort port);
//! Returns multicast port //! \~english Returns multicast port
//! \~russian Возвращает multicast порт
ushort multicastPort() const { return mcast_address.port(); } ushort multicastPort() const { return mcast_address.port(); }
//! Set multicast address to \"addr\" and queue to reinit //! \~english Set multicast address to "addr" and queue to reinit
//! \~russian Установить multicast адрес в "addr" и очередь на реинициализацию
void setMulticastAddress(const PINetworkAddress & addr); void setMulticastAddress(const PINetworkAddress & addr);
//! Returns multicast address //! \~english Returns multicast address
//! \~russian Возвращает multicast адрес
PINetworkAddress multicastAddress() const { return mcast_address; } PINetworkAddress multicastAddress() const { return mcast_address; }
//! Set broadcast port to \"port\" and queue to reinit //! \~english Set broadcast port to "port" and queue to reinit
//! \~russian Установить broadcast порт в "port" и очередь на реинициализацию
void setBroadcastPort(ushort port); void setBroadcastPort(ushort port);
//! Returns broadcast port //! \~english Returns broadcast port
//! \~russian Возвращает broadcast порт
ushort broadcastPort() { return bcast_port; } ushort broadcastPort() { return bcast_port; }
//! Set loopback start port to \"port\" and queue to reinit //! \~english Set loopback start port to "port" and queue to reinit
//! \~russian Установить начальный loopback порт в "port" и очередь на реинициализацию
void setLoopbackPort(ushort port); void setLoopbackPort(ushort port);
//! Returns loopback start port //! \~english Returns loopback start port
//! \~russian Возвращает начальный loopback порт
ushort loopbackPort() { return lo_port; } ushort loopbackPort() { return lo_port; }
//! Set loopback ports count to \"count\" and queue to reinit //! \~english Set loopback ports count to "count" and queue to reinit
//! \~russian Установить количество loopback портов в "count" и очередь на реинициализацию
void setLoopbackPortsCount(int count); void setLoopbackPortsCount(int count);
//! Returns loopback ports count //! \~english Returns loopback ports count
//! \~russian Возвращает количество loopback портов
int loopbackPortsCount() const { return lo_pcnt; } int loopbackPortsCount() const { return lo_pcnt; }
//! If not send_only starts all threaded reads //! \~english If not send_only starts all threaded reads
//! \~russian Если не send_only запускает все потоковые чтения
void startRead(); void startRead();
//! Stop all threaded reads //! \~english Stop all threaded reads
//! \~russian Остановить все потоковые чтения
void stopRead(); void stopRead();
//! Reinit all PIEthernets with current \a PIEthernet::allAddresses() //! \~english Reinit all PIEthernets with current \a PIEthernet::allAddresses()
//! \~russian Реинициализировать все PIEthernets с текущими \a PIEthernet::allAddresses()
void reinit(); void reinit();
//! Send packet //! \~english Send packet
//! \~russian Отправить пакет
void send(const PIByteArray & data); void send(const PIByteArray & data);
EVENT1(receiveEvent, PIByteArray, data); EVENT1(receiveEvent, PIByteArray, data);

View File

@@ -1,10 +1,13 @@
/*! \file piconnection.h //! \addtogroup IO-Utils
* \brief //! \{
* \ingroup IO-Utils //! \file piconnection.h
* \~\brief //! \brief
* \~english Complex I/O point //! \~english Complex I/O point
* \~russian Составное устройство ввода/вывода //! \~russian Составное устройство ввода/вывода
*/ //! \details
//! \~english This class provides a complex I/O point that can manage multiple devices, filters, channels, and senders.
//! \~russian Этот класс предоставляет составное устройство ввода/вывода, которое может управлять множеством устройств, фильтров, каналов и отправителей.
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Complex I/O point Complex I/O point
@@ -32,269 +35,373 @@
class PIConfig; class PIConfig;
//! \~english Complex I/O point
//! \~russian Составное устройство ввода/вывода
//! \details This class provides a complex I/O point that can manage multiple devices, filters, channels, and senders.
//! \~russian Этот класс предоставляет составное устройство ввода/вывода, которое может управлять множеством устройств, фильтров, каналов и отправителей.
class PIP_EXPORT PIConnection: public PIObject { class PIP_EXPORT PIConnection: public PIObject {
PIOBJECT_SUBCLASS(PIConnection, PIObject); PIOBJECT_SUBCLASS(PIConnection, PIObject);
public: public:
//! Constructs connection with name "name", or with default name = "connection" //! \~english Constructs connection with name "name", or with default name = "connection"
//! \~russian Создает подключение с именем "name" или с именем по умолчанию "connection"
PIConnection(const PIString & name = PIStringAscii("connection")); PIConnection(const PIString & name = PIStringAscii("connection"));
//! Constructs connection and configure it from config file "config" from section "name" //! \~english Constructs connection and configure it from config file "config" from section "name"
//! \~russian Создает подключение и настраивает его из файла конфигурации "config" из секции "name"
PIConnection(const PIString & config, const PIString & name); PIConnection(const PIString & config, const PIString & name);
//! Constructs connection and configure it from config content "string" from section "name" //! \~english Constructs connection and configure it from config content "string" from section "name"
//! \~russian Создает подключение и настраивает его из содержимого конфигурации "string" из секции "name"
PIConnection(PIString * string, const PIString & name); PIConnection(PIString * string, const PIString & name);
//! \~english Destructor
//! \~russian Деструктор
~PIConnection(); ~PIConnection();
/*! \brief Configure connection from config file "config" from section "name". Returns if configuration was successful //! \~english Configure connection from config file "config" from section "name". Returns if configuration was successful
* \details \b Warning: all devices, filters and channels removed before configure! */ //! \~russian Настраивает подключение из файла конфигурации "config" из секции "name". Возвращает успешность настройки
//! \details \b Warning: all devices, filters and channels removed before configure!
//! \~russian \b Внимание: все устройства, фильтры и каналы удаляются перед настройкой!
bool configureFromConfig(const PIString & config, const PIString & name = PIStringAscii("connection")); bool configureFromConfig(const PIString & config, const PIString & name = PIStringAscii("connection"));
/*! \brief Configure connection from config content "string" from section "name". Returns if configuration was successful //! \~english Configure connection from config content "string" from section "name". Returns if configuration was successful
* \details \b Warning: all devices, filters and channels removed before configure! */ //! \~russian Настраивает подключение из содержимого конфигурации "string" из секции "name". Возвращает успешность настройки
//! \details \b Warning: all devices, filters and channels removed before configure!
//! \~russian \b Внимание: все устройства, фильтры и каналы удаляются перед настройкой!
bool configureFromString(PIString * string, const PIString & name = PIStringAscii("connection")); bool configureFromString(PIString * string, const PIString & name = PIStringAscii("connection"));
//! Returns config file section of current connection configuration //! \~english Returns config file section of current connection configuration
//! \~russian Возвращает секцию файла конфигурации текущей конфигурации подключения
PIString makeConfig() const; PIString makeConfig() const;
/*! \brief Add device with full path "full_path", open mode "mode" to Device pool and connection //! \~english Add device with full path "full_path", open mode "mode" to Device pool and connection
* \details Returns pointer to device or null if device can not be created. If "start" is true, //! \~russian Добавляет устройство с полным путем "full_path", режимом открытия "mode" в пул устройств и подключение
* read thread is started immediately. Else, you can start read thread with functions \a startThreadedRead() //! \details Returns pointer to device or null if device can not be created. If "start" is true,
* or \a startAllThreadedReads(). By default, read thread doesn`t start */ //! \~english read thread is started immediately. Else, you can start read thread with functions \a startThreadedRead()
//! \~russian поток чтения запускается немедленно. В противном случае можно запустить поток чтения с помощью функций \a startThreadedRead()
//! \~english or \a startAllThreadedReads(). By default, read thread doesn`t start
//! \~russian или \a startAllThreadedReads(). По умолчанию поток чтения не запускается
PIIODevice * addDevice(const PIString & full_path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = false); PIIODevice * addDevice(const PIString & full_path, PIIODevice::DeviceMode mode = PIIODevice::ReadWrite, bool start = false);
//! \~english Sets the name for device "dev"
//! \~russian Устанавливает имя для устройства "dev"
void setDeviceName(PIIODevice * dev, const PIString & name); void setDeviceName(PIIODevice * dev, const PIString & name);
//! \~english Returns list of device names
//! \~russian Возвращает список имен устройств
PIStringList deviceNames(const PIIODevice * dev) const; PIStringList deviceNames(const PIIODevice * dev) const;
/*! \brief Remove device with full path "full_path" from connection //! \~english Remove device with full path "full_path" from connection
* \details Returns if device was removed. If there is no connection bounded to this device, //! \~russian Удаляет устройство с полным путем "full_path" из подключения
* it will be removed from Device pool */ //! \details Returns if device was removed. If there is no connection bounded to this device,
//! \~english it will be removed from Device pool
//! \~russian оно будет удалено из пула устройств
bool removeDevice(const PIString & full_path); bool removeDevice(const PIString & full_path);
/*! \brief Remove all device from connection //! \~english Remove all device from connection
* \details If there is no connection bounded to there devices, they removed from Device pool */ //! \~russian Удаляет все устройства из подключения
//! \details If there is no connection bounded to there devices, they removed from Device pool
//! \~russian Если к устройствам не привязано подключение, они удаляются из пула устройств
void removeAllDevices(); void removeAllDevices();
//! Returns device with full path "full_path" or null if there is no such device //! \~english Returns device with full path "full_path" or null if there is no such device
//! \~russian Возвращает устройство с полным путем "full_path" или null, если такого устройства нет
PIIODevice * deviceByFullPath(const PIString & full_path) const; PIIODevice * deviceByFullPath(const PIString & full_path) const;
//! Returns device with name "name" or null if there is no such device //! \~english Returns device with name "name" or null if there is no such device
//! \~russian Возвращает устройство с именем "name" или null, если такого устройства нет
PIIODevice * deviceByName(const PIString & name) const; PIIODevice * deviceByName(const PIString & name) const;
//! Returns all devices bounded to this connection //! \~english Returns all devices bounded to this connection
//! \~russian Возвращает все устройства, привязанные к этому подключению
PIVector<PIIODevice *> boundedDevices() const; PIVector<PIIODevice *> boundedDevices() const;
/*! \brief Add filter with name "name" to device with full path "full_path_name" or filter "full_path_name" //! \~english Add filter with name "name" to device with full path "full_path_name" or filter "full_path_name"
* \details If there is no filter with name "name", connection create new with split mode "mode" and bound //! \~russian Добавляет фильтр с именем "name" к устройству с полным путем "full_path_name" или фильтру "full_path_name"
* to it device "full_path_name" or filter "full_path_name". If filter with name "name" already exists, //! \details If there is no filter with name "name", connection create new with split mode "mode" and bound
* device "full_path_name" or filter "full_path_name" add to this filter. //! \~english to it device "full_path_name" or filter "full_path_name". If filter with name "name" already exists,
* This function returns PIPacketExtractor * assosiated with this filter //! \~english device "full_path_name" or filter "full_path_name" add to this filter.
* \n \b Attention! "mode" is altual olny if new filter was created! */ //! \~russian к нему устройство "full_path_name" или фильтр "full_path_name". Если фильтр с именем "name" уже существует,
//! \~english This function returns PIPacketExtractor * assosiated with this filter
//! \~russian устройство "full_path_name" или фильтр "full_path_name" добавляется к этому фильтру.
//! \~english This function returns PIPacketExtractor * assosiated with this filter
//! \~russian Эта функция возвращает PIPacketExtractor *, связанный с этим фильтром
//! \~\sa PIPacketExtractor
//! \details \b Attention! "mode" is altual olny if new filter was created!
//! \~russian \b Внимание! "mode" актуален только если был создан новый фильтр!
PIPacketExtractor * PIPacketExtractor *
addFilter(const PIString & name, const PIString & full_path_name, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None); addFilter(const PIString & name, const PIString & full_path_name, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None);
//! Add filter with name "name" to device "dev" //! \~english Add filter with name "name" to device "dev"
//! \~russian Добавляет фильтр с именем "name" к устройству "dev"
PIPacketExtractor * PIPacketExtractor *
addFilter(const PIString & name, const PIIODevice * dev, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None) { addFilter(const PIString & name, const PIIODevice * dev, PIPacketExtractor::SplitMode mode = PIPacketExtractor::None) {
return addFilter(name, devFPath(dev), mode); return addFilter(name, devFPath(dev), mode);
} }
//! Add filter with "filter" to device "dev" //! \~english Add filter with "filter" to device "dev"
//! \~russian Добавляет фильтр "filter" к устройству "dev"
PIPacketExtractor * addFilter(PIPacketExtractor * filter, const PIString & full_path_name); PIPacketExtractor * addFilter(PIPacketExtractor * filter, const PIString & full_path_name);
//! Add filter with "filter" to device "dev" //! \~english Add filter with "filter" to device "dev"
//! \~russian Добавляет фильтр "filter" к устройству "dev"
PIPacketExtractor * addFilter(PIPacketExtractor * filter, const PIIODevice * dev) { return addFilter(filter, devFPath(dev)); } PIPacketExtractor * addFilter(PIPacketExtractor * filter, const PIIODevice * dev) { return addFilter(filter, devFPath(dev)); }
/*! \brief Remove from filter with name "name" device with full path "full_path_name" or filter "full_path_name" //! \~english Remove from filter with name "name" device with full path "full_path_name" or filter "full_path_name"
* \details If there is no devices bounded to this filter, it will be removed. Returns if device was removed */ //! \~russian Удаляет из фильтра с именем "name" устройство с полным путем "full_path_name" или фильтр "full_path_name"
//! \details If there is no devices bounded to this filter, it will be removed. Returns if device was removed
//! \~russian Если к этому фильтру не привязано устройств, он будет удален. Возвращает успешность удаления устройства
bool removeFilter(const PIString & name, const PIString & full_path_name); bool removeFilter(const PIString & name, const PIString & full_path_name);
//! Remove from filter with name "name" device or filter "dev" //! \~english Remove from filter with name "name" device or filter "dev"
//! \~russian Удаляет из фильтра с именем "name" устройство или фильтр "dev"
bool removeFilter(const PIString & name, const PIIODevice * dev); bool removeFilter(const PIString & name, const PIIODevice * dev);
//! Remove filter with name "name". Returns if filter was removed //! \~english Remove filter with name "name". Returns if filter was removed
//! \~russian Удаляет фильтр с именем "name". Возвращает успешность удаления фильтра
bool removeFilter(const PIString & name); bool removeFilter(const PIString & name);
//! Remove all filters from connection //! \~english Remove all filters from connection
//! \~russian Удаляет все фильтры из подключения
void removeAllFilters(); void removeAllFilters();
//! Returns all filters of connection //! \~english Returns all filters of connection
//! \~russian Возвращает все фильтры подключения
PIVector<PIPacketExtractor *> filters() const; PIVector<PIPacketExtractor *> filters() const;
//! Returns all filter names of connection //! \~english Returns all filter names of connection
//! \~russian Возвращает все имена фильтров подключения
PIStringList filterNames() const; PIStringList filterNames() const;
//! Returns PIPacketExtractor * assosiated with filter "name" or null if there is no such filter //! \~english Returns PIPacketExtractor * assosiated with filter "name" or null if there is no such filter
//! \~russian Возвращает PIPacketExtractor *, связанный с фильтром "name" или null, если такого фильтра нет
PIPacketExtractor * filter(const PIString & name) const; PIPacketExtractor * filter(const PIString & name) const;
//! Returns all devices bounded to filter "name" //! \~english Returns all devices bounded to filter "name"
//! \~russian Возвращает все устройства, привязанные к фильтру "name"
PIVector<PIIODevice *> filterBoundedDevices(const PIString & name) const; PIVector<PIIODevice *> filterBoundedDevices(const PIString & name) const;
/*! \brief Add to connection channel from "name_from" to "name_to" //! \~english Add to connection channel from "name_from" to "name_to"
* \details "name_from" and "name_to" can be full pathes of devices or device names or filter names. //! \~russian Добавляет в подключение канал от "name_from" к "name_to"
* Returns \b false if there if no such device or filter, else create channel and returns \b true */ //! \details "name_from" and "name_to" can be full pathes of devices or device names or filter names.
//! \~english Returns \b false if there if no such device or filter, else create channel and returns \b true
//! \~russian Возвращает \b false, если такого устройства или фильтра нет, иначе создает канал и возвращает \b true
bool addChannel(const PIString & name_from, const PIString & name_to); bool addChannel(const PIString & name_from, const PIString & name_to);
//! Add to connection channel from "name_from" to "dev_to" //! \~english Add to connection channel from "name_from" to "dev_to"
//! \~russian Добавляет в подключение канал от "name_from" к "dev_to"
bool addChannel(const PIString & name_from, const PIIODevice * dev_to) { return addChannel(name_from, devFPath(dev_to)); } bool addChannel(const PIString & name_from, const PIIODevice * dev_to) { return addChannel(name_from, devFPath(dev_to)); }
//! Add to connection channel from "dev_from" to "name_to" //! \~english Add to connection channel from "dev_from" to "name_to"
//! \~russian Добавляет в подключение канал от "dev_from" к "name_to"
bool addChannel(const PIIODevice * dev_from, const PIString & name_to) { return addChannel(devFPath(dev_from), name_to); } bool addChannel(const PIIODevice * dev_from, const PIString & name_to) { return addChannel(devFPath(dev_from), name_to); }
//! Add to connection channel from "dev_from" to "dev_to" //! \~english Add to connection channel from "dev_from" to "dev_to"
//! \~russian Добавляет в подключение канал от "dev_from" к "dev_to"
bool addChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) { return addChannel(devFPath(dev_from), devFPath(dev_to)); } bool addChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) { return addChannel(devFPath(dev_from), devFPath(dev_to)); }
/*! \brief Remove from connection channel from "name_from" to "name_to" //! \~english Remove from connection channel from "name_from" to "name_to"
* \details "name_from" and "name_to" can be full pathes of devices or filter names. //! \~russian Удаляет из подключения канал от "name_from" к "name_to"
* Returns \b false if there if no such device or filter, else remove channel and returns \b true */ //! \details "name_from" and "name_to" can be full pathes of devices or filter names.
//! \~english Returns \b false if there if no such device or filter, else remove channel and returns \b true
//! \~russian Возвращает \b false, если такого устройства или фильтра нет, иначе удаляет канал и возвращает \b true
bool removeChannel(const PIString & name_from, const PIString & name_to); bool removeChannel(const PIString & name_from, const PIString & name_to);
//! Remove from connection channel from "name_from" to "dev_to" //! \~english Remove from connection channel from "name_from" to "dev_to"
//! \~russian Удаляет из подключения канал от "name_from" к "dev_to"
bool removeChannel(const PIString & name_from, const PIIODevice * dev_to) { return removeChannel(name_from, devFPath(dev_to)); } bool removeChannel(const PIString & name_from, const PIIODevice * dev_to) { return removeChannel(name_from, devFPath(dev_to)); }
//! Remove from connection channel from "dev_from" to "name_to" //! \~english Remove from connection channel from "dev_from" to "name_to"
//! \~russian Удаляет из подключения канал от "dev_from" к "name_to"
bool removeChannel(const PIIODevice * dev_from, const PIString & name_to) { return removeChannel(devFPath(dev_from), name_to); } bool removeChannel(const PIIODevice * dev_from, const PIString & name_to) { return removeChannel(devFPath(dev_from), name_to); }
//! Remove from connection channel from "dev_from" to "dev_to" //! \~english Remove from connection channel from "dev_from" to "dev_to"
//! \~russian Удаляет из подключения канал от "dev_from" к "dev_to"
bool removeChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) { bool removeChannel(const PIIODevice * dev_from, const PIIODevice * dev_to) {
return removeChannel(devFPath(dev_from), devFPath(dev_to)); return removeChannel(devFPath(dev_from), devFPath(dev_to));
} }
/*! \brief Remove from connection all channels from "name_from" //! \~english Remove from connection all channels from "name_from"
* \details "name_from" can be full path of device or filter name. //! \~russian Удаляет из подключения все каналы от "name_from"
* Returns \b false if there if no such device or filter, else remove channels and returns \b true */ //! \details "name_from" can be full path of device or filter name.
//! \~english Returns \b false if there if no such device or filter, else remove channels and returns \b true
//! \~russian Возвращает \b false, если такого устройства или фильтра нет, иначе удаляет каналы и возвращает \b true
bool removeChannel(const PIString & name_from); bool removeChannel(const PIString & name_from);
//! Remove from connection all channels from "dev_from" //! \~english Remove from connection all channels from "dev_from"
//! \~russian Удаляет из подключения все каналы от "dev_from"
bool removeChannel(const PIIODevice * dev_from) { return removeChannel(devFPath(dev_from)); } bool removeChannel(const PIIODevice * dev_from) { return removeChannel(devFPath(dev_from)); }
//! Remove from connection all channels //! \~english Remove from connection all channels
//! \~russian Удаляет из подключения все каналы
void removeAllChannels(); void removeAllChannels();
//! Returns all channels of this connection as full pathes or filter names pair array (from, to) //! \~english Returns all channels of this connection as full pathes or filter names pair array (from, to)
//! \~russian Возвращает все каналы этого подключения в виде массива пар полных путей или имен фильтров (от, до)
PIVector<PIPair<PIString, PIString>> channels() const; PIVector<PIPair<PIString, PIString>> channels() const;
/*! \brief Add to connection sender with name "name" device with full path "full_path" //! \~english Add to connection sender with name "name" device with full path "full_path"
* \details If there is no sender with name "name", connection create new, bound //! \~russian Добавляет в подключение отправителя с именем "name" устройство с полным путем "full_path"
* to it device "full_path_name" and start sender timer with frequency "frequency". //! \details If there is no sender with name "name", connection create new, bound
* If sender with name "name" already exists, device "full_path_name" add to this sender //! \~english to it device "full_path_name" and start sender timer with frequency "frequency".
* If "start" is true, sender is started immediately. Else, you can start sender with //! \~russian к нему устройство "full_path_name" и запускает таймер отправителя с частотой "frequency".
* functions \a startSender() //! \~english If sender with name "name" already exists, device "full_path_name" add to this sender
* \n \b Attention! "frequency" is actual olny if new sender was created! */ //! \~russian Если отправитель с именем "name" уже существует, устройство "full_path_name" добавляется к этому отправителю
//! \~english If "start" is true, sender is started immediately. Else, you can start sender with
//! \~russian Если "start" равно true, отправитель запускается немедленно. В противном случае можно запустить отправителя с помощью
//! \~english functions \a startSender()
//! \~russian функций \a startSender()
//! \~\sa startSender()
//! \details \b Attention! "frequency" is actual olny if new sender was created!
//! \~russian \b Внимание! "frequency" актуален только если был создан новый отправитель!
void addSender(const PIString & name, const PIString & full_path_name, float frequency, bool start = false); void addSender(const PIString & name, const PIString & full_path_name, float frequency, bool start = false);
//! Add to connection sender with name "name" device "dev" //! \~english Add to connection sender with name "name" device "dev"
//! \~russian Добавляет в подключение отправителя с именем "name" устройство "dev"
void addSender(const PIString & name, const PIIODevice * dev, float frequency, bool start = false) { void addSender(const PIString & name, const PIIODevice * dev, float frequency, bool start = false) {
addSender(name, devFPath(dev), frequency, start); addSender(name, devFPath(dev), frequency, start);
} }
/*! \brief Remove from sender with name "name" device with full path "full_path_name" //! \~english Remove from sender with name "name" device with full path "full_path_name"
* \details If there is no devices bounded to this sender, it will be removed. Returns if sender was removed */ //! \~russian Удаляет из отправителя с именем "name" устройство с полным путем "full_path_name"
//! \details If there is no devices bounded to this sender, it will be removed. Returns if sender was removed
//! \~russian Если к этому отправителю не привязано устройств, он будет удален. Возвращает успешность удаления отправителя
bool removeSender(const PIString & name, const PIString & full_path_name); bool removeSender(const PIString & name, const PIString & full_path_name);
//! Remove from sender with name "name" device "dev" //! \~english Remove from sender with name "name" device "dev"
//! \~russian Удаляет из отправителя с именем "name" устройство "dev"
bool removeSender(const PIString & name, const PIIODevice * dev) { return removeSender(name, devFPath(dev)); } bool removeSender(const PIString & name, const PIIODevice * dev) { return removeSender(name, devFPath(dev)); }
//! Remove sender with name "name", returns if sender was removed //! \~english Remove sender with name "name", returns if sender was removed
//! \~russian Удаляет отправителя с именем "name", возвращает успешность удаления отправителя
bool removeSender(const PIString & name); bool removeSender(const PIString & name);
//! Set sender "name" fixed send data "data", returns if sender exists //! \~english Set sender "name" fixed send data "data", returns if sender exists
//! \~russian Устанавливает фиксированные данные отправки для отправителя "name", возвращает существование отправителя
bool setSenderFixedData(const PIString & name, const PIByteArray & data); bool setSenderFixedData(const PIString & name, const PIByteArray & data);
//! Remove sender "name" fixed send data, returns if sender exists //! \~english Remove sender "name" fixed send data, returns if sender exists
//! \~russian Удаляет фиксированные данные отправки для отправителя "name", возвращает существование отправителя
bool clearSenderFixedData(const PIString & name); bool clearSenderFixedData(const PIString & name);
//! Returns sender "name" fixed send data //! \~english Returns sender "name" fixed send data
//! \~russian Возвращает фиксированные данные отправки для отправителя "name"
PIByteArray senderFixedData(const PIString & name) const; PIByteArray senderFixedData(const PIString & name) const;
//! Returns sender "name" timer frequency, -1 if there is no such sender, or 0 if sender is not started yet //! \~english Returns sender "name" timer frequency, -1 if there is no such sender, or 0 if sender is not started yet
//! \~russian Возвращает частоту таймера отправителя "name", -1 если такого отправителя нет, или 0 если отправитель еще не запущен
float senderFrequency(const PIString & name) const; float senderFrequency(const PIString & name) const;
//! Remove from connection all senders //! \~english Remove from connection all senders
//! \~russian Удаляет из подключения всех отправителей
void removeAllSenders(); void removeAllSenders();
//! Start read thread of device with full path "full_path" //! \~english Start read thread of device with full path "full_path"
//! \~russian Запускает поток чтения устройства с полным путем "full_path"
void startThreadedRead(const PIString & full_path_name); void startThreadedRead(const PIString & full_path_name);
//! Start read thread of device "dev" //! \~english Start read thread of device "dev"
//! \~russian Запускает поток чтения устройства "dev"
void startThreadedRead(const PIIODevice * dev) { startThreadedRead(devFPath(dev)); } void startThreadedRead(const PIIODevice * dev) { startThreadedRead(devFPath(dev)); }
//! Start read threads of all Device pool device //! \~english Start read threads of all Device pool device
//! \~russian Запускает потоки чтения всех устройств пула устройств
void startAllThreadedReads(); void startAllThreadedReads();
//! Start sender "name" timer //! \~english Start sender "name" timer
//! \~russian Запускает таймер отправителя "name"
void startSender(const PIString & name); void startSender(const PIString & name);
//! Start all senders timers //! \~english Start all senders timers
//! \~russian Запускает все таймеры отправителей
void startAllSenders(); void startAllSenders();
//! Start all read threads and senders //! \~english Start all read threads and senders
//! \~russian Запускает все потоки чтения и отправителей
void start() { void start() {
startAllThreadedReads(); startAllThreadedReads();
startAllSenders(); startAllSenders();
} }
//! Stop read thread of device with full path "full_path" //! \~english Stop read thread of device with full path "full_path"
//! \~russian Останавливает поток чтения устройства с полным путем "full_path"
void stopThreadedRead(const PIString & full_path_name); void stopThreadedRead(const PIString & full_path_name);
//! Stop read thread of device "dev" //! \~english Stop read thread of device "dev"
//! \~russian Останавливает поток чтения устройства "dev"
void stopThreadedRead(const PIIODevice * dev) { stopThreadedRead(devFPath(dev)); } void stopThreadedRead(const PIIODevice * dev) { stopThreadedRead(devFPath(dev)); }
//! Stop read threads of all Device pool device //! \~english Stop read threads of all Device pool device
//! \~russian Останавливает потоки чтения всех устройств пула устройств
void stopAllThreadedReads(); void stopAllThreadedReads();
//! Stop sender "name" timer //! \~english Stop sender "name" timer
//! \~russian Останавливает таймер отправителя "name"
void stopSender(const PIString & name); void stopSender(const PIString & name);
//! Stop all senders timers //! \~english Stop all senders timers
//! \~russian Останавливает все таймеры отправителей
void stopAllSenders(); void stopAllSenders();
//! Stop all read threads and senders //! \~english Stop all read threads and senders
//! \~russian Останавливает все потоки чтения и отправителей
void stop() { void stop() {
stopAllThreadedReads(); stopAllThreadedReads();
stopAllSenders(); stopAllSenders();
} }
//! Stop connection and remove all devices //! \~english Stop connection and remove all devices
//! \~russian Останавливает подключение и удаляет все устройства
void destroy() { void destroy() {
stop(); stop();
removeAllDevices(); removeAllDevices();
} }
//! Returns if there are no devices in this connection //! \~english Returns if there are no devices in this connection
//! \~russian Возвращает, если в этом подключении нет устройств
bool isEmpty() const { return device_modes.isEmpty(); } bool isEmpty() const { return device_modes.isEmpty(); }
//! Returns PIDiagnostics * assosiated with device with full path "full_path_name", name "full_path_name" or filter "full_path_name" //! \~english Returns PIDiagnostics * assosiated with device with full path "full_path_name", name "full_path_name" or filter "full_path_name"
//! \~russian Возвращает PIDiagnostics *, связанный с устройством с полным путем "full_path_name", именем "full_path_name" или фильтром "full_path_name"
PIDiagnostics * diagnostic(const PIString & full_path_name) const; PIDiagnostics * diagnostic(const PIString & full_path_name) const;
//! Returns PIDiagnostics * assosiated with device or filter "dev" //! \~english Returns PIDiagnostics * assosiated with device or filter "dev"
//! \~russian Возвращает PIDiagnostics *, связанный с устройством или фильтром "dev"
PIDiagnostics * diagnostic(const PIIODevice * dev) const { return diags_.value(const_cast<PIIODevice *>(dev), 0); } PIDiagnostics * diagnostic(const PIIODevice * dev) const { return diags_.value(const_cast<PIIODevice *>(dev), 0); }
//! Write data "data" to device with full path "full_path" and returns result of \a write() function of device //! \~english Write data "data" to device with full path "full_path" and returns result of \a write() function of device
//! \~russian Записывает данные "data" в устройство с полным путем "full_path" и возвращает результат функции \a write() устройства
int writeByFullPath(const PIString & full_path, const PIByteArray & data); int writeByFullPath(const PIString & full_path, const PIByteArray & data);
//! Write data "data" to device with name "name" and returns result of \a write() function of device //! \~english Write data "data" to device with name "name" and returns result of \a write() function of device
//! \~russian Записывает данные "data" в устройство с именем "name" и возвращает результат функции \a write() устройства
int writeByName(const PIString & name, const PIByteArray & data); int writeByName(const PIString & name, const PIByteArray & data);
//! Write data "data" to device "dev" and returns result of \a write() function of device //! \~english Write data "data" to device "dev" and returns result of \a write() function of device
//! \~russian Записывает данные "data" в устройство "dev" и возвращает результат функции \a write() устройства
int write(PIIODevice * dev, const PIByteArray & data); int write(PIIODevice * dev, const PIByteArray & data);
//! Returns all connections in application //! \~english Returns all connections in application
//! \~russian Возвращает все подключения в приложении
static PIVector<PIConnection *> allConnections(); static PIVector<PIConnection *> allConnections();
//! Returns all devices in Device pool //! \~english Returns all devices in Device pool
//! \~russian Возвращает все устройства в пуле устройств
static PIVector<PIIODevice *> allDevices(); static PIVector<PIIODevice *> allDevices();
//! Set Device pool fake mode to \"yes\" and returns previous mode //! \~english Set Device pool fake mode to \"yes\" and returns previous mode
//! \~russian Устанавливает фальшивый режим пула устройств в \"yes\" и возвращает предыдущий режим
static bool setFakeMode(bool yes); static bool setFakeMode(bool yes);
//! Returns if Device pool works in fake mode //! \~english Returns if Device pool works in fake mode
//! \~russian Возвращает, работает ли пул устройств в фальшивом режиме
static bool isFakeMode(); static bool isFakeMode();
//! \~english Device pool class
//! \~russian Класс пула устройств
class PIP_EXPORT DevicePool: public PIThread { class PIP_EXPORT DevicePool: public PIThread {
PIOBJECT_SUBCLASS(DevicePool, PIThread); PIOBJECT_SUBCLASS(DevicePool, PIThread);
friend void __DevicePool_threadReadDP(void * ddp); friend void __DevicePool_threadReadDP(void * ddp);
@@ -314,54 +421,95 @@ public:
void unboundConnection(PIConnection * parent); void unboundConnection(PIConnection * parent);
PIIODevice * device(const PIString & fp) const; PIIODevice * device(const PIString & fp) const;
DeviceData * deviceData(PIIODevice * d) const; DeviceData * deviceData(PIIODevice * d) const;
//! \~english Returns list of bounded connections
//! \~russian Возвращает список привязанных подключений
PIVector<PIConnection *> boundedConnections() const; PIVector<PIConnection *> boundedConnections() const;
//! \~english Returns list of bounded devices
//! \~russian Возвращает список привязанных устройств
PIVector<PIIODevice *> boundedDevices() const; PIVector<PIIODevice *> boundedDevices() const;
//! \~english Returns list of bounded devices for specific parent connection
//! \~russian Возвращает список привязанных устройств для конкретного родительского подключения
PIVector<PIIODevice *> boundedDevices(const PIConnection * parent) const; PIVector<PIIODevice *> boundedDevices(const PIConnection * parent) const;
protected: protected:
//! \~english Device data structure
//! \~russian Структура данных устройства
struct PIP_EXPORT DeviceData { struct PIP_EXPORT DeviceData {
//! \~english Constructor
//! \~russian Конструктор
DeviceData(): dev(0), rthread(0), started(false) {} DeviceData(): dev(0), rthread(0), started(false) {}
//! \~english Destructor
//! \~russian Деструктор
~DeviceData(); ~DeviceData();
//! \~english Device pointer
//! \~russian Указатель на устройство
PIIODevice * dev; PIIODevice * dev;
//! \~english Read thread pointer
//! \~russian Указатель на поток чтения
PIThread * rthread; PIThread * rthread;
//! \~english Started flag
//! \~russian Флаг запуска
bool started; bool started;
//! \~english List of listeners
//! \~russian Список слушателей
PIVector<PIConnection *> listeners; PIVector<PIConnection *> listeners;
}; };
//! \~english Thread execution function
//! \~russian Функция выполнения потока
void run() override; void run() override;
//! \~english Called when device is read
//! \~russian Вызывается при чтении устройства
void deviceReaded(DeviceData * dd, const PIByteArray & data); void deviceReaded(DeviceData * dd, const PIByteArray & data);
//! \~english Map of devices
//! \~russian Карта устройств
PIMap<PIString, DeviceData *> devices; PIMap<PIString, DeviceData *> devices;
//! \~english Fake mode flag
//! \~russian Флаг фальшивого режима
bool fake; bool fake;
}; };
//! \~english Data received event
//! \~russian Событие получения данных
EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data); EVENT2(dataReceivedEvent, const PIString &, from, const PIByteArray &, data);
//! \~english Packet received event
//! \~russian Событие получения пакета
EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data); EVENT2(packetReceivedEvent, const PIString &, from, const PIByteArray &, data);
//! \~english Quality changed event
//! \~russian Событие изменения качества
EVENT3(qualityChanged, const PIIODevice *, dev, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality); EVENT3(qualityChanged, const PIIODevice *, dev, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
//! \events //! \~english Events
//! \~russian События
//! \{ //! \{
//! \fn void dataReceivedEvent(const PIString & from, const PIByteArray & data) //! \fn void dataReceivedEvent(const PIString & from, const PIByteArray & data)
//! \brief Raise on data received from device with full path "from" //! \~english Raise on data received from device with full path "from"
//! \~russian Возникает при получении данных от устройства с полным путем "from"
//! \fn void packetReceivedEvent(const PIString & from, const PIByteArray & data) //! \fn void packetReceivedEvent(const PIString & from, const PIByteArray & data)
//! \brief Raise on packet received from filter with name "from" //! \~english Raise on packet received from filter with name "from"
//! \~russian Возникает при получении пакета от фильтра с именем "from"
//! \fn void qualityChanged(const PIIODevice * device, PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) //! \fn void qualityChanged(const PIIODevice * device, PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality)
//! \brief Raise on diagnostic quality of device "device" changed from "old_quality" to "new_quality" //! \~english Raise on diagnostic quality of device "device" changed from "old_quality" to "new_quality"
//! \~russian Возникает при изменении диагностического качества устройства "device" с "old_quality" на "new_quality"
//! \} //! \}
protected: protected:
//! Executes on data received from device with full path "from" //! \~english Executes on data received from device with full path "from"
//! \~russian Выполняется при получении данных от устройства с полным путем "from"
virtual void dataReceived(const PIString & from, const PIByteArray & data) {} virtual void dataReceived(const PIString & from, const PIByteArray & data) {}
//! Executes on packet received from filter with name "from" //! \~english Executes on packet received from filter with name "from"
//! \~russian Выполняется при получении пакета от фильтра с именем "from"
virtual void packetReceived(const PIString & from, const PIByteArray & data) {} virtual void packetReceived(const PIString & from, const PIByteArray & data) {}
//! You should returns data for sender "sender_name" //! \~english You should returns data for sender "sender_name"
//! \~russian Вы должны возвращать данные для отправителя "sender_name"
virtual PIByteArray senderData(const PIString & sender_name); virtual PIByteArray senderData(const PIString & sender_name);
private: private:

View File

@@ -29,14 +29,26 @@
#include "pibasetransfer.h" #include "pibasetransfer.h"
//! \~english Class for send and receive PIByteArray via \a PIBaseTransfer
//! \~russian Класс для отправки и приема PIByteArray с помощью \a PIBaseTransfer
class PIP_EXPORT PIDataTransfer: public PIBaseTransfer { class PIP_EXPORT PIDataTransfer: public PIBaseTransfer {
PIOBJECT_SUBCLASS(PIDataTransfer, PIBaseTransfer); PIOBJECT_SUBCLASS(PIDataTransfer, PIBaseTransfer);
public: public:
//! \~english Constructs empty data transfer
//! \~russian Создает пустой transfer данных
PIDataTransfer() { ; } PIDataTransfer() { ; }
//! \~english Destructor
//! \~russian Деструктор
~PIDataTransfer() { ; } ~PIDataTransfer() { ; }
//! \~english Send data
//! \~russian Отправить данные
bool send(const PIByteArray & ba); bool send(const PIByteArray & ba);
//! \~english Get received data
//! \~russian Получить принятые данные
const PIByteArray & data() { return data_; } const PIByteArray & data() { return data_; }
private: private:

View File

@@ -1,9 +1,13 @@
/*! \file pidiagnostics.h //! \addtogroup IO
* \ingroup IO //! \{
* \~\brief //! \file pidiagnostics.h
* \~english Connection quality diagnostics //! \brief
* \~russian Диагностика качества связи //! \~english Connection quality diagnostics
*/ //! \~russian Диагностика качества связи
//! \details
//! \~english This class provides connection quality diagnostics based on packet reception statistics
//! \~russian Класс обеспечивает диагностику качества связи на основе статистики приема пакетов
//! \~\}
/* /*
PIP - Platform Independent Primitives PIP - Platform Independent Primitives
Speed and quality in/out diagnostics Speed and quality in/out diagnostics
@@ -30,6 +34,8 @@
#include "pitimer.h" #include "pitimer.h"
//! \~english Connection quality diagnostics class based on packet statistics
//! \~russian Класс диагностики качества связи на основе статистики пакетов
class PIP_EXPORT PIDiagnostics: public PITimer { class PIP_EXPORT PIDiagnostics: public PITimer {
PIOBJECT_SUBCLASS(PIDiagnostics, PITimer); PIOBJECT_SUBCLASS(PIDiagnostics, PITimer);
friend class PIConnection; friend class PIConnection;
@@ -37,118 +43,215 @@ class PIP_EXPORT PIDiagnostics: public PITimer {
public: public:
NO_COPY_CLASS(PIDiagnostics); NO_COPY_CLASS(PIDiagnostics);
//! Constructs an empty diagnostics and if "start_" start it //! \~english Constructs an empty diagnostics and if "start_" start it
//! \~russian Создает пустую диагностику и запускает её, если "start_" установлено
PIDiagnostics(bool start_ = true); PIDiagnostics(bool start_ = true);
//! \~english Virtual destructor
//! \~russian Виртуальный деструктор
virtual ~PIDiagnostics(); virtual ~PIDiagnostics();
//! Connection quality //! \~english Connection quality enumeration
//! \~russian Перечисление качества связи
enum Quality { enum Quality {
Unknown /** Unknown, no one packet received yet */ = 1, //! \~english Unknown, no one packet received yet
Failure /** No connection, no one correct packet received for last period */ = 2, //! \~russian Неизвестно, еще не получен ни один пакет
Bad /** Bad connection, correct packets received <= 20% */ = 3, Unknown = 1,
Average /** Average connection, correct packets received > 20% and <= 80% */ = 4, //! \~english No connection, no one correct packet received for last period
Good /** Good connection, correct packets received > 80% */ = 5 //! \~russian Нет соединения, за последний период не получено ни одного корректного пакета
Failure = 2,
//! \~english Bad connection, correct packets received <= 20%
//! \~russian Плохое соединение, корректных пакетов получено <= 20%
Bad = 3,
//! \~english Average connection, correct packets received > 20% and <= 80%
//! \~russian Среднее соединение, корректных пакетов получено > 20% и <= 80%
Average = 4,
//! \~english Good connection, correct packets received > 80%
//! \~russian Хорошее соединение, корректных пакетов получено > 80%
Good = 5
}; };
//! Information about current diagnostics state //! \~english Information about current diagnostics state
//! \~russian Информация о текущем состоянии диагностики
struct PIP_EXPORT State { struct PIP_EXPORT State {
//! \~english Default constructor
//! \~russian Конструктор по умолчанию
State(); State();
//! \~english Immediate frequency in Hz
//! \~russian Мгновенная частота в Гц
float immediate_freq = 0.f; float immediate_freq = 0.f;
//! \~english Integral frequency in Hz
//! \~russian Интегральная частота в Гц
float integral_freq = 0.f; float integral_freq = 0.f;
//! \~english Received packets per second
//! \~russian Принятых пакетов в секунду
ullong received_packets_per_sec = 0ull; ullong received_packets_per_sec = 0ull;
//! \~english Total received packets count
//! \~russian Общее количество принятых пакетов
ullong received_packets = 0ull; ullong received_packets = 0ull;
//! \~english Total received wrong packets count
//! \~russian Общее количество неправильно принятых пакетов
ullong received_packets_wrong = 0ull; ullong received_packets_wrong = 0ull;
//! \~english Received bytes per second
//! \~russian Принятых байт в секунду
ullong received_bytes_per_sec = 0ull; ullong received_bytes_per_sec = 0ull;
//! \~english Total received bytes count
//! \~russian Общее количество принятых байт
ullong received_bytes = 0ull; ullong received_bytes = 0ull;
//! \~english Total received wrong bytes count
//! \~russian Общее количество неправильно принятых байт
ullong received_bytes_wrong = 0ull; ullong received_bytes_wrong = 0ull;
//! \~english Sended packets per second
//! \~russian Отправленных пакетов в секунду
ullong sended_packets_per_sec = 0ull; ullong sended_packets_per_sec = 0ull;
//! \~english Total sended packets count
//! \~russian Общее количество отправленных пакетов
ullong sended_packets = 0ull; ullong sended_packets = 0ull;
//! \~english Sended bytes per second
//! \~russian Отправленных байт в секунду
ullong sended_bytes_per_sec = 0ull; ullong sended_bytes_per_sec = 0ull;
//! \~english Total sended bytes count
//! \~russian Общее количество отправленных байт
ullong sended_bytes = 0ull; ullong sended_bytes = 0ull;
//! \~english Receive speed string in format "n {B|kB|MB|GB|TB}/s"
//! \~russian Строка скорости приема в формате "n {B|kB|MB|GB|TB}/s"
PIString receive_speed; PIString receive_speed;
//! \~english Send speed string in format "n {B|kB|MB|GB|TB}/s"
//! \~russian Строка скорости отправки в формате "n {B|kB|MB|GB|TB}/s"
PIString send_speed; PIString send_speed;
//! \~english Current connection quality
//! \~russian Текущее качество соединения
PIDiagnostics::Quality quality = PIDiagnostics::Unknown; PIDiagnostics::Quality quality = PIDiagnostics::Unknown;
}; };
//! Returns current state //! \~english Returns current diagnostics state
//! \~russian Возвращает текущее состояние диагностики
PIDiagnostics::State state() const; PIDiagnostics::State state() const;
//! Returns period of full disconnect in seconds and period of averaging frequency //! \~english Returns period of full disconnect in seconds and period of averaging frequency
//! \~russian Возвращает период полного отключения в секундах и период усреднения частоты
PISystemTime disconnectTimeout() const { return disconn_; } PISystemTime disconnectTimeout() const { return disconn_; }
//! Returns period of full disconnect in seconds and period of averaging frequency //! \~english Set disconnect timeout (deprecated, use PISystemTime version)
//! \~russian Установить таймаут отключения (устаревший, используйте версию с PISystemTime)
void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") { void setDisconnectTimeout(float s) DEPRECATEDM("use setDisconnectTimeout(PISystemTime)") {
setDisconnectTimeout(PISystemTime::fromSeconds(s)); setDisconnectTimeout(PISystemTime::fromSeconds(s));
} }
//! Returns period of full disconnect and period of averaging frequency //! \~english Set disconnect timeout
//! \~russian Установить таймаут отключения
void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); } void setDisconnectTimeout(PISystemTime tm) { setProperty("disconnectTimeout", tm); }
//! Returns connection quality //! \~english Returns connection quality
//! \~russian Возвращает качество соединения
PIDiagnostics::Quality quality() const; PIDiagnostics::Quality quality() const;
//! Returns receive speed in format "n {B|kB|MB|GB|TB}/s" //! \~english Returns receive speed in format "n {B|kB|MB|GB|TB}/s"
//! \~russian Возвращает скорость приема в формате "n {B|kB|MB|GB|TB}/s"
PIString receiveSpeed() const; PIString receiveSpeed() const;
//! Returns send speed in format "n {B|kB|MB|GB|TB}/s" //! \~english Returns send speed in format "n {B|kB|MB|GB|TB}/s"
//! \~russian Возвращает скорость отправки в формате "n {B|kB|MB|GB|TB}/s"
PIString sendSpeed() const; PIString sendSpeed() const;
EVENT_HANDLER0(void, start);
EVENT_HANDLER1(void, start, PISystemTime, interval);
EVENT_HANDLER0(void, reset);
EVENT_HANDLER1(void, received, int, size) { received(size, true); }
EVENT_HANDLER2(void, received, int, size, bool, correct);
EVENT_HANDLER1(void, sended, int, size);
EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
//! \handlers //! \handlers
//! \{ //! \{
//! \fn void start(double msecs = 1000.) //! \fn void start()
//! \brief Start diagnostics evaluations with period "msecs" milliseconds //! \~english Start diagnostics with default period (1000ms)
//! \~russian Запустить диагностику с периодом по умолчанию (1000мс)
EVENT_HANDLER0(void, start);
//! \fn void start(PISystemTime interval)
//! \~english Start diagnostics with specified period
//! \~russian Запустить диагностику с указанным периодом
EVENT_HANDLER1(void, start, PISystemTime, interval);
//! \fn void reset() //! \fn void reset()
//! \brief Reset diagnostics counters //! \~english Reset diagnostics counters
//! \~russian Сбросить счетчики диагностики
EVENT_HANDLER0(void, reset);
//! \fn void received(int size, bool correct = true) //! \fn void received(int size)
//! \brief Notify diagnostics about "correct" corected received packet //! \~english Notify diagnostics about received packet
//! \~russian Уведомить диагностику о принятом пакете
EVENT_HANDLER1(void, received, int, size) { received(size, true); }
//! \fn void received(int size, bool correct)
//! \~english Notify diagnostics about received packet with correctness flag
//! \~russian Уведомить диагностику о принятом пакете с флагом корректности
EVENT_HANDLER2(void, received, int, size, bool, correct);
//! \fn void sended(int size) //! \fn void sended(int size)
//! \brief Notify diagnostics about sended packet //! \~english Notify diagnostics about sended packet
//! \~russian Уведомить диагностику об отправленном пакете
EVENT_HANDLER1(void, sended, int, size);
//! \} //! \}
//! \events //! \events
//! \{ //! \{
//! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality) //! \fn void qualityChanged(PIDiagnostics::Quality new_quality, PIDiagnostics::Quality old_quality)
//! \brief Raise on change receive quality from "old_quality" to "new_quality" //! \~english Emitted when receive quality changes
//! \~russian Генерируется при изменении качества приема
EVENT2(qualityChanged, PIDiagnostics::Quality, new_quality, PIDiagnostics::Quality, old_quality);
//! \} //! \}
private: private:
//! \~english Internal structure for packet statistics history
//! \~russian Внутренняя структура для истории статистики пакетов
struct PIP_EXPORT Entry { struct PIP_EXPORT Entry {
//! \~english Number of correct bytes
//! \~russian Количество корректных байт
ullong bytes_ok = 0; ullong bytes_ok = 0;
//! \~english Number of wrong bytes
//! \~russian Количество неправильных байт
ullong bytes_fail = 0; ullong bytes_fail = 0;
//! \~english Count of correct packets
//! \~russian Количество корректных пакетов
uint cnt_ok = 0; uint cnt_ok = 0;
//! \~english Count of wrong packets
//! \~russian Количество неправильных пакетов
uint cnt_fail = 0; uint cnt_fail = 0;
//! \~english Flag indicating if entry is empty
//! \~russian Флаг, указывающий, что запись пустая
bool empty = true; bool empty = true;
}; };
//! \~english Equality operator for Entry structure
//! \~russian Оператор равенства для структуры Entry
friend bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator==(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
//! \~english Inequality operator for Entry structure
//! \~russian Оператор неравенства для структуры Entry
friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator!=(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
//! \~english Less-than operator for Entry structure
//! \~russian Оператор меньше для структуры Entry
friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s); friend bool operator<(const PIDiagnostics::Entry & f, const PIDiagnostics::Entry & s);
//! \~english Timer tick handler
//! \~russian Обработчик тика таймера
void tick(int) override; void tick(int) override;
//! \~english Calculate history statistics
//! \~russian Вычислить статистику истории
Entry calcHistory(PIQueue<Entry> & hist, int & cnt); Entry calcHistory(PIQueue<Entry> & hist, int & cnt);
//! \~english Property changed handler
//! \~russian Обработчик изменения свойства
void propertyChanged(const char *) override; void propertyChanged(const char *) override;
//! \~english Change disconnect timeout
//! \~russian Изменить таймаут отключения
void changeDisconnectTimeout(PISystemTime disct); void changeDisconnectTimeout(PISystemTime disct);
//! \~english History queue for received packets
//! \~russian Очередь истории для принятых пакетов
PIQueue<Entry> history_rec, history_send; PIQueue<Entry> history_rec, history_send;
//! \~english Disconnect timeout
//! \~russian Таймаут отключения
PISystemTime disconn_; PISystemTime disconn_;
//! \~english Current state
//! \~russian Текущее состояние
State cur_state; State cur_state;
//! \~english Mutex for state access protection
//! \~russian Мьютекс для защиты доступа к состоянию
mutable PIMutex mutex_state; mutable PIMutex mutex_state;
}; };

View File

@@ -29,45 +29,61 @@
#include "pibytearray.h" #include "pibytearray.h"
#include "pip_io_utils_export.h" #include "pip_io_utils_export.h"
//! \~english Base class for ethernet utils
//! \~russian Базовый класс для утилит ethernet
class PIP_IO_UTILS_EXPORT PIEthUtilBase { class PIP_IO_UTILS_EXPORT PIEthUtilBase {
public: public:
//! \~english Constructs PIEthUtilBase
//! \~russian Создает PIEthUtilBase
PIEthUtilBase(); PIEthUtilBase();
//! \~english Destructor
//! \~russian Деструктор
~PIEthUtilBase(); ~PIEthUtilBase();
//! Set crypt layer enabled //! \~english Set crypt layer enabled
//! \~russian Включить слой шифрования
void setCryptEnabled(bool on); void setCryptEnabled(bool on);
//! Enable crypt layer //! \~english Enable crypt layer
//! \~russian Включить слой шифрования
void cryptEnable(); void cryptEnable();
//! Disable crypt layer //! \~english Disable crypt layer
//! \~russian Выключить слой шифрования
void cryptDisable(); void cryptDisable();
//! Returns if crypt layer enabled //! \~english Returns if crypt layer enabled
//! \~russian Возвращает, включен ли слой шифрования
bool isCryptEnabled() const; bool isCryptEnabled() const;
//! Set crypt layer key to \"k\" //! \~english Set crypt layer key to "k"
//! \~russian Установить ключ шифрования в "k"
void setCryptKey(const PIByteArray & k); void setCryptKey(const PIByteArray & k);
//! Generate crypt layer key by \a PICrypt::hash and //! \~english Generate crypt layer key by \a PICrypt::hash and set crypt layer enabled
//! set crypt layer enabled //! \~russian Сгенерировать ключ шифрования с помощью \a PICrypt::hash и включить шифрование
void createCryptKey(const PIString & k); void createCryptKey(const PIString & k);
//! Returns crypt layer key //! \~english Returns crypt layer key
//! \~russian Возвращает ключ шифрования
PIByteArray cryptKey() const; PIByteArray cryptKey() const;
//! \brief Returns addition size for crypted data. //! \~english Returns addition size for crypted data
//! \~russian Возвращает дополнительный размер для зашифрованных данных
static size_t cryptSizeAddition(); static size_t cryptSizeAddition();
protected: protected:
/*! \brief Returns encrypted data if layer enabled, //! \~english Returns encrypted data if layer enabled, otherwise returns unchanged "data"
* otherwise returns unchanged \"data\" */ //! \~russian Возвращает зашифрованные данные, если слой включен, иначе возвращает неизмененные "data"
PIByteArray cryptData(const PIByteArray & data); PIByteArray cryptData(const PIByteArray & data);
/*! \brief Returns decrypted data if layer enabled, //! \~english Returns decrypted data if layer enabled, otherwise returns unchanged "data". If decryption was unsuccessful returns empty
* otherwise returns unchanged \"data\". If decryption //! %PIByteArray
* was unsuccessfull returns empty %PIByteArray. */ //! \~russian Возвращает расшифрованные данные, если слой включен, иначе возвращает неизмененные "data". Если расшифровка неуспешна,
//! возвращает пустой %PIByteArray
PIByteArray decryptData(const PIByteArray & data); PIByteArray decryptData(const PIByteArray & data);
private: private:

View File

@@ -31,25 +31,40 @@
#define __PIFILETRANSFER_VERSION 2 #define __PIFILETRANSFER_VERSION 2
//! \~english Class for send and receive files and directories via \a PIBaseTransfer
//! \~russian Класс для отправки и приема файлов и папок с помощью \a PIBaseTransfer
class PIP_EXPORT PIFileTransfer: public PIBaseTransfer { class PIP_EXPORT PIFileTransfer: public PIBaseTransfer {
PIOBJECT_SUBCLASS(PIFileTransfer, PIBaseTransfer); PIOBJECT_SUBCLASS(PIFileTransfer, PIBaseTransfer);
public: public:
//! \~english Constructs empty file transfer
//! \~russian Создает пустой transfer файлов
PIFileTransfer(); PIFileTransfer();
//! \~english Destructor
//! \~russian Деструктор
~PIFileTransfer(); ~PIFileTransfer();
//! \~english Step type for file transfer
//! \~russian Тип шага для передачи файлов
enum StepType { enum StepType {
pft_None, pft_None,
pft_Description, pft_Description,
pft_Data pft_Data
}; };
//! \~english File information structure
//! \~russian Структура информации о файле
struct PIP_EXPORT PFTFileInfo: public PIFile::FileInfo { struct PIP_EXPORT PFTFileInfo: public PIFile::FileInfo {
//! \~english Constructor
//! \~russian Конструктор
PFTFileInfo(const PIFile::FileInfo & fi = PIFile::FileInfo()): PIFile::FileInfo(fi) {} PFTFileInfo(const PIFile::FileInfo & fi = PIFile::FileInfo()): PIFile::FileInfo(fi) {}
PIString dest_path; PIString dest_path;
}; };
#pragma pack(push, 1) #pragma pack(push, 1)
//! \~english File transfer header structure
//! \~russian Структура заголовка передачи файлов
struct PIP_EXPORT PFTHeader { struct PIP_EXPORT PFTHeader {
union { union {
struct { struct {
@@ -60,6 +75,8 @@ public:
}; };
int step; // PacketType int step; // PacketType
int session_id; int session_id;
//! \~english Check if signature is valid
//! \~russian Проверка валидности подписи
bool check_sig() { bool check_sig() {
if (sig[0] != sign[0] || sig[1] != sign[1] || sig[2] != sign[2] || version != __PIFILETRANSFER_VERSION) return false; if (sig[0] != sign[0] || sig[1] != sign[1] || sig[2] != sign[2] || version != __PIFILETRANSFER_VERSION) return false;
return true; return true;
@@ -67,23 +84,64 @@ public:
}; };
#pragma pack(pop) #pragma pack(pop)
//! \~english Send file
//! \~russian Отправить файл
bool send(const PIFile & file); bool send(const PIFile & file);
//! \~english Send file by path
//! \~russian Отправить файл по пути
bool send(const PIString & file); bool send(const PIString & file);
//! \~english Send files list
//! \~russian Отправить список файлов
bool send(const PIStringList & files); bool send(const PIStringList & files);
//! \~english Send file info
//! \~russian Отправить информацию о файле
bool send(PIFile::FileInfo entry) { return send(PIVector<PIFile::FileInfo>() << entry); } bool send(PIFile::FileInfo entry) { return send(PIVector<PIFile::FileInfo>() << entry); }
//! \~english Send file info vector
//! \~russian Отправить вектор информации о файлах
bool send(PIVector<PIFile::FileInfo> entries); bool send(PIVector<PIFile::FileInfo> entries);
//! \~english Set directory
//! \~russian Установить директорию
void setDirectory(const PIDir & d) { dir = d; } void setDirectory(const PIDir & d) { dir = d; }
//! \~english Set directory by path
//! \~russian Установить директорию по пути
void setDirectory(const PIString & path) { dir.setDir(path); } void setDirectory(const PIString & path) { dir.setDir(path); }
//! \~english Get directory
//! \~russian Получить директорию
PIDir directory() const { return dir; } PIDir directory() const { return dir; }
//! \~english Check if transfer is started
//! \~russian Проверить, начата ли передача
bool isStarted() const { return started_; } bool isStarted() const { return started_; }
//! \~english Get current file name
//! \~russian Получить имя текущего файла
PIString curFile() const; PIString curFile() const;
//! \~english Get total bytes of current file
//! \~russian Получить общее количество байт текущего файла
llong bytesFileAll() const { return bytes_file_all; } llong bytesFileAll() const { return bytes_file_all; }
//! \~english Get current bytes of current file
//! \~russian Получить текущие байты текущего файла
llong bytesFileCur() const { return bytes_file_cur; } llong bytesFileCur() const { return bytes_file_cur; }
//! \~english Get pointer to current file name
//! \~russian Получить указатель на имя текущего файла
const PIString * curFile_ptr() const { return &cur_file_string; } const PIString * curFile_ptr() const { return &cur_file_string; }
//! \~english Get pointer to total bytes of current file
//! \~russian Получить указатель на общее количество байт текущего файла
const llong * bytesFileAll_ptr() const { return &bytes_file_all; } const llong * bytesFileAll_ptr() const { return &bytes_file_all; }
//! \~english Get pointer to current bytes of current file
//! \~russian Получить указатель на текущие байты текущего файла
const llong * bytesFileCur_ptr() const { return &bytes_file_cur; } const llong * bytesFileCur_ptr() const { return &bytes_file_cur; }
EVENT(receiveFilesStarted); EVENT(receiveFilesStarted);

Some files were not shown because too many files have changed in this diff Show More