migration
5
semester-4/ОС/lb-4/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
Викладач: Мельникова Р. В.
|
||||
Оцінка: 92
|
||||
|
||||
Додатково:
|
||||
Виконував в команді.
|
BIN
semester-4/ОС/lb-4/img/Directory.h.png
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
semester-4/ОС/lb-4/img/Directory_GetDirectories.png
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
semester-4/ОС/lb-4/img/Directory_GetFiles.png
Normal file
After Width: | Height: | Size: 148 KiB |
BIN
semester-4/ОС/lb-4/img/DriveInfo.h.png
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
semester-4/ОС/lb-4/img/DriveInfo_GetDrives.png
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
semester-4/ОС/lb-4/img/File.h.png
Normal file
After Width: | Height: | Size: 243 KiB |
BIN
semester-4/ОС/lb-4/img/FileStream.h.png
Normal file
After Width: | Height: | Size: 232 KiB |
BIN
semester-4/ОС/lb-4/img/File_GetSize.png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
semester-4/ОС/lb-4/img/File_SetAttributes.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
semester-4/ОС/lb-4/img/cpp_1.png
Normal file
After Width: | Height: | Size: 238 KiB |
BIN
semester-4/ОС/lb-4/img/cpp_2.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
semester-4/ОС/lb-4/img/cpp_3.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
semester-4/ОС/lb-4/img/cpp_4.png
Normal file
After Width: | Height: | Size: 155 KiB |
BIN
semester-4/ОС/lb-4/img/cpp_5.png
Normal file
After Width: | Height: | Size: 124 KiB |
BIN
semester-4/ОС/lb-4/img/cpp_6.png
Normal file
After Width: | Height: | Size: 94 KiB |
BIN
semester-4/ОС/lb-4/img/cpp_7.png
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
semester-4/ОС/lb-4/img/cpp_8.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
semester-4/ОС/lb-4/img/cs_1.png
Normal file
After Width: | Height: | Size: 148 KiB |
BIN
semester-4/ОС/lb-4/img/cs_2.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
semester-4/ОС/lb-4/img/cs_3.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
semester-4/ОС/lb-4/img/cs_4.png
Normal file
After Width: | Height: | Size: 93 KiB |
BIN
semester-4/ОС/lb-4/img/cs_5.png
Normal file
After Width: | Height: | Size: 95 KiB |
BIN
semester-4/ОС/lb-4/img/cs_6.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
semester-4/ОС/lb-4/img/cs_7.png
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
semester-4/ОС/lb-4/img/cs_8.png
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
semester-4/ОС/lb-4/img/test.jpg
Normal file
After Width: | Height: | Size: 58 KiB |
694
semester-4/ОС/lb-4/lib.typ
Normal file
@ -0,0 +1,694 @@
|
||||
|
||||
// Academic aliases {{{1
|
||||
|
||||
/// subject abbreviations to full names
|
||||
#let subjects = (
|
||||
"БД": "Бази даних",
|
||||
"ОПНJ": "Основи програмування на Java",
|
||||
"ОС": "Операційні системи",
|
||||
"ПП": "Проектний практикум",
|
||||
"СПМ": "Скриптові мови програмування",
|
||||
"Ф": "Філософія",
|
||||
)
|
||||
|
||||
/// education program abbreviations to name & number
|
||||
#let edu_programs = (
|
||||
"ПЗПІ": (
|
||||
name: "Інженерія програмного забезпечення",
|
||||
number: 121, // TODO: ПЗПІ is "F2" now
|
||||
),
|
||||
)
|
||||
|
||||
// Template formatting functions {{{1
|
||||
|
||||
/// numberless heading
|
||||
#let nheading(title) = heading(depth: 1, numbering: none, title)
|
||||
|
||||
/// fill horizontal space with a box and not an empty space
|
||||
#let hfill(width) = box(width: width, repeat(" ")) // NOTE: This is a HAIR SPACE (U+200A), not a regular space
|
||||
|
||||
/// make underlined cell with filled value
|
||||
#let uline(align: center, content) = underline[
|
||||
#if align != left { hfill(1fr) }
|
||||
#content
|
||||
#if align != right { hfill(1fr) }
|
||||
]
|
||||
|
||||
/// bold text
|
||||
#let bold(content) = text(weight: "bold")[#content]
|
||||
|
||||
/// month name from its number
|
||||
#let month_gen(month) = (
|
||||
"січня",
|
||||
"лютого",
|
||||
"березня",
|
||||
"квітня",
|
||||
"травня",
|
||||
"червня",
|
||||
"липня",
|
||||
"серпня",
|
||||
"вересня",
|
||||
"жовтня",
|
||||
"листопада",
|
||||
"грудня",
|
||||
).at(month - 1)
|
||||
|
||||
// Helper functions {{{1
|
||||
|
||||
/// captioned image with label derived from path:
|
||||
/// - "image.png" = @image
|
||||
/// - "img/image.png" = @image
|
||||
/// - "img/foo/image.png" = @foo_image
|
||||
/// - "img/foo/foo_image.png" = @foo_image
|
||||
/// the caption will be modified based on a conditional positional value:
|
||||
/// - `none`: no change
|
||||
/// - some value: "`caption` (за даними `value`)"
|
||||
/// - no value: "`caption` (рисунок виконано самостійно)"
|
||||
/// additional named arguments will be passed to original `image` function
|
||||
#let img(path, caption, ..sink) = {
|
||||
let parts = path.split(".").first().split("/")
|
||||
|
||||
let label_string = if parts.len() <= 2 or parts.at(-1).starts-with(parts.at(-2)) {
|
||||
// ("image",), (_, "image") and (.., "img", "img_image")
|
||||
parts.last()
|
||||
} else {
|
||||
// (.., "img", "image") = "img_image"
|
||||
parts.at(-2) + "_" + parts.at(-1)
|
||||
}.replace(" ", "_")
|
||||
|
||||
let caption = if sink.pos().len() == 0 {
|
||||
caption + " (рисунок виконано самостійно)"
|
||||
} else if sink.pos().first() == none {
|
||||
caption
|
||||
} else {
|
||||
[#caption (за даними #sink.pos().first())]
|
||||
}
|
||||
|
||||
[#figure(image(path, ..sink.named()), caption: caption) #label(label_string)]
|
||||
}
|
||||
|
||||
// Styling {{{1
|
||||
/// NOTE: may be wrong
|
||||
#let ua_alpha_numbering = "абвгдежиклмнпрстуфхцшщюя".split("") // 0 = "", 1 = "а"
|
||||
|
||||
// general outlook {{{2
|
||||
// spacing between lines
|
||||
#let spacing = 0.95em
|
||||
|
||||
#let style(it) = {
|
||||
set page(
|
||||
paper: "a4",
|
||||
margin: (top: 20mm, right: 10mm, bottom: 20mm, left: 25mm),
|
||||
number-align: top + right,
|
||||
numbering: (..numbers) => {
|
||||
if numbers.pos().at(0) != 1 {
|
||||
numbering("1", numbers.pos().at(0))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
set text(font: ("Times New Roman", "Liberation Serif"), size: 14pt, hyphenate: false, lang: "uk")
|
||||
set par(justify: true, first-line-indent: (amount: 1.25cm, all: true))
|
||||
set underline(evade: false)
|
||||
|
||||
// set 1.5 line spacing
|
||||
set block(spacing: spacing)
|
||||
set par(spacing: spacing)
|
||||
set par(leading: spacing)
|
||||
|
||||
// enums and lists {{{2
|
||||
set enum(numbering: i => { ua_alpha_numbering.at(i) + ")" }, indent: 1.25cm, body-indent: 0.5cm)
|
||||
show enum: it => {
|
||||
set enum(indent: 0em, numbering: "1)")
|
||||
it
|
||||
}
|
||||
|
||||
set list(indent: 1.35cm, body-indent: 0.5cm, marker: [--])
|
||||
|
||||
// figures {{{2
|
||||
show figure: it => {
|
||||
v(spacing * 2, weak: true)
|
||||
it
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
set figure.caption(separator: [ -- ])
|
||||
show figure.where(kind: table): set figure.caption(position: top)
|
||||
show figure.caption.where(kind: table): set align(left)
|
||||
|
||||
// figure numbering
|
||||
show heading.where(level: 1): it => {
|
||||
counter(math.equation).update(0)
|
||||
counter(figure.where(kind: image)).update(0)
|
||||
counter(figure.where(kind: table)).update(0)
|
||||
counter(figure.where(kind: raw)).update(0)
|
||||
it
|
||||
}
|
||||
set math.equation(numbering: (..num) => numbering("(1.1)", counter(heading).get().at(0), num.pos().first()))
|
||||
set figure(numbering: (..num) => numbering("1.1", counter(heading).get().at(0), num.pos().first()))
|
||||
|
||||
// appearance of references to images and tables {{{2
|
||||
set ref(
|
||||
supplement: it => {
|
||||
if it == none or not it.has("kind") {
|
||||
it
|
||||
} else if it.kind == image {
|
||||
"див. рис."
|
||||
} else if it.kind == table {
|
||||
"див. таблицю"
|
||||
} else {
|
||||
it
|
||||
}
|
||||
},
|
||||
)
|
||||
show ref: it => {
|
||||
let el = it.element
|
||||
|
||||
if el == none or not el.has("kind") {
|
||||
return it
|
||||
}
|
||||
if el.kind != image and el.kind != table {
|
||||
return it
|
||||
}
|
||||
|
||||
[(#it)]
|
||||
}
|
||||
|
||||
// headings {{{2
|
||||
set heading(numbering: "1.1")
|
||||
|
||||
show heading.where(level: 1): it => {
|
||||
set align(center)
|
||||
set text(size: 14pt, weight: "semibold")
|
||||
|
||||
pagebreak(weak: true)
|
||||
upper(it)
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
show heading.where(level: 2): it => {
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
v(spacing * 2, weak: true)
|
||||
block(width: 100%, spacing: 0em)[
|
||||
#h(1.25cm)
|
||||
#counter(heading).display(it.numbering)
|
||||
#it.body
|
||||
]
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
show heading.where(level: 3): it => {
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
v(spacing * 2, weak: true)
|
||||
block(width: 100%, spacing: 0em)[
|
||||
#h(1.25cm)
|
||||
#counter(heading).display(it.numbering)
|
||||
#it.body
|
||||
]
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
it
|
||||
}
|
||||
|
||||
// Coursework template {{{1
|
||||
|
||||
/// DSTU 3008:2015 Template for NURE
|
||||
/// -> content
|
||||
/// - doc (content): Content to apply the template to.
|
||||
/// - title (str): Title of the document.
|
||||
/// - subject_shorthand (str): Subject short name.
|
||||
/// - department_gen (str): Department name in genitive form.
|
||||
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
|
||||
/// - mentors ((name: str, gender: str, degree: str),): List of mentors dicts.
|
||||
/// - edu_program_shorthand (str): Education program shorthand.
|
||||
/// - task_list (done_date: datetime, initial_date: datetime, source: (content | str), content: (content | str), graphics: (content | str)): Task list object.
|
||||
/// - calendar_plan ( plan_table: (content | str), approval_date: datetime): Calendar plan object.
|
||||
/// - abstract (keywords: (str, ), text: (content | str)): Abstract object.
|
||||
/// - bib_path path: Path to the bibliography yaml file.
|
||||
/// - appendices (content): Content with appendices.
|
||||
#let cw-template(
|
||||
doc,
|
||||
title: "NONE",
|
||||
subject_shorthand: "NONE",
|
||||
department_gen: "Програмної інженерії",
|
||||
author: (),
|
||||
mentors: (),
|
||||
edu_program_shorthand: "ПЗПІ",
|
||||
task_list: (),
|
||||
calendar_plan: (),
|
||||
abstract: (),
|
||||
bib_path: "bibl.yml",
|
||||
appendices: (),
|
||||
) = {
|
||||
set document(title: title, author: author.name)
|
||||
|
||||
show: style
|
||||
|
||||
let bib-count = state("citation-counter", ())
|
||||
show cite: it => {
|
||||
it
|
||||
bib-count.update(((..c)) => (..c, it.key))
|
||||
}
|
||||
show bibliography: it => {
|
||||
set text(size: 0pt)
|
||||
it
|
||||
}
|
||||
|
||||
|
||||
let head_mentor = mentors.at(0)
|
||||
let edu_program = edu_programs.at(edu_program_shorthand)
|
||||
|
||||
// page 1 {{{2
|
||||
[
|
||||
#set align(center)
|
||||
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
|
||||
|
||||
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
|
||||
|
||||
\
|
||||
|
||||
Кафедра Програмної інженерії
|
||||
|
||||
\
|
||||
|
||||
ПОЯСНЮВАЛЬНА ЗАПИСКА
|
||||
|
||||
ДО КУРСОВОЇ РОБОТИ
|
||||
|
||||
з дисципліни: "#subjects.at(subject_shorthand, default: "NONE")"
|
||||
|
||||
Тема роботи: "#title"
|
||||
|
||||
\ \ \
|
||||
|
||||
#columns(2, gutter: 4cm)[
|
||||
#set align(left)
|
||||
|
||||
#if author.gender == "m" { [Виконав\ ] } else { [Виконала\ ] } ст. гр. #author.group
|
||||
|
||||
\
|
||||
Керівник:\
|
||||
#head_mentor.degree
|
||||
|
||||
\
|
||||
Робота захищена на оцінку
|
||||
|
||||
\
|
||||
Комісія:\
|
||||
#for mentor in mentors {
|
||||
[#mentor.degree\
|
||||
]
|
||||
}
|
||||
|
||||
#colbreak()
|
||||
#set align(left)
|
||||
|
||||
\
|
||||
#author.name
|
||||
|
||||
\ \
|
||||
#head_mentor.name
|
||||
|
||||
\
|
||||
#underline(" " * 35)
|
||||
|
||||
\ \
|
||||
#for mentor in mentors {
|
||||
[#mentor.name\
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
#v(1fr)
|
||||
|
||||
Харків -- #task_list.done_date.display("[year]")
|
||||
|
||||
#pagebreak()
|
||||
]
|
||||
|
||||
// page 2 {{{2
|
||||
{
|
||||
uline[Харківський національний університет радіоелектроніки]
|
||||
|
||||
linebreak()
|
||||
linebreak()
|
||||
|
||||
grid(
|
||||
columns: (100pt, 1fr),
|
||||
bold[
|
||||
Кафедра
|
||||
Дисципліна
|
||||
Спеціальність
|
||||
],
|
||||
{
|
||||
uline(align: left, department_gen)
|
||||
linebreak()
|
||||
uline(align: left, subjects.at(subject_shorthand))
|
||||
linebreak()
|
||||
uline(align: left, [#edu_program.number #edu_program.name])
|
||||
},
|
||||
)
|
||||
grid(
|
||||
columns: (1fr, 1fr, 1fr),
|
||||
gutter: 0.3fr,
|
||||
[#bold[Курс] #uline(2)], [#bold[Група] #uline(author.group)], [#bold[Семестр] #uline(3)],
|
||||
)
|
||||
|
||||
linebreak()
|
||||
linebreak()
|
||||
linebreak()
|
||||
|
||||
align(center, bold[ЗАВДАННЯ \ на курсову роботу студента])
|
||||
|
||||
linebreak()
|
||||
|
||||
uline(align: left)[_#author.full_name_gen _]
|
||||
|
||||
linebreak()
|
||||
linebreak()
|
||||
|
||||
bold[\1. Тема роботи:]
|
||||
uline[#title.]
|
||||
|
||||
linebreak()
|
||||
|
||||
{
|
||||
bold[\2. Строк здачі закінченої роботи:]
|
||||
uline(task_list.done_date.display("[day].[month].[year]"))
|
||||
hfill(10fr)
|
||||
}
|
||||
|
||||
linebreak()
|
||||
|
||||
bold[\3. Вихідні дані для роботи:]
|
||||
uline(task_list.source)
|
||||
|
||||
linebreak()
|
||||
|
||||
bold[\4. Зміст розрахунково-пояснювальної записки:]
|
||||
uline(task_list.content)
|
||||
|
||||
linebreak()
|
||||
|
||||
bold[\5. Перелік графічного матеріалу:]
|
||||
uline(task_list.graphics)
|
||||
|
||||
linebreak()
|
||||
|
||||
{
|
||||
bold[\6. Дата видачі завдання:]
|
||||
uline(task_list.initial_date.display("[day].[month].[year]"))
|
||||
hfill(10fr)
|
||||
}
|
||||
|
||||
pagebreak()
|
||||
}
|
||||
|
||||
// page 3 {{{2
|
||||
{
|
||||
align(center, bold[КАЛЕНДАРНИЙ ПЛАН])
|
||||
set par(first-line-indent: 0pt)
|
||||
|
||||
linebreak()
|
||||
|
||||
calendar_plan.plan_table
|
||||
|
||||
linebreak()
|
||||
|
||||
grid(
|
||||
columns: (5fr, 5fr),
|
||||
grid(
|
||||
columns: (1fr, 2fr, 1fr),
|
||||
gutter: 0.2fr,
|
||||
[
|
||||
Студент \
|
||||
Керівник \
|
||||
#align(center)["#underline[#calendar_plan.approval_date.day()]"]
|
||||
],
|
||||
[
|
||||
#uline(align: center, []) \
|
||||
#uline(align: center, []) \
|
||||
#uline(align: center, month_gen(calendar_plan.approval_date.month()))
|
||||
],
|
||||
[
|
||||
\ \
|
||||
#underline[#calendar_plan.approval_date.year()] р.
|
||||
],
|
||||
),
|
||||
[
|
||||
#author.name, \
|
||||
#head_mentor.degree
|
||||
#head_mentor.name.
|
||||
],
|
||||
)
|
||||
|
||||
pagebreak()
|
||||
}
|
||||
|
||||
// page 4 {{{2
|
||||
[
|
||||
#align(center, bold[РЕФЕРАТ]) \
|
||||
|
||||
#context [
|
||||
#let pages = counter(page).final().at(0)
|
||||
#let images = query(figure.where(kind: image)).len()
|
||||
#let tables = query(figure.where(kind: table)).len()
|
||||
#let bibs = bib-count.final().dedup().len()
|
||||
/* TODO: why this stopped working?
|
||||
#let tables = counter(figure.where(kind: table)).final().at(0)
|
||||
#let images = counter(figure.where(kind: image)).final().at(0)*/
|
||||
|
||||
#let counters = ()
|
||||
|
||||
#if pages != 0 { counters.push[#pages с.] }
|
||||
#if tables != 0 { counters.push[#tables табл.] }
|
||||
#if images != 0 { counters.push[#images рис.] }
|
||||
#if bibs != 0 { counters.push[#bibs джерел] }
|
||||
|
||||
Пояснювальна записка до курсової роботи: #counters.join(", ").
|
||||
]
|
||||
|
||||
\
|
||||
|
||||
#{
|
||||
let keywords = abstract.keywords.map(upper)
|
||||
let is_cyrillic = word => word.split("").any(char => ("А" <= char and char <= "я"))
|
||||
|
||||
let n = keywords.len()
|
||||
for i in range(n) {
|
||||
for j in range(0, n - i - 1) {
|
||||
if (
|
||||
(not is_cyrillic(keywords.at(j)) and is_cyrillic(keywords.at(j + 1)))
|
||||
or (
|
||||
is_cyrillic(keywords.at(j)) == is_cyrillic(keywords.at(j + 1)) and keywords.at(j) > keywords.at(j + 1)
|
||||
)
|
||||
) {
|
||||
(keywords.at(j), keywords.at(j + 1)) = (keywords.at(j + 1), keywords.at(j))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
keywords.join(", ")
|
||||
}
|
||||
|
||||
\
|
||||
|
||||
#abstract.text
|
||||
]
|
||||
|
||||
// page 5 {{{2
|
||||
outline(
|
||||
title: [
|
||||
ЗМІСТ
|
||||
#v(spacing * 2, weak: true)
|
||||
],
|
||||
depth: 2,
|
||||
indent: auto,
|
||||
)
|
||||
|
||||
doc
|
||||
|
||||
// bibliography {{{2
|
||||
{
|
||||
heading(depth: 1, numbering: none)[Перелік джерел посилання]
|
||||
|
||||
bibliography(
|
||||
bib_path,
|
||||
style: "ieee",
|
||||
full: true,
|
||||
title: none,
|
||||
)
|
||||
|
||||
let bib_data = yaml(bib_path)
|
||||
|
||||
let format-entry(citation) = {
|
||||
if (citation.type == "Web") {
|
||||
let date_array = citation.url.date.split("-")
|
||||
let date = datetime(
|
||||
year: int(date_array.at(0)),
|
||||
month: int(date_array.at(1)),
|
||||
day: int(date_array.at(2)),
|
||||
)
|
||||
[
|
||||
#citation.title.
|
||||
#citation.author.
|
||||
URL: #citation.url.value (дата звернення: #date.display("[day].[month].[year]")).
|
||||
]
|
||||
} else if citation.type == "Book" [
|
||||
#citation.author
|
||||
#citation.title.
|
||||
#citation.publisher,
|
||||
#citation.date.
|
||||
#citation.page-total c.
|
||||
] else [
|
||||
UNSUPPORTED BIBLIOGRAPHY ENTRY TYPE, PLEASE OPEN AN ISSUE
|
||||
]
|
||||
}
|
||||
|
||||
show enum.item: it => {
|
||||
set par(first-line-indent: 0pt)
|
||||
box(width: 1.25cm)
|
||||
box(width: 1em + 0.5cm)[#it.number.]
|
||||
it.body
|
||||
linebreak()
|
||||
}
|
||||
|
||||
context {
|
||||
for (i, citation) in query(ref.where(element: none)).map(r => str(r.target)).dedup().enumerate() {
|
||||
enum.item(
|
||||
i + 1,
|
||||
format-entry(bib_data.at(citation)),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// appendices {{{2
|
||||
{
|
||||
counter(heading).update(0)
|
||||
|
||||
set heading(
|
||||
numbering: (i, ..nums) => {
|
||||
let char = upper(ua_alpha_numbering.at(i))
|
||||
if nums.pos().len() == 0 { char } else {
|
||||
char + "." + nums.pos().map(str).join(".")
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
show heading.where(level: 1): it => {
|
||||
set align(center)
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
pagebreak(weak: true)
|
||||
bold[ДОДАТОК #counter(heading).display(it.numbering)]
|
||||
linebreak()
|
||||
it.body
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
show heading.where(level: 2): it => {
|
||||
set text(size: 14pt, weight: "regular")
|
||||
|
||||
v(spacing * 2, weak: true)
|
||||
block(width: 100%, spacing: 0em)[
|
||||
#h(1.25cm)
|
||||
#counter(heading).display(it.numbering)
|
||||
#it.body
|
||||
]
|
||||
v(spacing * 2, weak: true)
|
||||
}
|
||||
|
||||
appendices
|
||||
}
|
||||
}
|
||||
|
||||
// Laboratory work template {{{1
|
||||
|
||||
/// DSTU 3008:2015 Template for NURE
|
||||
/// -> content
|
||||
/// - doc (content): Content to apply the template to.
|
||||
/// - doctype ("ЛБ" | "ПЗ"): Document type.
|
||||
/// - title (str): Title of the document.
|
||||
/// - subject_shorthand (str): Subject short name.
|
||||
/// - department_gen (str): Department name in genitive form.
|
||||
/// - worknumber (int): Number of the work, can be omitted.
|
||||
/// - authors ((name: str, full_name_gen: str, variant: int, group: str, gender: str),): List of Authors dicts.
|
||||
/// - mentor (name: str, gender: str, degree: str): Mentors objects.
|
||||
#let lab-pz-template(
|
||||
doc,
|
||||
doctype: "NONE",
|
||||
title: "NONE",
|
||||
subject_shorthand: "NONE",
|
||||
department_gen: "Програмної інженерії",
|
||||
worknumber: 1,
|
||||
authors: (),
|
||||
mentor: (),
|
||||
) = {
|
||||
set document(title: title, author: authors.at(0).name)
|
||||
|
||||
show: style
|
||||
|
||||
context counter(heading).update(worknumber - 1)
|
||||
|
||||
// page 1 {{{2
|
||||
align(center)[
|
||||
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ \
|
||||
ХАРКІВСЬКИЙ НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ РАДІОЕЛЕКТРОНІКИ
|
||||
|
||||
\ \
|
||||
Кафедра #department_gen
|
||||
|
||||
\ \ \
|
||||
Звіт \
|
||||
з
|
||||
#if doctype == "ЛБ" [лабораторної роботи] else [практичної роботи]
|
||||
#if worknumber != none [№ #worknumber]
|
||||
|
||||
з дисципліни: "#subjects.at(subject_shorthand, default: "UNLNOWN SUBJECT, PLEASE OPEN AN ISSUE")"
|
||||
|
||||
з теми: "#title"
|
||||
|
||||
\ \ \ \
|
||||
|
||||
#columns(2)[
|
||||
#set align(left)
|
||||
#set par(first-line-indent: 0pt)
|
||||
#if authors.len() == 1 {
|
||||
let author = authors.at(0)
|
||||
if author.gender == "m" [Виконав:\ ] else [Виконала:\ ]
|
||||
[
|
||||
ст. гр. #author.group\
|
||||
#author.name\
|
||||
]
|
||||
if author.variant != none [Варіант: №#author.variant]
|
||||
} else [
|
||||
Виконали:\
|
||||
ст. гр. #authors.at(0).group\
|
||||
#for author in authors {
|
||||
[#author.name \ ]
|
||||
}
|
||||
]
|
||||
|
||||
#colbreak()
|
||||
#set align(right)
|
||||
|
||||
#if mentor.gender == "m" { [Перевірив:\ ] } else { [Перевірила:\ ] }
|
||||
#mentor.degree #if mentor.degree.len() >= 15 [\ ]
|
||||
#mentor.name\
|
||||
]
|
||||
|
||||
#v(1fr)
|
||||
|
||||
Харків -- #datetime.today().display("[year]")
|
||||
]
|
||||
|
||||
pagebreak(weak: true)
|
||||
|
||||
heading(title)
|
||||
doc
|
||||
}
|
||||
|
||||
// vim:sts=2:sw=2:fdl=0:fdm=marker:cms=/*%s*/
|
17
semester-4/ОС/lb-4/src/.clangd
Normal file
@ -0,0 +1,17 @@
|
||||
CompileFlags:
|
||||
Add: [-Wall, -Wextra, -std=c++17, -DBUILD_SHARED, --target=x86_64-w64-mingw32]
|
||||
CompilationDatabase: build/
|
||||
|
||||
Diagnostics:
|
||||
UnusedIncludes: Strict
|
||||
|
||||
InlayHints:
|
||||
Enabled: Yes
|
||||
ParameterNames: Yes
|
||||
DeducedTypes: Yes
|
||||
|
||||
Index:
|
||||
Background: Build
|
||||
|
||||
Hover:
|
||||
ShowAKA: Yes
|
23
semester-4/ОС/lb-4/src/cpp/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
CC = x86_64-w64-mingw32-g++
|
||||
CXXFLAGS = -std=c++23 -I/usr/x86_64-w64-mingw32/include -Iinclude -static
|
||||
LDFLAGS = -lstdc++exp
|
||||
|
||||
SOURCES = main.cpp $(wildcard src/*.cpp)
|
||||
TARGET = build/main.exe
|
||||
|
||||
.PHONY: all build run clean
|
||||
|
||||
all: build run
|
||||
|
||||
build: clean $(TARGET)
|
||||
|
||||
$(TARGET): $(SOURCES)
|
||||
@mkdir -p build
|
||||
@$(CC) $(CXXFLAGS) -o $(TARGET) $(SOURCES) $(LDFLAGS)
|
||||
|
||||
run: $(TARGET)
|
||||
@WINEDEBUG=fixme-all wine $(TARGET)
|
||||
|
||||
clean:
|
||||
@rm -rf build
|
||||
@rm -rf ../files_moved
|
26
semester-4/ОС/lb-4/src/cpp/include/System/IO/Directory.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "IFileSystemEntity.h"
|
||||
|
||||
namespace System::IO {
|
||||
class Directory : public IFileSystemEntity {
|
||||
private:
|
||||
std::wstring path;
|
||||
public:
|
||||
explicit Directory(const std::wstring& directoryPath);
|
||||
~Directory() override = default;
|
||||
|
||||
std::wstring GetPath() const override;
|
||||
DWORD GetAttributes() const override;
|
||||
bool SetAttributes(DWORD attributes) override;
|
||||
|
||||
static bool Exists(const std::wstring& path);
|
||||
static bool CreateDirectory(const std::wstring& path);
|
||||
static bool Delete(const std::wstring& path);
|
||||
static bool Move(const std::wstring& source, const std::wstring& destination);
|
||||
static std::vector<std::wstring> GetFiles(const std::wstring& path);
|
||||
static std::vector<std::wstring> GetDirectories(const std::wstring& path);
|
||||
};
|
||||
}
|
33
semester-4/ОС/lb-4/src/cpp/include/System/IO/DriveInfo.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
namespace System::IO {
|
||||
enum class DriveType : unsigned int {
|
||||
Unknown = 0,
|
||||
NoRootDir = 1,
|
||||
Removable = 2,
|
||||
Fixed = 3,
|
||||
Remote = 4,
|
||||
CDROM = 5,
|
||||
RAM = 6
|
||||
};
|
||||
|
||||
class DriveInfo {
|
||||
public:
|
||||
explicit DriveInfo(const std::wstring& path);
|
||||
|
||||
std::wstring Name;
|
||||
DriveType DriveType;
|
||||
std::wstring DriveFormat;
|
||||
uint64_t TotalSize;
|
||||
uint64_t AvailableFreeSpace;
|
||||
bool IsReady;
|
||||
|
||||
static std::vector<DriveInfo> GetDrives();
|
||||
|
||||
private:
|
||||
std::wstring rootPath;
|
||||
};
|
||||
}
|
27
semester-4/ОС/lb-4/src/cpp/include/System/IO/File.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "IFileSystemEntity.h"
|
||||
|
||||
namespace System::IO {
|
||||
class File : public IFileSystemEntity {
|
||||
private:
|
||||
std::wstring path;
|
||||
|
||||
public:
|
||||
explicit File(const std::wstring &filePath);
|
||||
~File() override = default;
|
||||
|
||||
std::wstring GetPath() const override;
|
||||
static DWORD GetAttributes(const std::wstring &path);
|
||||
static bool SetAttributes(const std::wstring &path, DWORD attributes);
|
||||
|
||||
static bool Exists(const std::wstring &path);
|
||||
static bool Copy(const std::wstring &source, const std::wstring &destination,
|
||||
bool overwrite = false);
|
||||
static bool Delete(const std::wstring &path);
|
||||
static bool Move(const std::wstring &source, const std::wstring &destination);
|
||||
static uint64_t GetSize(const std::wstring &path);
|
||||
};
|
||||
} // namespace System::IO
|
26
semester-4/ОС/lb-4/src/cpp/include/System/IO/FileStream.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
namespace System::IO {
|
||||
class FileStream {
|
||||
private:
|
||||
HANDLE hFile;
|
||||
std::wstring path;
|
||||
public:
|
||||
FileStream(const std::wstring& filePath,
|
||||
DWORD access,
|
||||
DWORD creationDisposition,
|
||||
DWORD shareMode = 0,
|
||||
DWORD flagsAndAttributes = FILE_ATTRIBUTE_NORMAL);
|
||||
~FileStream();
|
||||
|
||||
bool Read(void* buffer, DWORD numBytesToRead, DWORD& numBytesRead);
|
||||
bool Write(const void* buffer, DWORD numBytesToWrite, DWORD& numBytesWritten);
|
||||
bool Seek(LARGE_INTEGER offset, DWORD moveMethod, ULARGE_INTEGER& newPos);
|
||||
bool SetEnd();
|
||||
|
||||
HANDLE GetHandle() const { return hFile; }
|
||||
std::wstring GetPath() const { return path; }
|
||||
};
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
namespace System::IO {
|
||||
class IFileSystemEntity {
|
||||
public:
|
||||
virtual std::wstring GetPath() const = 0;
|
||||
virtual DWORD GetAttributes() const = 0;
|
||||
virtual bool SetAttributes(DWORD attributes) = 0;
|
||||
virtual ~IFileSystemEntity() = default;
|
||||
};
|
||||
}
|
112
semester-4/ОС/lb-4/src/cpp/main.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include <chrono>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "include/System/IO/Directory.h"
|
||||
#include "include/System/IO/DriveInfo.h"
|
||||
#include "include/System/IO/File.h"
|
||||
#include "include/System/IO/FileStream.h"
|
||||
|
||||
using namespace System::IO;
|
||||
|
||||
int main() {
|
||||
const std::wstring filesDir = L"../files";
|
||||
const std::wstring filePath = filesDir + L"/bigfile.dat";
|
||||
const std::wstring copyPath = filesDir + L"/bigfile_copy.dat";
|
||||
const std::wstring movedCopyPath = filesDir + L"/moved_bigfile_copy.dat";
|
||||
const std::wstring movedDirPath = L"../files_moved";
|
||||
const size_t blockSize = 1024 * 1024; // 1 MB
|
||||
const int32_t iterations = 100; // 100 MB file
|
||||
|
||||
if (!Directory::Exists(filesDir))
|
||||
Directory::CreateDirectory(filesDir);
|
||||
|
||||
std::vector<char> buffer(blockSize, 'A');
|
||||
DWORD bytesWritten = 0;
|
||||
|
||||
auto startWrite = std::chrono::high_resolution_clock::now();
|
||||
{
|
||||
FileStream outStream(filePath, GENERIC_WRITE, CREATE_ALWAYS);
|
||||
for (int32_t i = 0; i < iterations; i++)
|
||||
outStream.Write(buffer.data(), static_cast<DWORD>(buffer.size()),
|
||||
bytesWritten);
|
||||
}
|
||||
auto endWrite = std::chrono::high_resolution_clock::now();
|
||||
std::wcout << L"C++ Write time: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
endWrite - startWrite)
|
||||
.count()
|
||||
<< L" ms" << std::endl;
|
||||
|
||||
auto startCopy = std::chrono::high_resolution_clock::now();
|
||||
File::Copy(filePath, copyPath, true);
|
||||
auto endCopy = std::chrono::high_resolution_clock::now();
|
||||
std::wcout << L"C++ Copy time: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(endCopy -
|
||||
startCopy)
|
||||
.count()
|
||||
<< L" ms" << std::endl;
|
||||
|
||||
auto startRead = std::chrono::high_resolution_clock::now();
|
||||
{
|
||||
FileStream inStream(filePath, GENERIC_READ, OPEN_EXISTING);
|
||||
std::vector<char> readBuffer(blockSize);
|
||||
DWORD bytesRead = 0;
|
||||
while (inStream.Read(readBuffer.data(),
|
||||
static_cast<DWORD>(readBuffer.size()), bytesRead) &&
|
||||
bytesRead > 0) {
|
||||
}
|
||||
}
|
||||
auto endRead = std::chrono::high_resolution_clock::now();
|
||||
std::wcout << L"C++ Read time: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(endRead -
|
||||
startRead)
|
||||
.count()
|
||||
<< L" ms" << std::endl;
|
||||
|
||||
auto startAttr = std::chrono::high_resolution_clock::now();
|
||||
DWORD attrs = File::GetAttributes(filePath);
|
||||
File::SetAttributes(filePath, attrs | FILE_ATTRIBUTE_HIDDEN);
|
||||
File::SetAttributes(filePath, attrs);
|
||||
auto endAttr = std::chrono::high_resolution_clock::now();
|
||||
std::wcout << L"File attribute toggle time: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(endAttr -
|
||||
startAttr)
|
||||
.count()
|
||||
<< L" ms" << std::endl;
|
||||
|
||||
auto startMoveFile = std::chrono::high_resolution_clock::now();
|
||||
File::Move(copyPath, movedCopyPath);
|
||||
auto endMoveFile = std::chrono::high_resolution_clock::now();
|
||||
std::wcout << L"Move file time: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
endMoveFile - startMoveFile)
|
||||
.count()
|
||||
<< L" ms" << std::endl;
|
||||
|
||||
if (!Directory::Exists(movedDirPath))
|
||||
Directory::CreateDirectory(movedDirPath);
|
||||
|
||||
auto startMoveDir = std::chrono::high_resolution_clock::now();
|
||||
Directory::Move(filesDir, movedDirPath + L"/files");
|
||||
auto endMoveDir = std::chrono::high_resolution_clock::now();
|
||||
std::wcout << L"Move directory time: "
|
||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
endMoveDir - startMoveDir)
|
||||
.count()
|
||||
<< L" ms" << std::endl;
|
||||
|
||||
std::wcout << L"Listing drives:\n";
|
||||
auto fixedDrives = DriveInfo::GetDrives();
|
||||
for (const auto &d : fixedDrives) {
|
||||
if (d.IsReady && d.DriveType == DriveType::Fixed &&
|
||||
d.DriveFormat != L"squashfs") {
|
||||
std::wcout << L"Drive: " << d.Name << L" | Type: "
|
||||
<< static_cast<UINT>(d.DriveType) << L" | Format: "
|
||||
<< d.DriveFormat << L" | Total: "
|
||||
<< d.TotalSize / (1024 * 1024) << L" MB" << L" | Free: "
|
||||
<< d.AvailableFreeSpace / (1024 * 1024) << L" MB\n";
|
||||
}
|
||||
}
|
||||
}
|
69
semester-4/ОС/lb-4/src/cpp/src/Directory.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include "../include/System/IO/Directory.h"
|
||||
|
||||
namespace System::IO {
|
||||
Directory::Directory(const std::wstring& directoryPath) : path(directoryPath) { }
|
||||
|
||||
std::wstring Directory::GetPath() const {
|
||||
return path;
|
||||
}
|
||||
|
||||
DWORD Directory::GetAttributes() const {
|
||||
return GetFileAttributesW(path.c_str());
|
||||
}
|
||||
|
||||
bool Directory::SetAttributes(DWORD attributes) {
|
||||
return SetFileAttributesW(path.c_str(), attributes) != 0;
|
||||
}
|
||||
|
||||
bool Directory::Exists(const std::wstring& path) {
|
||||
DWORD attributes = GetFileAttributesW(path.c_str());
|
||||
return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
bool Directory::CreateDirectory(const std::wstring& path) {
|
||||
return CreateDirectoryW(path.c_str(), nullptr) != 0;
|
||||
}
|
||||
|
||||
bool Directory::Delete(const std::wstring& path) {
|
||||
return RemoveDirectoryW(path.c_str()) != 0;
|
||||
}
|
||||
|
||||
bool Directory::Move(const std::wstring& source, const std::wstring& destination) {
|
||||
return MoveFileExW(source.c_str(), destination.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
std::vector<std::wstring> Directory::GetFiles(const std::wstring& path) {
|
||||
std::vector<std::wstring> files;
|
||||
std::wstring searchPath = path + L"\\*";
|
||||
WIN32_FIND_DATAW findData;
|
||||
HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
return files;
|
||||
do {
|
||||
if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
files.push_back(findData.cFileName);
|
||||
} while (FindNextFileW(hFind, &findData) != 0);
|
||||
FindClose(hFind);
|
||||
return files;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> Directory::GetDirectories(const std::wstring& path) {
|
||||
std::vector<std::wstring> directories;
|
||||
std::wstring searchPath = path + L"\\*";
|
||||
WIN32_FIND_DATAW findData;
|
||||
HANDLE hFind = FindFirstFileW(searchPath.c_str(), &findData);
|
||||
if (hFind == INVALID_HANDLE_VALUE)
|
||||
return directories;
|
||||
do {
|
||||
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
std::wstring dirName = findData.cFileName;
|
||||
if (dirName != L"." && dirName != L"..")
|
||||
directories.push_back(dirName);
|
||||
}
|
||||
} while (FindNextFileW(hFind, &findData) != 0);
|
||||
FindClose(hFind);
|
||||
return directories;
|
||||
}
|
||||
}
|
51
semester-4/ОС/lb-4/src/cpp/src/DriveInfo.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "../include/System/IO/DriveInfo.h"
|
||||
#include <windows.h>
|
||||
|
||||
namespace System::IO {
|
||||
DriveType toDriveType(UINT type) {
|
||||
switch (type) {
|
||||
case DRIVE_REMOVABLE: return DriveType::Removable;
|
||||
case DRIVE_FIXED: return DriveType::Fixed;
|
||||
case DRIVE_REMOTE: return DriveType::Remote;
|
||||
case DRIVE_CDROM: return DriveType::CDROM;
|
||||
case DRIVE_RAMDISK: return DriveType::RAM;
|
||||
case DRIVE_NO_ROOT_DIR: return DriveType::NoRootDir;
|
||||
default: return DriveType::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
DriveInfo::DriveInfo(const std::wstring& path)
|
||||
: rootPath(path)
|
||||
{
|
||||
Name = rootPath;
|
||||
UINT type = GetDriveTypeW(rootPath.c_str());
|
||||
DriveType = toDriveType(type);
|
||||
IsReady = (type != DRIVE_NO_ROOT_DIR);
|
||||
|
||||
WCHAR fsName[MAX_PATH] = {0};
|
||||
if (GetVolumeInformationW(rootPath.c_str(), nullptr, 0, nullptr, nullptr, nullptr, fsName, MAX_PATH)) {
|
||||
DriveFormat = fsName;
|
||||
} else {
|
||||
DriveFormat.clear();
|
||||
}
|
||||
|
||||
ULARGE_INTEGER total, free, available;
|
||||
if (GetDiskFreeSpaceExW(rootPath.c_str(), &available, &total, &free)) {
|
||||
TotalSize = total.QuadPart;
|
||||
AvailableFreeSpace = available.QuadPart;
|
||||
} else {
|
||||
TotalSize = 0;
|
||||
AvailableFreeSpace = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<DriveInfo> DriveInfo::GetDrives() {
|
||||
std::vector<DriveInfo> drives;
|
||||
WCHAR buffer[256] = {0};
|
||||
DWORD len = GetLogicalDriveStringsW(256, buffer);
|
||||
for (WCHAR* p = buffer; *p; p += wcslen(p) + 1) {
|
||||
drives.emplace_back(p);
|
||||
}
|
||||
return drives;
|
||||
}
|
||||
}
|
62
semester-4/ОС/lb-4/src/cpp/src/File.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include <windows.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../include/System/IO/File.h"
|
||||
|
||||
namespace System::IO {
|
||||
File::File(const std::wstring& filePath) : path(filePath) { }
|
||||
|
||||
std::wstring File::GetPath() const {
|
||||
return path;
|
||||
}
|
||||
|
||||
DWORD File::GetAttributes(const std::wstring& path) {
|
||||
return GetFileAttributesW(path.c_str());
|
||||
}
|
||||
|
||||
bool File::SetAttributes(const std::wstring& path, DWORD attributes) {
|
||||
return SetFileAttributesW(path.c_str(), attributes) != FALSE;
|
||||
}
|
||||
|
||||
bool File::Exists(const std::wstring& path) {
|
||||
DWORD attributes = GetFileAttributesW(path.c_str());
|
||||
return (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY));
|
||||
}
|
||||
|
||||
bool File::Copy(const std::wstring& source, const std::wstring& destination, bool overwrite) {
|
||||
return CopyFileW(source.c_str(), destination.c_str(), overwrite ? FALSE : TRUE) != 0;
|
||||
}
|
||||
|
||||
bool File::Delete(const std::wstring& path) {
|
||||
return DeleteFileW(path.c_str()) != 0;
|
||||
}
|
||||
|
||||
bool File::Move(const std::wstring& source, const std::wstring& destination) {
|
||||
return MoveFileExW(source.c_str(), destination.c_str(), MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
uint64_t File::GetSize(const std::wstring& path) {
|
||||
HANDLE hFile = CreateFileW(
|
||||
path.c_str(),
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
throw std::runtime_error("Unable to open file to get its size.");
|
||||
}
|
||||
|
||||
LARGE_INTEGER size;
|
||||
if (!GetFileSizeEx(hFile, &size)) {
|
||||
CloseHandle(hFile);
|
||||
throw std::runtime_error("Unable to get file size.");
|
||||
}
|
||||
|
||||
CloseHandle(hFile);
|
||||
return static_cast<uint64_t>(size.QuadPart);
|
||||
}
|
||||
}
|
42
semester-4/ОС/lb-4/src/cpp/src/FileStream.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include <windows.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "../include/System/IO/FileStream.h"
|
||||
|
||||
namespace System::IO {
|
||||
FileStream::FileStream(const std::wstring& filePath,
|
||||
DWORD access,
|
||||
DWORD creationDisposition,
|
||||
DWORD shareMode,
|
||||
DWORD flagsAndAttributes)
|
||||
: path(filePath)
|
||||
{
|
||||
hFile = CreateFileW(filePath.c_str(), access, shareMode, nullptr, creationDisposition, flagsAndAttributes, nullptr);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
throw std::runtime_error("Unable to open file.");
|
||||
}
|
||||
|
||||
FileStream::~FileStream() {
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
|
||||
bool FileStream::Read(void* buffer, DWORD numBytesToRead, DWORD& numBytesRead) {
|
||||
return ReadFile(hFile, buffer, numBytesToRead, &numBytesRead, nullptr) != 0;
|
||||
}
|
||||
|
||||
bool FileStream::Write(const void* buffer, DWORD numBytesToWrite, DWORD& numBytesWritten) {
|
||||
return WriteFile(hFile, buffer, numBytesToWrite, &numBytesWritten, nullptr) != 0;
|
||||
}
|
||||
|
||||
bool FileStream::Seek(LARGE_INTEGER offset, DWORD moveMethod, ULARGE_INTEGER& newPos) {
|
||||
LARGE_INTEGER tempPos = { 0 };
|
||||
BOOL result = SetFilePointerEx(hFile, offset, &tempPos, moveMethod);
|
||||
newPos.QuadPart = static_cast<ULONGLONG>(tempPos.QuadPart);
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
bool FileStream::SetEnd() {
|
||||
return SetEndOfFile(hFile) != 0;
|
||||
}
|
||||
}
|
83
semester-4/ОС/lb-4/src/cs/Program.cs
Normal file
@ -0,0 +1,83 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
string filesDir = "../files";
|
||||
string filePath = Path.Combine(filesDir, "bigfile.dat");
|
||||
string copyPath = Path.Combine(filesDir, "bigfile_copy.dat");
|
||||
string movedCopyPath = Path.Combine(filesDir, "moved_bigfile_copy.dat");
|
||||
string movedDirPath = "../files_moved";
|
||||
int blockSize = 1024 * 1024; // 1 MB
|
||||
int iterations = 100; // 100 MB
|
||||
|
||||
if (!Directory.Exists(filesDir))
|
||||
Directory.CreateDirectory(filesDir);
|
||||
|
||||
byte[] buffer = new byte[blockSize];
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
buffer[i] = (byte)'A';
|
||||
|
||||
var swWrite = Stopwatch.StartNew();
|
||||
using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
for (int i = 0; i < iterations; i++)
|
||||
fs.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
swWrite.Stop();
|
||||
Console.WriteLine($"C# Write time: {swWrite.ElapsedMilliseconds} ms");
|
||||
|
||||
var swCopy = Stopwatch.StartNew();
|
||||
File.Copy(filePath, copyPath, true);
|
||||
swCopy.Stop();
|
||||
Console.WriteLine($"C# Copy time: {swCopy.ElapsedMilliseconds} ms");
|
||||
|
||||
var swRead = Stopwatch.StartNew();
|
||||
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
byte[] readBuffer = new byte[blockSize];
|
||||
while (fs.Read(readBuffer, 0, readBuffer.Length) > 0) { }
|
||||
}
|
||||
swRead.Stop();
|
||||
Console.WriteLine($"C# Read time: {swRead.ElapsedMilliseconds} ms");
|
||||
|
||||
var swAttr = Stopwatch.StartNew();
|
||||
FileAttributes originalAttrs = File.GetAttributes(filePath);
|
||||
File.SetAttributes(filePath, originalAttrs | FileAttributes.Hidden);
|
||||
File.SetAttributes(filePath, originalAttrs);
|
||||
swAttr.Stop();
|
||||
Console.WriteLine($"File attribute toggle time: {swAttr.ElapsedMilliseconds} ms");
|
||||
|
||||
var swMoveFile = Stopwatch.StartNew();
|
||||
File.Move(copyPath, movedCopyPath, true);
|
||||
swMoveFile.Stop();
|
||||
Console.WriteLine($"Move file time: {swMoveFile.ElapsedMilliseconds} ms");
|
||||
|
||||
if (!Directory.Exists(movedDirPath))
|
||||
Directory.CreateDirectory(movedDirPath);
|
||||
|
||||
var swMoveDir = Stopwatch.StartNew();
|
||||
Directory.Move(filesDir, Path.Combine(movedDirPath, "files"));
|
||||
swMoveDir.Stop();
|
||||
Console.WriteLine($"Move directory time: {swMoveDir.ElapsedMilliseconds} ms");
|
||||
|
||||
Console.WriteLine("Listing fixed drives:");
|
||||
var fixedDrives = DriveInfo.GetDrives()
|
||||
.Where(d => d.IsReady &&
|
||||
d.DriveType == DriveType.Fixed &&
|
||||
d.DriveFormat != "squashfs" &&
|
||||
d.DriveFormat != "tracefs" &&
|
||||
d.DriveFormat != "pstorefs" &&
|
||||
d.DriveFormat != "bpf_fs" &&
|
||||
d.DriveFormat != "rpc_pipefs");
|
||||
|
||||
foreach (var drive in fixedDrives)
|
||||
{
|
||||
Console.WriteLine($"Drive: {drive.Name} | " +
|
||||
$"Type: {drive.DriveType} | Format: {drive.DriveFormat} | " +
|
||||
$"Total: {drive.TotalSize / (1024 * 1024)} MB | " +
|
||||
$"Free: {drive.AvailableFreeSpace / (1024 * 1024)} MB");
|
||||
}
|
||||
}
|
||||
}
|
10
semester-4/ОС/lb-4/src/cs/cs.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
24
semester-4/ОС/lb-4/src/src.sln
Normal file
@ -0,0 +1,24 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.2.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cs", "cs\cs.csproj", "{C2B9A492-D5E2-4F2E-6856-CE8104140E99}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C2B9A492-D5E2-4F2E-6856-CE8104140E99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C2B9A492-D5E2-4F2E-6856-CE8104140E99}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C2B9A492-D5E2-4F2E-6856-CE8104140E99}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C2B9A492-D5E2-4F2E-6856-CE8104140E99}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {B1CAAF6F-AAAE-4123-9A24-FC3315E7AFCD}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
136
semester-4/ОС/lb-4/Лр_4_Ситник_Малишкін_ПЗПІ_23_2.typ
Normal file
@ -0,0 +1,136 @@
|
||||
// #import "@local/nure:0.0.0": *
|
||||
#import "lib.typ": *
|
||||
|
||||
#show: lab-pz-template.with(
|
||||
doctype: "ЛБ",
|
||||
title: "Керування зовнішніми пристроями. Нестандартні пристрої",
|
||||
subject_shorthand: "ОС",
|
||||
department_gen: "Програмної інженерії",
|
||||
authors: (
|
||||
(
|
||||
name: "Ситник Є. С.",
|
||||
full_name_gen: "Ситника Єгора Сергійовича",
|
||||
group: "ПЗПІ-23-2",
|
||||
gender: "m",
|
||||
variant: none,
|
||||
),
|
||||
(
|
||||
name: "Малишкін А. С.",
|
||||
full_name_gen: "Малишкіна Андрія Сергійовича",
|
||||
group: "ПЗПІ-23-2",
|
||||
gender: "m",
|
||||
variant: none,
|
||||
),
|
||||
),
|
||||
mentor: (
|
||||
name: "Мельнікова Р. В.",
|
||||
gender: "f",
|
||||
degree: "доц. каф. ПІ",
|
||||
),
|
||||
worknumber: 4,
|
||||
)
|
||||
|
||||
#v(-spacing)
|
||||
|
||||
== Мета роботи
|
||||
Навчитися практичному використанню функцій WinAPI для роботи з файлами.
|
||||
|
||||
== Хід роботи
|
||||
#v(-spacing)
|
||||
=== Створення класу для роботи з пристроями, файлами та каталогами.
|
||||
#v(-spacing)
|
||||
==== Вивчити усі функції, які використовуються для роботи з пристроями, файлами та каталогами в C\#.
|
||||
В C\# класи для роботи з пристроями, файлами та каталогами знаходяться в просторі імен "System.IO".
|
||||
Такі класи як "File", "FileStream", "Directory" та "DriveInfo" надають основні засоби для взаємодії з файловою системою.
|
||||
|
||||
Клас "File" пропонує статичні методи для виконання базових операцій над файлами.
|
||||
До них належать: створення нового файлу ("File.Create"), видалення існуючого файлу ("File.Delete"),
|
||||
перевірка існування файлу ("File.Exists"), копіювання файлу ("File.Copy"), переміщення файлу ("File.Move"), та інші.
|
||||
|
||||
Клас "FileStream" надає базову функціональність для роботи з файлами як з потоками даних.
|
||||
Його основні функції включають відкриття файлу для читання або запису (через конструктори або методи "Open", "OpenRead", "OpenWrite"),
|
||||
читання даних з файлу ("Read"), запис даних у файл ("Write"), закриття файлового потоку
|
||||
("Close" або використання блоку "using" для автоматичного закриття), а також керування поточною позицією у файлі ("Seek").
|
||||
|
||||
Клас "Directory" надає статичні методи для виконання базових операцій над директоріями.
|
||||
Серед них: створення нової директорії ("Directory.CreateDirectory"), видалення існуючої директорії ("Directory.Delete"),
|
||||
перевірка існування директорії ("Directory.Exists"), переміщення директорії ("Directory.Move"),
|
||||
а також отримання списку файлів у директорії ("Directory.GetFiles") та списку піддиректорій ("Directory.GetDirectories").
|
||||
|
||||
Клас "DriveInfo" надає інформацію про логічні диски, підключені до комп'ютера,
|
||||
для отримання інформації про конкретний диск необхідно створити його екземпляр,
|
||||
передавши ім'я диску в конструктор, а серед основних властивостей можна знайти ім'я диску ("Name"),
|
||||
його тип ("DriveType"), стан готовності ("IsReady"), загальний розмір ("TotalSize"),
|
||||
доступний вільний простір ("AvailableFreeSpace"), формат файлової системи ("DriveFormat"),
|
||||
мітку тому ("VolumeLabel") та об'єкт кореневого каталогу ("RootDirectory"),
|
||||
а для отримання інформації про всі диски в системі використовується статичний метод "GetDrives".
|
||||
|
||||
==== Визначити клас (класи) для мови С++, інтерфейс для яких подібний інтерфейсу C\#.
|
||||
Створимо на C++ класи "File", "FileStream", "Directory" та "DriveInfo". Для кожного з них створимо власний файл заголовків.
|
||||
|
||||
#figure(image("img/File.h.png", width: 83%), caption: [Вміст файлу "File.h"])
|
||||
#figure(image("img/FileStream.h.png", width: 83%), caption: [Вміст файлу "FileStream.h"])
|
||||
#figure(image("img/Directory.h.png", width: 83%), caption: [Вміст файлу "Directory.h"])
|
||||
#figure(image("img/DriveInfo.h.png", width: 96%), caption: [Вміст файлу "DriveInfo.h"])
|
||||
|
||||
==== Реалізувати функції класу (класів) за допомогою функцій WinAPI.
|
||||
Оскільки WinAPI надає функції, майже ідентичні необхідним, більшість з реалізацій є лише обгортками навколо відповідних функцій WinAPI.
|
||||
|
||||
Наприклад функція "SetAttributes" класу "File" має наступний вигляд:
|
||||
#figure(image("img/File_SetAttributes.png"), caption: [Реалізація функції "SetAttributes" класу "File"])
|
||||
|
||||
Таким чином реалізовано більшість методів.
|
||||
|
||||
Із методів, що не мають точних аналогів у WinAPI можна виділити такі.
|
||||
|
||||
#figure(image("img/File_GetSize.png", width: 85%), caption: [Реалізація функції "GetSize" класу "File"])
|
||||
#figure(
|
||||
image("img/Directory_GetDirectories.png", width: 85%),
|
||||
caption: [Реалізація функції "GetDirectories" класу "Directory"],
|
||||
)
|
||||
#figure(image("img/Directory_GetFiles.png"), caption: [Реалізація функції "GetFiles" класу "Directory"])
|
||||
#figure(image("img/DriveInfo_GetDrives.png"), caption: [Реалізація функції "GetDrives" класу "DriveInfo"])
|
||||
|
||||
==== Порівняти швидкодію функцій при їх використанні для C\#, C в разі використання великих файлів.
|
||||
|
||||
Створимо прості програми для порівняння швидкодії функцій стандартної бібліотеки C\# та функцій реалізованих на С++.
|
||||
|
||||
Для замірів часу на С++ використаємо модуль "chrono" із стандартної бібліотеки.
|
||||
|
||||
Для зручності тестів заздалегідь підготуємо всі змінні із потрібними шляхами:
|
||||
#figure(image("img/cpp_1.png"), caption: [Підготовка до тестів])
|
||||
|
||||
Додамо код для тестів:
|
||||
#figure(image("img/cpp_2.png"), caption: [Тест запису в файл])
|
||||
#figure(image("img/cpp_3.png"), caption: [Тест копіювання файлу])
|
||||
#figure(image("img/cpp_4.png"), caption: [Тест читання з файлу])
|
||||
#figure(image("img/cpp_5.png"), caption: [Тест отримання та встановлення атрибутів файлу])
|
||||
#figure(image("img/cpp_6.png"), caption: [Тест переміщення файлу])
|
||||
#figure(image("img/cpp_7.png"), caption: [Тест переміщення директорії])
|
||||
#figure(image("img/cpp_8.png"), caption: [Тест отримання інформації про носії даних])
|
||||
|
||||
Для замірів часу на C\# скористаємося класом "StopWatch" стандартної бібліотеки.
|
||||
|
||||
Для зручності тестів заздалегідь підготуємо всі змінні із потрібними шляхами:
|
||||
#figure(image("img/cs_1.png"), caption: [Підготовка до тестів])
|
||||
|
||||
Додамо код для тестів:
|
||||
#figure(image("img/cs_2.png"), caption: [Тест запису в файл])
|
||||
#figure(image("img/cs_3.png"), caption: [Тест копіювання файлу])
|
||||
#figure(image("img/cs_4.png"), caption: [Тест читання з файлу])
|
||||
#figure(image("img/cs_5.png"), caption: [Тест отримання та встановлення атрибутів файлу])
|
||||
#figure(image("img/cs_6.png"), caption: [Тест переміщення файлу])
|
||||
#figure(image("img/cs_7.png"), caption: [Тест переміщення директорії])
|
||||
#figure(image("img/cs_8.png"), caption: [Тест отримання інформації про носії даних])
|
||||
|
||||
Запустимо обидві програми, та порівняємо результати.
|
||||
|
||||
// #figure(image("img/cpp_test.png"), caption: [Результат тестування С++ програми])
|
||||
#figure(image("img/test.jpg", width: 87%), caption: [Результат тестування програм])
|
||||
|
||||
Варто зазначити, що оскільки лабораторна робота виконувалась на операційній системі Linux, програми показують дещо різні результати. Для запуску C++ версії було використано шар трансляції Wine, в той час коли C\# версія працює нативно, через це інформація про диски в C++ та C\# версії не співпадають.
|
||||
|
||||
Швидкодія обох версій відрізняється незначно, це можна пояснити тим, що обидві програми використовують системну API (WinAPI в випадку із Windows) для взаємодії із файловою системою.
|
||||
|
||||
== Висновки
|
||||
Під час виконання даної лабораторної роботи ми навчилися практичному використанню функцій WinAPI для роботи з файлами.
|